Spring+mybatis+gradle 项目搭建实战-一步步搭建应用

本人博客:http://chen-shang.github.io
原文地址

saas 项目是一个给其他应用提供接口的项目,更偏重业务一点,主要是负责员工提交申请的信息的记录和状态的流转

使用到的工具

  1. 框架 -- 以 Spring 为主, Spring MVC 思想为辅
  2. 编程语言 -- 以 java 为主
  3. 项目构建工具 -- gradle
  4. 持久层框架 -- mybatis
  5. 版本控制工具 -- git
  6. 数据库 -- postgresql
  7. 脚本编程 -- shell
  8. IDE -- Intellij IDEA
  9. 容器 -- tomcat

搭建项目的前提是保证你的 jdk、gradle、git、postgresql 等都已经安装和配置完成,如下是我工具所对应的版本

chenshang@MrRobot-3:~$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
chenshang@MrRobot-3:~$ git --version 
git version 2.8.1
chenshang@MrRobot-3:~$ postgres --version
postgres (PostgreSQL) 9.6.2
chenshang@MrRobot-3:~$ gradle -v
------------------------------------------------------------
Gradle 3.2.1
------------------------------------------------------------
Build time:   2016-11-22 15:19:54 UTC
Revision:     83b485b914fd4f335ad0e66af9d14aad458d2cc5
Groovy:       2.4.7
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_121 (Oracle Corporation 25.121-b13)
OS:           Mac OS X 10.12.4 x86_64

由于是一个以 spring 框架为基础的项目,我们需要先集成 spring ,然后以此为基础一点一点盖楼。

新建 Gradle Java Web 项目

首先搭建一个 gradle 的 java web项目,然后添加 spring 依赖

打开 idea 在首页选择 Create New Project



点击 Next



如上图选择 Gradle 然后在右侧的窗口中勾选 Java 和 Web。这代表我将用 Gradle 新建一个 Java Web 项目。

点击 Next,在下一页为自己的应用起一个响亮而且文雅的名字(主要是写 GroupId、ArtifactId、Version)

GroupId:组 id,可以理解为你所属的项目组或公司的名称
ArtifactId:项目 id,可以理解为你项目的名称,Artifact是手工艺品的意思,引申为作品,代表你做的项目是你的作品

点击 Next


这里上面三个复选框可以选择性的勾选,第一个是自动 import(具体不知道是做什么的),第二个是创建项目的缺省目录,勾选后就可以在新建的项目中看到你熟悉的项目目录的结构如下

chenshang@bogon:~/Learn/spring/saas$ tree -L 3 src
src
├── main
│   ├── java
│   ├── resources
│   └── webapp
│       └── index.jsp
└── test
    ├── java
    └── resources

7 directories, 1 file

点击 Next 到下面这个页面



这里有个 Project name 让你填写工程名称,这个一般和你的项目名称也就是前面你定义的ArtifactId是相同的。其实这个 Project name 默认就是ArtifactId的名字,不用你做任何修改,只需在配置 Project Location 也就是你工程所在的目录即可,如果项目目录不存在 IEDA 会给你新建这个目录,之后你的项目目录结构和内容都应该在该目录下完成。

点击 Finish

等待 IDEA 的 Gradle 插件加载并解析完成项目后我们的 Gradle Java Web 项目就建好了。

还记得我们开始勾选了 Java 和 Web 两个选项吧,我们在 gradle.setting 文件中可以看到项目自动为我们添加了两个 gradle 插件 java 和 war。如果开始不勾选的话,这个配置文件就需要我们自己手动填写了。


建项目的方式多种多样,这里只是使用 IEDA 工具纯界面操作建立了一个简单的项目,其实最简单最理想的方式就是用工具只用点击就可以配置好项目,这样能省去繁琐的手工配置节省很多时间。
如果在第四步的时候没有勾选自动新建目录,那么新建的目录就是一个裸露的项目

chenshang@MrRobot-3:~/learn/spring/saas/src$ tree -L 3
.
└── main
    └── webapp
        └── index.jsp

2 directories, 1 file

