Springboot項目初始化集成搭建(一)

需求

從今天開始花一些時間來搭建springboot項目,構(gòu)建的需求

  • 初始化springboot的maven項目
  • 引入數(shù)據(jù)源連接mysql數(shù)據(jù)庫
  • 引入orm框架
  • 基礎配置
  • 引入分頁
  • 引入日志

構(gòu)建項目

image.png
  • 如你所見,項目里面基本沒有代碼耘子,除了幾個空目錄外,還包含如下幾樣東西吸耿。
    pom.xml:Maven構(gòu)建說明文件制妄。
    DemoApplication.java:一個帶有main()方法的類掸绞,用于啟動應用程序(關(guān)鍵)。
    DemoApplicationTests.java:一個空的Junit測試類,它加載了一個使用Spring Boot字典配置功能的Spring應用程序上下文衔掸。
    application.properties:一個空的properties文件烫幕,你可以根據(jù)需要添加配置屬性。

初始化代碼

創(chuàng)建TestController類敞映,添加如下代碼较曼。

@RestController
@EnableAutoConfiguration
public class TestController {

    @RequestMapping("/")
    public String test() {
        return "Hello world";
    }
}

啟動程序

在DemoApplication.java 文件點擊右鍵運行main方法(也可以另外一種啟動方式:mvn spring-boot:run -Dspring.profiles.active=dev),之后運行http://localhost:8080/就會看到 Hello world了振愿。

  • 注意一點:DemoApplication這個啟動類必須放在最外層捷犹,要不會抱一個錯誤Whitelabel Error Page,詳細解釋也可以看官網(wǎng)http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-structuring-your-code

代碼規(guī)范

接下來我們做一下代碼規(guī)范要求,以后都按照這種格式統(tǒng)一書寫冕末。

業(yè)務分層

  • domain層:實體類萍歉。
  • api層:對外接口。
  • service層:業(yè)務層档桃。
  • dao層:持久層枪孩。
  • Controller層:控制層。

pom文件配置

以下是基礎jar文件:

 <dependencies>
    <!-- base -->
    <dependency>
        <groupId>com.lulj</groupId>
        <artifactId>bruce-bean</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>

    <!-- spring boot start -->

    <!--核心模塊胳蛮,包括自動配置支持销凑、日志和YAM-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!--測試模塊,包括JUnit仅炊、Hamcrest斗幼、Mockito-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!--支持web的模塊-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--引用AOP-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    <!--啟動時啟動內(nèi)置tomcat -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>

    <!-- 集成log-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </dependency>


    <!-- MyBatis -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.1</version>
    </dependency>


    <!--mapper-->
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>1.2.4</version>
    </dependency>

    <!-- 熱部署,不用重啟 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>


    <!-- 添加freemarker依賴 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>


  <!-- spring boot end -->


    <!--spring2.0集成redis所需common-pool2-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.5.0</version>
    </dependency>

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.5</version>
    </dependency>

    <!-- 將作為Redis對象序列化器 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>

    <dependency>
        <groupId>net.sf.json-lib</groupId>
        <artifactId>json-lib</artifactId>
        <version>2.4</version>
        <classifier>jdk15</classifier>
    </dependency>


    <!-- MySql驅(qū)動 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!-- 集成druid抚垄,使用連接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.0</version>
    </dependency>

    <!-- lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.10</version>
    </dependency>

    <!--pagehelper-->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.2.3</version>
    </dependency>

    <dependency>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
    </dependency>

框架配置

在resources目錄下新建application.properties或者application.yml配置文件蜕窿,本文使用properties,添加如下配置:

#公共配置與profiles選擇無關(guān)
mybatis.typeAliasesPackage=com.example.demo.domain
mybatis.mapperLocations=classpath*:com/example/demo/dao/**/*Mapper.xml
configuration.cacheEnabled=true
configuration.useGeneratedKeys=true
configuration.defaultExecutorType=REUSE
configuration.log-imp=LOGBACK
#駝峰標識
configuration.mapUnderscoreToCamelCase=true
configuration.jdbcTypeForNull=NULL
#sql日志
logging.level.com.example.demo..dao=DEBUG
###########################################開發(fā)配置###########################################
#端口
server.port=8080
#項目名稱
server.servlet.context-path=/demo
#服務名稱
spring.application.name=demo

###mysql驅(qū)動配置信息
spring.datasource.url=jdbc:mysql://192.168.179.191:3306/wx?useUnicode=true&useSSL=false&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 連接池的配置信息
spring.datasource.filters=stat
spring.datasource.maxActive=20
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=select 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements=20

########分頁#######
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
pagehelper.offset-as-page-num=true
pagehelper.row-bounds-with-count=true

引入日志配置

SpringBoot 的日志文件放在resources目錄下呆馁,在resources目錄下新建logback.xml.

