For XXFor XX

作为一个高手
我习惯了孤独

Kotlin服务端Spring Boot系列干货教程2 - 框架整合

框架整合,整合MyBatis/MyBatis-Plus、Log4j2、Generator代码生成、Druid连接池、Freemarker等

ChMkJlnJ4TOIAyeVAJqtjV-XTiAAAgzDAE7v40Amq2l708.jpg

1. pom.xml中引入相关jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.forxx.springboot4kt</groupId>
    <artifactId>springboot4kt</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>springboot4kt</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <kotlin.version>1.1.61</kotlin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jre8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--json-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.6</version>
        </dependency>
        <!--log4j2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!--用于log4j2日志的异步存储-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.3.7</version>
        </dependency>
        <!--mybatis-->
        <!--<dependency>-->
            <!--<groupId>org.mybatis.spring.boot</groupId>-->
            <!--<artifactId>mybatis-spring-boot-starter</artifactId>-->
            <!--<version>1.3.0</version>-->
        <!--</dependency>-->
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatisplus-spring-boot-starter</artifactId>
            <version>1.0.5</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>2.1.7</version>
        </dependency>
        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!--开启 cache 缓存-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- ehcache 缓存 -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <!--freemarker模板-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

    </dependencies>

    <build>
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>kotlin-maven-plugin</artifactId>
                <groupId>org.jetbrains.kotlin</groupId>
                <version>${kotlin.version}</version>
                <configuration>
                    <compilerPlugins>
                        <plugin>spring</plugin>
                    </compilerPlugins>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.5</version>
                <dependencies>
                    <dependency>
                        <groupId>com.kecikeci</groupId>
                        <artifactId>mybatis-generator-kecikeci</artifactId>
                        <version>1.0</version>
                        <scope>system</scope>
                        <systemPath>${project.basedir}/src/main/resources/mybatis-generator-kecikeci.jar</systemPath>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>


</project>

2. application.properties配置

## druid基础配置
spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/springboot4kt?useUnicode=true&characterEncoding=utf-8
spring.datasource.druid.username=root
spring.datasource.druid.password=root
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
## 连接池配置
spring.datasource.druid.initial-size=5
spring.datasource.druid.max-active=30
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-wait=60000
spring.datasource.druid.pool-prepared-statements=true
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
spring.datasource.druid.max-open-prepared-statements=20
spring.datasource.druid.validation-query=SELECT 1
spring.datasource.druid.validation-query-timeout=30000
spring.datasource.druid.test-on-borrow=true
spring.datasource.druid.test-on-return=false
spring.datasource.druid.test-while-idle=false
## 监控配置
spring.datasource.druid.filters=stat,wall,log4j2
spring.datasource.druid.web-stat-filter.enabled=true 
spring.datasource.druid.web-stat-filter.url-pattern=/druid/*
spring.datasource.druid.web-stat-filter.profile-enable=true
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
## StatViewServlet配置
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.reset-enable=true
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=forxx
## Spring监控配置
spring.datasource.druid.aop-patterns=me.forxx.springboot4kt.service..*(..),me.forxx.springboot4kt.web..*(..)
spring.aop.proxy-target-class=true

#log4j2
logging.config=classpath:log4j2.xml

#mybatis
#mybatis.type-aliases-package=me.forxx.springboot4kt.dao
#mybatis.mapperLocations=classpath:/mapper/*.xml
#mybatis和mybatis-plus 2选1
#mybatis-plus
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
mybatis-plus.type-aliases-package=me.forxx.springboot4kt.dao
#刷新mapper 调试神器
mybatis-plus.global-config.refresh-mapper=true

3. log4j2.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="OFF" debug="off" monitorInterval="1800">
    <Properties>
        <property name="LOG_HOME_ERROR">/data/logs/</property>
        <property name="FILE_NAME_ERROR">springboot4kt_logs_error</property>
        <property name="LOG_HOME_INFO">/data/logs/</property>
        <property name="FILE_NAME_INFO">springboot4kt_logs</property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 输出日志的格式 -->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>

        <RollingFile name="app_info" fileName="${LOG_HOME_INFO}/${FILE_NAME_INFO}.log" immediateFlush="false" filePattern="${LOG_HOME_INFO}/$${date:yyyy-MM}/${FILE_NAME_INFO}-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} %L %M - %msg%xEx%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="6" modulate="true" />
                <SizeBasedTriggeringPolicy size="50 MB"/>
            </Policies>
            <Filters>
                <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <DefaultRolloverStrategy max="50"/>
        </RollingFile>

        <RollingFile name="app_error" fileName="${LOG_HOME_ERROR}/${FILE_NAME_ERROR}.log" immediateFlush="false" filePattern="${LOG_HOME_ERROR}/$${date:yyyy-MM}/${FILE_NAME_ERROR}-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} %L %M - %msg%xEx%n" />
            <Policies>
                <TimeBasedTriggeringPolicy interval="6" modulate="true" />
                <SizeBasedTriggeringPolicy size="50 MB"/>
            </Policies>
            <Filters>
                <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <DefaultRolloverStrategy max="50"/>
        </RollingFile>

    </Appenders>
    <Loggers>
        <Logger name="org.springframework" level="error" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="app_error"/>
        </Logger>
        <Logger name="org.apache.ibatis" level="error" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="app_error"/>
        </Logger>
        <Logger name="org.mybatis" level="error" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="app_error"/>
        </Logger>
        <Logger name="me.forxx.springboot4kt" level="debug" additivity="false">
            <appender-ref ref="Console"/>
            <appender-ref ref="app_info"/>
        </Logger>
        <!-- AsyncRoot - 异步记录日志 - 需要LMAX Disruptor的支持 -->
        <AsyncRoot level="info" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="app_info"/>
            <AppenderRef ref="app_error"/>
        </AsyncRoot>

    </Loggers>
</configuration>

4. Springboot4ktApplication中开启自动配置注解

@SpringBootApplication
@EnableCaching
@MapperScan("me.forxx.springboot4kt.dao")
@EnableScheduling
class Springboot4ktApplication

fun main(args: Array<String>) {
    SpringApplication.run(Springboot4ktApplication::class.java, *args)
}

5. Aop日志记录类构建

package me.forxx.springboot4kt.aop;


import com.alibaba.fastjson.JSON;
import me.forxx.springboot4kt.util.Util;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * Created by GaoMingQiang on 2017/12/12 0019 11:19.
 */