这里推荐一款 Gradle 插件 gradle_templet,这是一款生成项目标准目录结构和类的插件,支持多种语言
只需要在 build.gradle 中添加下面

apply from: 'http://www.tellurianring.com/projects/gradle-plugins/gradle-templates/1.3/apply.groovy'

自己去发现其中的乐趣吧!

集成 spring

其实就是引用 spring 的 jar 包的过程

很简单在dependencies{}中添加

compile 'org.springframework:spring-webmvc:4.3.7.RELEASE'

该项目就会自动引入 spring 的依赖。至于怎么选择需要的 jar 包,这个真的就需要你去各种谷歌各种查资料了,因为第三方工具这种东西,只有你知道你才会去用,就像我搭建项目的时候我还不知道有 springboot 这种东西一些样我只能按照我以前的经验来搭建项目, 当我知道有 springboot这个工具的时候我就会发现其实集成第三方框架是多么的容易。

推荐一个搜索 jar 包的网站
http://search.maven.org/
以上项目就继承了 spring + spring MVC 了,我们写一个传统的项目来验证一下

首先在 src/java 目录中新建包,按照约定我们一般是公司域名的反写,我们这里就随便起名为 com.finhub.saas 吧

在com.finhub.saas这个包下,新建 controller/RootCtrl.class 文件

package com.finhub.saas.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by chenshang on 2017/4/8.
 */
@Controller
public class RootCtrl {
    @ResponseBody
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String test() {
        return "Hello world";
    }
}

在 web.xml 中添加 spring 的配置

  1. 一个是 contextConfigLocation
  2. 一个是 dispatcherServlet
    这里直接贴出我的配置项,其实 spring 的配置组合还有很多
 <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/applicationContext.xml</param-value>
 </context-param>
 <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring/dispatcherServlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
 </servlet-mapping>

spring 的配置文件统一放在 resources 目录下的 spring 目录中,resource 这个资源文件中主要放置各种配置文件以及自定义属性等文件的集合
webapp 则主要放置于 web 项目相关的东西如 css、js、html 等

这里要新建两个文件一个叫 applicationContext.xml,从名字上也可以看出来,这个是应用上下文的配置文件,主要用来存储 spring用到的 bean 配置,如果有些配置需要从其他 xml 文件中引入,可以用 import 来实现

新建resources/applicationContext

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven/>
    <context:component-scan base-package="com.finhub.saas.controller"/>
</beans>

新建resources/dispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--默认的注解映射支持:有了它,才能自动扫描各个包并注册到appplicationcontex的应用上下文中 -->
    <mvc:default-servlet-handler/>
    <mvc:resources location="/WEB-INF/fonts/" mapping="/fonts/**"/>
    <mvc:resources location="/WEB-INF/css/" mapping="/css/**"/>
    <mvc:resources location="/WEB-INF/img/" mapping="/img/**"/>
    <mvc:resources location="/WEB-INF/js/" mapping="/js/**"/>

    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    </bean>
</beans>

启动项目
访问 http://localhost:8080/hello

集成mybtais

这下要与数据库继承了,根据你选择的数据库应用相应数据库的驱动 jar 包。这里以 postgrsq 为例子,我引入相关依赖

    //=================>database jar<=============
    compile 'org.mongodb:bson:3.4.2'
    compile 'com.alibaba:druid:1.0.23'
    compile 'org.mybatis:mybatis:3.4.2'
    compile 'org.mybatis:mybatis-spring:1.3.1'
    compile 'org.postgresql:postgresql:9.4.1212.jre7'
    compile 'redis.clients:jedis:2.9.0'
    compile 'org.springframework.data:spring-data-redis:1.8.0.RELEASE'
    compile 'org.springframework:spring-orm:4.3.6.RELEASE'
    //=================>json jar<=================
    compile 'com.alibaba:fastjson:1.2.24'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.7.3'
    compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.7.3'
    //=================>others<===================
    compile 'javax.servlet:javax.servlet-api:3.1.0'
    compile 'jstl:jstl:1.2'
    compile 'joda-time:joda-time:2.9.7'
    compile 'org.apache.commons:commons-lang3:3.5'