logback.xml配置及說明

   <?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2010-2011 The myBatis Team Licensed under the Apache License,
    Version 2.0 (the "License"); you may not use this file except in compliance
    with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software distributed
    under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
    OR CONDITIONS OF ANY KIND, either express or implied. See the License for
    the specific language governing permissions and limitations under the License. -->
<configuration>
    <contextName>demo</contextName>

    <property name="log.name" value="demo" />
    <property name="log.dir" value="../logs" />

    <appender name="FILEERROR"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.dir}/log_error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir}/error/${log.name}-error-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>[%date{ISO8601}] [%-5level] - [%thread] [%X{requestId}] [%logger] [%X{akkaSource}] - %msg
                %rootException %n
            </pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILEWARN"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.dir}/${log.name}_warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir}/warn/${log.name}-warn-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>[%date{ISO8601}] [%-5level] - [%thread] [%X{requestId}] [%logger] [%X{akkaSource}] - %msg
                %rootException %n
            </pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILEINFO"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.dir}/${log.name}_info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir}/info/${log.name}-info-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>[%date{ISO8601}] [%-5level] - [%thread] [%X{requestId}] [%logger] [%X{akkaSource}] - %msg
                %rootException %n
            </pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %black() %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight([%-5level]) %cyan([%X{requestId}]) %boldMagenta([%logger]) [%X{akkaSource}] - %cyan(%msg
                %rootException %n)
            </pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
    </appender>

    <logger name="org.springframework" level="WARN" />
    <logger name="org.hibernate" level="WARN" />

    <root level="INFO">
        <appender-ref ref="FILEERROR" />
        <appender-ref ref="FILEWARN" />
        <appender-ref ref="FILEINFO" />

        <!-- 生產(chǎn)環(huán)境將請stdout,testfile去掉 -->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

日志統(tǒng)一管理

@Aspect
@Order(-99)
@Configuration
@Slf4j
public class LogConfig {

    @Pointcut("execution(* com.example.demo.controller..*.*(..))," +
            "execution(* com.example.demo.api..*.*(..))")
    public void executionService() {

    }

    @Before(value = "executionService()")
    public void doBefore(JoinPoint joinPoint) {
        String requestId = String.valueOf(UUID.randomUUID());
        MDC.put("requestId", requestId);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        log.info("HTTP URL : " + request.getRequestURL().toString());
        log.info("HTTP METHOD : " + request.getMethod());
        log.info("IP : " + IPAddrUtil.localAddress());
        log.info("CLASS METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."
                + joinPoint.getSignature().getName());
        log.info("PARAMS : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(pointcut = "executionService()", returning = "returnValue")
    public void doAfterReturning(Object returnValue) {
        log.info("=====>@AfterReturning:The response parameter is:{}", returnValue);
        MDC.clear();
    }

    @Around("executionService()")
    public Object timeAround(ProceedingJoinPoint joinPoint) {
        long startTime = System.currentTimeMillis();
        Object obj = null;
        try {
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            log.error("=====>Counts the elapsed time of a method execution to surround notification errors:", e);
        }
        long endTime = System.currentTimeMillis();
        log.info("=====>Processing this request takes time:{} ms", endTime - startTime);
        return obj;
    }
}

說明

版權(quán)聲明:

本文為博主原創(chuàng)文章浙滤,轉(zhuǎn)載請附上原文出處鏈接和本聲明阴挣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者纺腊。
  • 序言:七十年代末畔咧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子揖膜,更是在濱河造成了極大的恐慌誓沸,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壹粟,死亡現(xiàn)場離奇詭異拜隧,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門洪添,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垦页,“玉大人,你說我怎么就攤上這事薇组⊥獗郏” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵律胀,是天一觀的道長宋光。 經(jīng)常有香客問我,道長炭菌,這世上最難降的妖魔是什么罪佳? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮黑低,結(jié)果婚禮上赘艳,老公的妹妹穿的比我還像新娘。我一直安慰自己克握,他們只是感情好蕾管,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著菩暗,像睡著了一般掰曾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上停团,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天旷坦,我揣著相機與錄音,去河邊找鬼佑稠。 笑死秒梅,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的舌胶。 我是一名探鬼主播捆蜀,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼幔嫂!你這毒婦竟也來了漱办?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤婉烟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后暇屋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體似袁,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了昙衅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扬霜。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖而涉,靈堂內(nèi)的尸體忽然破棺而出著瓶,到底是詐尸還是另有隱情,我是刑警寧澤啼县,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布材原,位于F島的核電站,受9級特大地震影響季眷,放射性物質(zhì)發(fā)生泄漏余蟹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一子刮、第九天 我趴在偏房一處隱蔽的房頂上張望威酒。 院中可真熱鬧,春花似錦挺峡、人聲如沸葵孤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尤仍。三九已至,卻和暖如春病线,著一層夾襖步出監(jiān)牢的瞬間吓著,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工送挑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绑莺,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓惕耕,卻偏偏與公主長得像纺裁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子司澎,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容