@Component
@Aspect
public class Logs {

    private Logger log = LogManager.getLogger();
    @Autowired
    private HttpServletRequest res;

    @Before("execution(* me.forxx.springboot4kt.service..*(..)) || execution(* me.forxx.springboot4kt.web..*(..))")
    public void before(JoinPoint join){
        StringBuffer userName = new StringBuffer("游客");
        String ip = Util.getIp(res);
        String className = join.getTarget().getClass().getName();
        String function = join.getSignature().getName();
        String args = Arrays.asList(join.getArgs()).toString();
        StringBuffer msg = new StringBuffer();
        msg.append("当前用户 【");
        msg.append(userName);
        msg.append("】 IP 【");
        msg.append(ip);
        msg.append("】 正在访问 【类:<");
        msg.append(className);
        msg.append(">,方法:<");
        msg.append(function);
        msg.append(">,参数:<");
        msg.append(args);
        msg.append(">】");
        log.info(msg);
    }

    @AfterThrowing(pointcut="execution(* me.forxx.springboot4kt.service..*(..)) || execution(* me.forxx.springboot4kt.web..*(..))",throwing="e")
    public void exception(JoinPoint join, Exception e) {
        StringBuffer userName = new StringBuffer("游客");
        String ip = Util.getIp(res);
        String className = join.getTarget().getClass().getName();
        String function = join.getSignature().getName();
        String args = Arrays.asList(join.getArgs()).toString();
        StringBuffer msg = new StringBuffer();
        //记录报错内容
        StackTraceElement[] elems = e.getStackTrace();
        String text = "\n";
        for(StackTraceElement elem : elems) {
            text +=  "\t"+elem.toString()+"\n";
        }
        msg.append("当前用户 【");
        msg.append(userName);
        msg.append("】 IP 【");
        msg.append(ip);
        msg.append("】 正在访问 【类:<");
        msg.append(className);
        msg.append(">,方法:<");
        msg.append(function);
        msg.append(">,参数:<");
        msg.append(args);
        msg.append(">】 出现异常:【");
        msg.append(e.toString());
        msg.append("】 \n\t >> ------------------ 异常详情 -----------------<< \n");
        msg.append(text);
        log.error(msg);

        StringBuffer msgs = new StringBuffer();
        msgs.append("当前用户 【");
        msgs.append(userName);
        msgs.append("】 IP 【");
        msgs.append(ip);
        msgs.append("】 正在访问 【类:<");
        msgs.append(className);
        msgs.append(">,方法:<");
        msgs.append(function);
        msgs.append(">,参数:<");
        msgs.append(args);
        msgs.append(">】 出现异常:【");
        msgs.append(e.toString());
        msgs.append("】");
        log.info(msgs);
    }

    @AfterReturning(returning = "result",pointcut = "execution(* me.forxx.springboot4kt.service..*(..)) || execution(* me.forxx.springboot4kt.web..*(..))")
    public void After(JoinPoint join, Object result){
        StringBuffer userName = new StringBuffer("游客");
        String ip = Util.getIp(res);
        String className = join.getTarget().getClass().getName();
        String function = join.getSignature().getName();
        String args = JSON.toJSONString(result);
        StringBuffer msg = new StringBuffer();
        msg.append("当前用户 【");
        msg.append(userName);
        msg.append("】 IP 【");
        msg.append(ip);
        msg.append("】 返回结果 【类:<");
        msg.append(className);
        msg.append(">,方法:<");
        msg.append(function);
        msg.append(">,结果:<");
        msg.append(args);
        msg.append(">】");
        log.info(msg);
    }

}

QQ截图20171214150703.png


GitHub源码地址:https://github.com/kecikeci/springboot4kt

Gitee码云地址:https://gitee.com/kecikeci/springboot4kt

系列教程:https://4xx.me/tag/Kotin-Spring-Boot/

转载请注明出处:For XX » Kotlin服务端Spring Boot系列干货教程2 - 框架整合
标签:Kotlin Kotin+Spring Boot
分享到: 更多