新建 resources/jdbc/jdbc.properties

jdbc_driver=org.postgresql.Driver
jdbc_url=jdbc:postgresql://localhost:5432/saas
jdbc_username=postgres
jdbc_password=

新建 resources/spring-mybatis/spring-mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <value>classpath:jdbc/jdbc.properties</value>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
    </bean>
    <!-- ========================================针对spring-myBatis的配置项============================== -->
    <!-- 配置数据源,使用的是alibaba的Druid(德鲁伊)数据源 -->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc_driver}"/>
        <property name="url" value="${jdbc_url}"/>
        <property name="username" value="${jdbc_username}"/>
        <property name="password" value="${jdbc_password}"/>
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="0"/>
        <!-- 连接池最大使用连接数量 -->
        <property name="maxActive" value="20"/>
        <!-- 连接池最大空闲 -->
        <!--<property name="maxIdle" value="20"/>-->
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="0"/>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="60000"/>
        <!--
        <property name="poolPreparedStatements" value="true" />
        <property name="maxPoolPreparedStatementPerConnectionSize" value="33" />
        -->
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>
        <property name="testWhileIdle" value="true"/>
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="25200000"/>
        <!-- 打开removeAbandoned功能 -->
        <property name="removeAbandoned" value="true"/>
        <!-- 1800秒,也就是30分钟 -->
        <property name="removeAbandonedTimeout" value="1800"/>
        <!-- 关闭abanded连接时输出错误日志 -->
        <property name="logAbandoned" value="true"/>
        <!-- 监控数据库 -->
        <!-- <property name="filters" value="stat" /> -->
        <property name="filters" value="mergeStat"/>
    </bean>
    <!-- ========================================针对myBatis的配置项============================== -->
    <!-- ==============================配置sqlSessionFactory============================== -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
    </bean>
    <!-- ==============================配置扫描器============================== -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>-->
        <property name="basePackage" value="com.finhub.saas.dao"/>
    </bean>
    <!-- ==============================配置Spring的事务管理器============================== -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!-- ==============================拦截器方式配置事物============================== -->
    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="append*" propagation="REQUIRED"/>
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="modify*" propagation="REQUIRED"/>
            <tx:method name="edit*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="remove*" propagation="REQUIRED"/>
            <tx:method name="repair" propagation="REQUIRED"/>
            <tx:method name="delAndRepair" propagation="REQUIRED"/>

            <tx:method name="get*" propagation="SUPPORTS"/>
            <tx:method name="find*" propagation="SUPPORTS"/>
            <tx:method name="load*" propagation="SUPPORTS"/>
            <tx:method name="search*" propagation="SUPPORTS"/>
            <tx:method name="datagrid*" propagation="SUPPORTS"/>

            <tx:method name="*" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>

</beans>

这样 mybatis 和数据库也就集成好了
这样就可以愉快的开始写代码了

集成logback

上面已经添加好了依赖

新建 resources/logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_PATH" value="/logs/saas"/>
    <property name="LOG_FILE" value="saas"/>

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.SSS}] [%level] %logger:%line [%X{RID}] - %message%n%xException%n
            </pattern>
        </encoder>
    </appender>

    <!-- 文件输出 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${LOG_FILE}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${LOG_FILE}-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.SSS}] [%level] %logger:%line [%X{RID}] - %message%n%xException%n
            </pattern>
        </encoder>
    </appender>

    <!-- 文件输出_error -->
    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${LOG_FILE}-error.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${LOG_FILE}-error-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>[%d{yyyy-MM-dd'T'HH:mm:ss.SSS}] [%level] %logger:%line [%X{RID}] - %message%n%xException%n
            </pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="FILE"/>
        <appender-ref ref="FILE_ERROR"/>
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

MDC

统一的异常处理体系

over 可以愉快的玩耍了

彩蛋--敬请期待

  1. 后期会更新成多数据源的配置
  2. 还会讲解这个传统项目转战 springboot 项目
  3. 项目的版本控制策略
  4. 项目的部署控制策略
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容