Spring 5 + Spring MVC 5 + MyBatis 3 的 Maven 项目集成

相关链接:

MyEclipse CI 2018.9.0 配置 Apache Maven 3.5.4

在MyEclipse CI 2018.9.0 中使用 Maven 3.5.4 创建Maven项目

在MyEclipse中使用SVN提交(自动忽略 .settings .project .classpath等)、检出(无.settings .project .classpath文件等)Maven代码


  1. 配置Maven请查看:
    MyEclipse CI 2018.9.0 配置 Apache Maven 3.5.4
     
  2. 新建Maven项目请查看:
    在MyEclipse CI 2018.9.0 中使用 Maven 3.5.4 创建Maven项目
     
  3. 新建项目配置:

    Dynamic Web Module

    4.0

    Java

    1.8

    JavaScript

    1.0

    JSTL Libraries

    1.2.4

    MyEclipse Server Library

    Apache Tomcat v9.0

  4. 项目结构预览:



     
  5. 配置pom.xml:
    <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>net.csdn</groupId>
    	<artifactId>CSDN</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>war</packaging>
    	<name>CSDN</name>
    
    	<!-- 阿里云maven代码库 -->
    	<repositories>
    		<repository>
    			<id>aliyun</id>
    			<name>aliyun</name>
    			<url>http://maven.aliyun.com/nexus/content/groups/public</url>
    		</repository>
    	</repositories>
    	<!-- 阿里云maven代码库 -->
    
    	<properties>
    
    		<!-- Spring框架jar包版本 -->
    		<!-- 2018年7月26日 5.0.8.RELEASE 截止2018-09-06为最新版 -->
    		<spring.version>5.0.8.RELEASE</spring.version>
    
    		<!-- 启用@AspectJ支持 -->
    		<!-- 2018年4月20日 1.9.1 截止2018-09-06为最新版 -->
    		<aspectjweaver.version>1.9.1</aspectjweaver.version>
    
    		<!-- mchange c3p0 -->
    		<!-- 2015年12月9日 0.9.5.2 截止2018-09-06为最新版 -->
    		<c3p0.version>0.9.5.2</c3p0.version>
    		<!-- 2018年2月2日 0.2.15 截止2018-09-06为最新版 -->
    		<mchange-commons.version>0.2.15</mchange-commons.version>
    		<!-- mchange c3p0 -->
    
    		<!-- MyBatis -->
    		<!-- 2018年3月11日 3.4.6 截止2018-09-06为最新版 -->
    		<mybatis.version>3.4.6</mybatis.version>
    
    		<!-- MyBatis整合Spring中间件jar包 -->
    		<!-- 2018年3月14日 1.3.2 截止2018-09-06为最新版 -->
    		<mybatis-spring.version>1.3.2</mybatis-spring.version>
    
    		<!-- mysql 数据库驱动 -->
    		<!-- 2018年6月28日 8.0.12 截止2018-09-06为最新版 -->
    		<mysql-connector.version>8.0.12</mysql-connector.version>
    
    		<!-- log4j2 -->
    		<!-- 2018年7月30日 2.11.1 截止2018-09-06为最新版 -->
    		<log4j2.version>2.11.1</log4j2.version>
    
    		<!-- slf4j -->
    		<!-- 2017年3月16日 1.7.25 截止2018-09-06为最新版 -->
    		<slf4j.version>1.7.25</slf4j.version>
    
    		<!-- commons-lang3 -->
    		<!-- 2018年8月16日 3.8 截止2018-09-06为最新版 -->
    		<!-- 工具类 -->
    		<commons-lang3.version>3.8</commons-lang3.version>
    
    		<!-- commons-text -->
    		<!-- 工具类 -->
    		<!-- 2018年6月9日 截止2018-09-06为最新版 -->
    		<commons-text.version>1.4</commons-text.version>
    
    		<!-- springfox -->
    		<!-- 2018年6月23日 2.9.2 截止2018-09-06为最新版 -->
    		<springfox-swagger2.version>2.9.2</springfox-swagger2.version>
    
    		<!-- javax/servlet/jsp/jstl/core/Config -->
    		<!-- 2006年5月12日 1.2 -->
    		<jstl.version>1.2</jstl.version>
    
    		<!-- jetty-webapp -->
    		<!-- 2018年8月30日 9.4.12.v20180830 截止2018-09-06为最新版 -->
    		<jetty-webapp.version>9.4.12.v20180830</jetty-webapp.version>
    
    		<!-- gson -->
    		<!-- 2018年5月22日 2.8.5 截止2018-09-06为最新版 -->
    		<gson.version>2.8.5</gson.version>
    
    		<!-- json -->
    		<!-- 还需要commons-lang,已被引入 -->
    		<commons-beanutils.version>1.9.3</commons-beanutils.version>
    		<commons-collections.version>3.2.2</commons-collections.version>
    		<commons-logging.version>1.2</commons-logging.version>
    		<ezmorph.version>1.0.6</ezmorph.version>
    		<json.version>2.4</json.version>
    
    		<!-- github验证码 -->
    		<patchca.version>0.0.1</patchca.version>
    
    	</properties>
    
    	<dependencies>
    
    		<!-- ++++++++++++++++++++++++++++++ spring、spring mvc ++++++++++++++++++++ -->
    
    		<!-- spring 视图解析器 5.0.8.RELEASE -->
    		<!-- 相关依赖(自动引入5.0.8.RELEASE): spring-aop-、spring-beans-、spring-context-、spring-core-、spring-expression-、spring-jcl-、spring-web- -->
    		<!-- 同spring-websocket -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-webmvc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- spring JDBC事务管理器 5.0.8.RELEASE -->
    		<!-- 相关依赖(自动引入5.0.8.RELEASE):spring-beans、spring-core、spring-jcl、spring-tx -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-jdbc</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- 相关依赖(自动引入5.0.8.RELEASE):spring-aop、spring-beans、spring-context、spring-core、spring-expression、spring-jcl、spring-web、 -->
    		<!-- 同spring-webmvc -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-websocket</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    		<!-- 相关依赖(自动引入5.0.8.RELEASE):spring-beans-、spring-core-、spring-jcl- -->
    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-messaging</artifactId>
    			<version>${spring.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ aspectjweaver ++++++++++++++++++++ -->
    
    		<!-- aspectjweaver -->
    		<dependency>
    			<groupId>org.aspectj</groupId>
    			<artifactId>aspectjweaver</artifactId>
    			<version>${aspectjweaver.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ c3p0 ++++++++++++++++++++ -->
    
    		<!-- c3p0 -->
    		<!-- mchange c3p0 0.9.5.2 -->
    		<!-- 相关依赖(自动引入0.2.11):mchange-commons-java- -->
    		<dependency>
    			<groupId>com.mchange</groupId>
    			<artifactId>c3p0</artifactId>
    			<version>${c3p0.version}</version>
    		</dependency>
    
    		<!-- mchange commons -->
    		<dependency>
    			<groupId>com.mchange</groupId>
    			<artifactId>mchange-commons-java</artifactId>
    			<version>${mchange-commons.version}</version>
    		</dependency>
    		<!-- c3p0 -->
    
    		<!-- ++++++++++++++++++++++++++++++ mybatis ++++++++++++++++++++ -->
    
    		<!-- MyBatis -->
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis</artifactId>
    			<version>${mybatis.version}</version>
    		</dependency>
    
    
    		<!-- ++++++++++++++++++++++++++++++ mybatis-spring ++++++++++++++++++++ -->
    
    		<!-- MyBatis整合Spring中间件jar包 -->
    		<dependency>
    			<groupId>org.mybatis</groupId>
    			<artifactId>mybatis-spring</artifactId>
    			<version>${mybatis-spring.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ mysql ++++++++++++++++++++ -->
    
    		<!-- mysql 数据库驱动 8.0.12 -->
    		<!-- 相关依赖(自动引入2.6.0):protobuf-java- -->
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<version>${mysql-connector.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ log4j2 ++++++++++++++++++++ -->
    
    		<!-- log4j2 2.11.1 -->
    		<!-- 相关依赖(自动引入2.11.1):log4j-core、log4j-api -->
    		<dependency>
    			<groupId>org.apache.logging.log4j</groupId>
    			<artifactId>log4j-web</artifactId>
    			<version>${log4j2.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ slf4j ++++++++++++++++++++ -->
    
    		<!-- slf4j -->
    		<!-- 相关依赖(自动引入1.2.17):log4j- -->
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-log4j12</artifactId>
    			<version>${slf4j.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>org.slf4j</groupId>
    			<artifactId>slf4j-api</artifactId>
    			<version>${slf4j.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ commons-lang3 ++++++++++++++++++++ -->
    
    		<!-- commons-lang3 -->
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-lang3</artifactId>
    			<version>${commons-lang3.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ commons-text ++++++++++++++++++++ -->
    
    		<!-- commons-text -->
    		<dependency>
    			<groupId>org.apache.commons</groupId>
    			<artifactId>commons-text</artifactId>
    			<version>${commons-text.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ springfox ++++++++++++++++++++ -->
    
    		<!-- springfox -->
    		<!-- 2018年6月23日 -->
    		<!-- aopalliance-1.0.jar -->
    		<!-- byte-buddy-1.8.12.jar -->
    		<!-- classmate-1.4.0.jar -->
    		<!-- guava-20.0.jar -->
    		<!-- jackson-annotations-2.9.5.jar -->
    		<!-- mapstruct-1.2.0.Final.jar -->
    		<!-- slf4j-api-1.7.25.jar -->
    		<!-- 版本4.0.9.RELEASE:spring-aop-、spring-beans-、spring-context-、spring-core-、spring-expression- -->
    		<!-- 版本2.9.2:springfox-core-、springfox-schema-、springfox-spi-、springfox-spring-web-、springfox-swagger2- 
    			、springfox-swagger-common- -->
    		<!-- 版本1.2.0.RELEASE:spring-plugin-core-、spring-plugin-metadata- -->
    		<!-- 版本1.5.20:swagger-annotations-、 swagger-models- -->
    		<dependency>
    			<groupId>io.springfox</groupId>
    			<artifactId>springfox-swagger2</artifactId>
    			<version>${springfox-swagger2.version}</version>
    		</dependency>
    
    		<!-- aopalliance-1.0.jar -->
    		<!-- byte-buddy-1.8.12.jar -->
    		<!-- guava-20.0.jar -->
    		<!-- slf4j-api-1.7.25.jar -->
    		<!-- 版本4.0.9.RELEASE:spring-aop-、spring-beans-、spring-context-、spring-core-、spring-expression- -->
    		<!-- 版本2.9.2:springfox-core-、springfox-spi-、springfox-spring-web- -->
    		<!-- 版本1.2.0.RELEASE:spring-plugin-core-、spring-plugin-metadata- -->
    		<dependency>
    			<groupId>io.springfox</groupId>
    			<artifactId>springfox-swagger-ui</artifactId>
    			<version>${springfox-swagger2.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ jstl ++++++++++++++++++++ -->
    
    		<!-- javax/servlet/jsp/jstl/core/Config -->
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>jstl</artifactId>
    			<version>${jstl.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ jetty-webapp ++++++++++++++++++++ -->
    
    		<!-- -->
    		<!-- javax.servlet-api-3.1.0.jar -->
    		<!-- 版本9.4.12.v20180830:jetty-http-、jetty-io-、jetty-security-、jetty-server-、jetty-servlet-、jetty-util-、jetty-xml- -->
    		<dependency>
    			<groupId>org.eclipse.jetty</groupId>
    			<artifactId>jetty-webapp</artifactId>
    			<version>${jetty-webapp.version}</version>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ gson ++++++++++++++++++++ -->
    
    		<!-- gson -->
    		<dependency>
    			<groupId>com.google.code.gson</groupId>
    			<artifactId>gson</artifactId>
    			<version>${gson.version}</version>
    		</dependency>
    
    
    		<!-- ++++++++++++++++++++++++++++++ json ++++++++++++++++++++ -->
    
    		<dependency>
    			<groupId>commons-beanutils</groupId>
    			<artifactId>commons-beanutils</artifactId>
    			<version>${commons-beanutils.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>commons-collections</groupId>
    			<artifactId>commons-collections</artifactId>
    			<version>${commons-collections.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>commons-logging</groupId>
    			<artifactId>commons-logging</artifactId>
    			<version>${commons-logging.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>net.sf.ezmorph</groupId>
    			<artifactId>ezmorph</artifactId>
    			<version>${ezmorph.version}</version>
    		</dependency>
    
    		<dependency>
    			<groupId>net.sf.json-lib</groupId>
    			<artifactId>json-lib</artifactId>
    			<version>${json.version}</version>
    			<classifier>jdk15</classifier>
    		</dependency>
    
    		<!-- ++++++++++++++++++++++++++++++ github验证码 ++++++++++++++++++++ -->
    
    		<dependency>
    			<groupId>com.github.bingoohuang</groupId>
    			<artifactId>patchca</artifactId>
    			<version>${patchca.version}</version>
    		</dependency>
    		<!-- <dependency> <groupId>net.pusuo</groupId> <artifactId>patchca</artifactId> 
    			<version>0.5.0</version> </dependency> -->
    
    		<!-- ++++++++++++++++++++++++++++++ ++++++++++++++++++++ -->
    
    	</dependencies>
    
    	<build>
    		<plugins>
    
    			<!-- 配置Tomcat插件 -->
    			<plugin>
    				<groupId>org.apache.tomcat.maven</groupId>
    				<artifactId>tomcat7-maven-plugin</artifactId>
    				<configuration>
    					<port>80</port>
    					<path>/CSDN</path>
    					<url>http://192.168.1.100:80/manager/text</url>
    					<username>tomcat</username>
    					<password>tomcat</password>
    				</configuration>
    			</plugin>
    			<!-- 配置Tomcat插件 -->
    
    			<!-- 默认 jdk 1.8 -->
    			<plugin>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<configuration>
    					<source>1.8</source>
    					<target>1.8</target>
    				</configuration>
    			</plugin>
    			<!-- 默认 jdk 1.8 -->
    
    		</plugins>
    	</build>
    
    </project>
  6. 配置web.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    	id="WebApp_ID" version="4.0">
    	<display-name>CSDN</display-name>
    
    	<!-- 方便的Web应用程序的ApplicationContext实例化 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/5.0.8.RELEASE/spring-framework-reference/core.html#context-create -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:spring-context.xml</param-value>
    	</context-param>
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	<!-- 方便的Web应用程序的ApplicationContext实例化 -->
    
    	<!-- DispatcherServlet -->
    	<!-- 定义Spring MVC的前端控制器 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet -->
    	<servlet>
    		<servlet-name>springmvc</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:spring-mvc.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<!-- 让Spring MVC的前端控制器拦截所有请求 -->
    	<servlet-mapping>
    		<servlet-name>springmvc</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    
    	<!-- 静态资源不拦截 -->
    	<servlet-mapping>
    		<servlet-name>default</servlet-name>
    		<url-pattern>*.js</url-pattern>
    		<url-pattern>*.css</url-pattern>
    		<url-pattern>*.gif</url-pattern>
    		<url-pattern>*.jpg</url-pattern>
    		<url-pattern>*.png</url-pattern>
    		<url-pattern>*.ico</url-pattern>
    		<url-pattern>*.mp3</url-pattern>
    		<url-pattern>*.woff</url-pattern>
    		<url-pattern>*.json</url-pattern>
    	</servlet-mapping>
    
    	<!-- DispatcherServlet -->
    
    	<!-- log4j2配置 -->
    	<!-- 参见:http://logging.apache.org/log4j/2.x/manual/webapp.html -->
    	<context-param>
    		<param-name>log4jConfiguration</param-name>
    		<param-value>classpath:log4j2.xml</param-value>
    	</context-param>
    	<listener>
    		<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
    	</listener>
    
    	<filter>
    		<filter-name>log4jServletFilter</filter-name>
    		<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>log4jServletFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    		<dispatcher>REQUEST</dispatcher>
    		<dispatcher>FORWARD</dispatcher>
    		<dispatcher>INCLUDE</dispatcher>
    		<dispatcher>ERROR</dispatcher>
    		<!-- <dispatcher>ASYNC</dispatcher> -->
    		<!-- Servlet 3.0仅禁用自动初始化; 2.5不支持 -->
    	</filter-mapping>
    
    	<!-- github验证码 -->
    	<!-- 直接访问http://127.0.0.1/CSDN/validImg.jpg即可得到验证码,不受SSM控制 -->
    	<servlet>
    		<servlet-name>ValidCode</servlet-name>
    		<servlet-class>net.csdn.servlet.ValidCode</servlet-class>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>ValidCode</servlet-name>
    		<url-pattern>/validImg.jpg</url-pattern>
    	</servlet-mapping>
    
    	<!-- 404页面 -->
    	<!-- <error-page> <error-code>404</error-code> <location>/WEB-INF/error/404.html</location> 
    		</error-page> -->
    
    	<!-- 500页面 -->
    	<!-- <error-page> <error-code>500</error-code> <location>/WEB-INF/error/500.html</location> 
    		</error-page> -->
    
    
    	<!-- <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> 
    		<welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> 
    		<welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> 
    		</welcome-file-list> -->
    
    </web-app>
  7. 配置jdbc.properties:
    # 在mysql-connector-java-8.0.12中已经被启用	com.mysql.jdbc.Driver
    # 在mysql-connector-java-8.0.12中使用		com.mysql.cj.jdbc.Driver
    # useSSL\=false 							不验证SSL
    # serverTimezone\=GMT%2B8					设置时区为东8区
    dataSource.driverClass=com.mysql.cj.jdbc.Driver
    dataSource.jdbcUrl=jdbc\:mysql\://127.0.0.1\:3306/csdn?useSSL\=false&serverTimezone\=GMT%2B8
    dataSource.user=root
    dataSource.password=root
    dataSource.maxPoolSize=20
    dataSource.maxIdleTime = 1000
    dataSource.minPoolSize=5
    dataSource.initialPoolSize=5
  8. 配置log4j.properties:
    log4j.rootLogger=info,stdout
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=[\u65F6\u95F4\:%d{yyyy-MM-dd hh\:mm\:ss}] [\u7EA7\u522B\:%p] [\u7C7B\:%c]  [\u6D88\u606F\:%m] %n 
    
    #log4j.logger.com.ibatis=debug
    #log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
    #log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
    #log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
    #log4j.logger.java.sql.Connection=debug
    #log4j.logger.java.sql.Statement=debug
    #log4j.logger.java.sql.PreparedStatement=debug,stdout
    
    # Spring Stuff
    #log4j.logger.org.springframework=INFO
    #log4j.logger.org.springframework.oxm=INFO
    #log4j.logger.org.springframework.web=debug
    
    log4j.logger.net.csdn.aop.aspect.SystemLogAspect=debug
    
  9. 配置log4j2.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xml>
    <Configuration status="OFF" monitorInterval="1800">
    
    	<properties>
    		<!-- log打印到本地的路径 -->
    		<property name="LOG_HOME">/log4j2/mybatis/genertor/logs/</property>
    		<property name="ERROR_LOG_FILE_NAME">error</property>
    	</properties>
    
    	<Appenders>
    
    		<!-- 控制台打印日志 -->
    		<Console name="Console" target="SYSTEM_OUT">
    			<PatternLayout pattern="%d %-5p (%F:%L) - %m%n" />
    		</Console>
    
    		<!-- 日志信息输出到文件配置 -->
    		<RollingRandomAccessFile name="ErrorLog"
    			fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log"
    			filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.log.gz">
    			<PatternLayout pattern="%d %-5p (%F:%L) - %m%n" />
    			<Policies>
    
    				<!-- TimeBasedTriggeringPolicy指定的size是1,结合起来就是1天生成一个新文件。 -->
    				<!-- 如果filePattern改成%d{yyyy-MM-dd HH}.gz,此时最小粒度为小时,则每一个小时生成一个文件。 -->
    
    				<TimeBasedTriggeringPolicy />
    
    				<!-- 指定当文件体积大于size指定的值时,触发Rolling -->
    				<SizeBasedTriggeringPolicy size="100 MB" />
    			</Policies>
    
    			<!-- 指定最多保存的文件个数 -->
    			<DefaultRolloverStrategy max="20" />
    
    		</RollingRandomAccessFile>
    
    	</Appenders>
    
    	<Loggers>
    
    		<root level="info" includeLocation="true">
    			<appender-ref ref="ErrorLog" />
    			<appender-ref ref="Console" />
    		</root>
    
    	</Loggers>
    
    </Configuration>
    
  10. 配置mybatis-config.xml:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    
    	<!-- 使用log4j2打印查询语句 -->
    	<settings>
    
    		<!-- <setting name="logImpl" value="LOG4J2" /> -->
    
    		<!-- 打印查询语句 -->
    		<setting name="logImpl" value="STDOUT_LOGGING" />
    	</settings>
    
    	<typeAliases>
    		<package name="net.csdn" />
    	</typeAliases>
    
    	<plugins>
    		<!-- 拦截器配置 -->
    		<plugin interceptor="net.csdn.util.sql.SqlCostInterceptor" />
    	</plugins>
    
    </configuration>
  11. 配置spring-context.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:aop="http://www.springframework.org/schema/aop"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    				        http://www.springframework.org/schema/beans/spring-beans.xsd
    				        http://www.springframework.org/schema/aop 
    				        http://www.springframework.org/schema/aop/spring-aop.xsd
    				        http://www.springframework.org/schema/context
            				http://www.springframework.org/schema/context/spring-context.xsd
            				http://www.springframework.org/schema/tx
    			            http://www.springframework.org/schema/tx/spring-tx.xsd
            				http://mybatis.org/schema/mybatis-spring
    			            http://mybatis.org/schema/mybatis-spring.xsd">
    
    
    
    	<!-- mybatis:scan会将 net.csdn.mapper 包里的所有接口当作mapper配置,之后可以自动引入mapper接口 -->
    	<!-- 多包用英文逗号隔开,如:<mybatis:scan base-package="net.csdn.mapper,com.baidu.mapper" 
    		/> -->
    	<!-- 参见:http://www.mybatis.org/spring/mappers.html -->
    	<mybatis:scan base-package="net.csdn.mapper" />
    
    	<!-- 自动检测类并注册bean定义 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-scanning-autodetection -->
    	<!-- 多包用英文逗号隔开,如:<mybatis:scan base-package="net.csdn,com.baidu" /> -->
    	<context:component-scan base-package="net.csdn" />
    
    	<!-- 使用BeanFactoryPostProcessor定制配置元数据 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factory-postprocessors -->
    	<context:property-override
    		location="classpath:jdbc.properties" />
    
    	<!-- 配置c3p0数据源 -->
    	<!-- 参见:https://www.mchange.com/projects/c3p0/ -->
    	<bean id="dataSource"
    		class="com.mchange.v2.c3p0.ComboPooledDataSource" />
    
    	<!-- 配置SqlSessionFactory,org.mybatis.spring.SqlSessionFactoryBean是Mybatis社区开发用于整合Spring的bean -->
    	<!-- 在基本的 MyBatis 中,session 工厂可以使用 SqlSessionFactoryBuilder 来创建。而在 MyBatis-Spring 
    		中,则使用 SqlSessionFactoryBean 来替代。 -->
    	<!-- 参见:http://www.mybatis.org/spring/zh/factorybean.html -->
    	<bean id="sqlSessionFactory"
    		class="org.mybatis.spring.SqlSessionFactoryBean">
    		<property name="dataSource" ref="dataSource" />
    		<property name="mapperLocations">
    			<array>
    				<!-- 扫描xml文件、可填写多个<value>值:如 <value>classpath:net/csdn/mapping/*.xml</value> 
    					<value>classpath:com/baidu/mapping/*.xml</value> -->
    				<!-- value中不可有空格:org.apache.ibatis.binding.BindingException: Invalid 
    					bound statement (not found): -->
    				<value>classpath:net/csdn/mapping/*.xml</value>
    			</array>
    		</property>
    
    		<!-- 读取MyBatis配置文件的位置,SQL日志输出 -->
    		<property name="configLocation"
    			value="classpath:mybatis-config.xml" />
    
    	</bean>
    
    	<!-- 声明性事务实现的示例 -->
    	<!--参见: https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-first-example -->
    	<bean id="transactionManager"
    		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource" />
    	</bean>
    
    	<!-- 启用支持annotation注解方式事务管理 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-annotations -->
    	<tx:annotation-driven
    		transaction-manager="transactionManager" />
    
    
    
    	<!-- 扫描切点类组件 -->
    	<context:component-scan
    		base-package="net.csdn.aop.aspect" />
    	<!-- <context:component-scan base-package="net.csdn.service" /> -->
    
    	<!-- 未知配置 -->
    	<bean id="taskExecutor"
    		class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    		<property name="corePoolSize" value="5" />
    		<property name="maxPoolSize" value="10" />
    		<!-- <property name="WaitForTasksToCompleteOnShutdown" value="true" /> -->
    	</bean>
    
    
    	<!-- bean定义 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/5.0.8.RELEASE/spring-framework-reference/core.html#beans-factory-instantiation -->
    
    </beans>
  12. 配置spring-mvc.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:aop="http://www.springframework.org/schema/aop"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
    	xmlns:websocket="http://www.springframework.org/schema/websocket"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    				        http://www.springframework.org/schema/beans/spring-beans.xsd
    				        http://www.springframework.org/schema/aop 
    				        http://www.springframework.org/schema/aop/spring-aop.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
            				http://www.springframework.org/schema/websocket
            				http://www.springframework.org/schema/websocket/spring-websocket.xsd">
    
    	<!-- 自动扫描该包,SpringMVC会将包下用了@controller注解的类注册为Spring的controller -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-stereotype-annotations -->
    	<!-- 多个 controller 用英文逗号隔开,如:<context:component-scan base-package="net.csdn.controller,com.baidu.controller" 
    		/> -->
    	<context:component-scan
    		base-package="net.csdn.controller" />
    
    	<!-- 启用MVC注解 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-config-enable -->
    	<mvc:annotation-driven>
    		<mvc:message-converters
    			register-defaults="true">
    			<bean
    				class="org.springframework.http.converter.StringHttpMessageConverter">
    				<property name="supportedMediaTypes">
    					<list>
    						<!-- json乱码处理 -->
    						<value>application/json; charset=UTF-8</value>
    					</list>
    				</property>
    			</bean>
    		</mvc:message-converters>
    	</mvc:annotation-driven>
    
    	<!-- 默认Servlet -->
    	<!-- 使用默认的Servlet来响应静态文件 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-default-servlet-handler -->
    	<mvc:default-servlet-handler />
    
    	<!-- 查看解析器 -->
    	<!-- 视图解析器 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-view-jsp-resolver -->
    	<bean id="viewResolver"
    		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<property name="viewClass"
    			value="org.springframework.web.servlet.view.JstlView" />
    		<property name="prefix" value="/WEB-INF/content/" />
    		<!-- <property name="suffix" value=".jsp" /> -->
    	</bean>
    
    	<!-- 使用XML配置启用@AspectJ支持 -->
    	<!-- 参见:https://docs.spring.io/spring/docs/5.0.8.RELEASE/spring-framework-reference/core.html#aop -->
    	<aop:aspectj-autoproxy />
    
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#websocket-server-handshake -->
    	<!-- <websocket:handlers> <websocket:mapping path="/myHandler" handler="myHandler" 
    		/> <websocket:handshake-interceptors> <bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor" 
    		/> </websocket:handshake-interceptors> </websocket:handlers> <bean id="myHandler" 
    		class="net.csdn.websocket.MyHandler" /> -->
    
    	<!-- 参见:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#websocket-server-runtime-configuration -->
    	<!-- 通过该类即可在普通工具类里获取spring管理的bean -->
    	<bean class="net.csdn.spring.SpringTool" />
    
    	<!-- 配置拦截器 -->
    	<mvc:interceptors>
    
    		<!-- admin 拦截器 -->
    		<mvc:interceptor>
    			<!-- 拦截所有url -->
    			<mvc:mapping path="/**" />
    			<!-- 不拦截url -->
    			<mvc:exclude-mapping path="/index.html" />
    			<bean class="net.csdn.handlerInterceptor.CSDNHandlerInterceptor"></bean>
    		</mvc:interceptor>
    
    	</mvc:interceptors>
    
    </beans>

    至此已配置完成。

     
  13. SQL:
    /*
     Navicat Premium Data Transfer
    
     Source Server         : 127.0.0.1
     Source Server Type    : MySQL
     Source Server Version : 50720
     Source Host           : 127.0.0.1:3306
     Source Schema         : csdn
    
     Target Server Type    : MySQL
     Target Server Version : 50720
     File Encoding         : 65001
    
     Date: 30/10/2018 15:34:47
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for test_log
    -- ----------------------------
    DROP TABLE IF EXISTS `test_log`;
    CREATE TABLE `test_log`  (
      `logId` int(11) NOT NULL AUTO_INCREMENT COMMENT '日志主键',
      `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '日志类型',
      `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '日志标题',
      `remoteAddr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求地址',
      `requestUri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'URI',
      `method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求方式',
      `params` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '提交参数',
      `exception` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '异常',
      `operateDate` datetime(0) DEFAULT NULL COMMENT '开始时间',
      `timeout` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束时间',
      `userId` int(11) DEFAULT NULL COMMENT '用户ID',
      PRIMARY KEY (`logId`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of test_log
    -- ----------------------------
    INSERT INTO `test_log` VALUES (1, 'info', '访问测试首页', '127.0.0.1', '/CSDN/test/aop/index.do', 'GET', '', NULL, '2018-10-30 15:16:39', '0:0:0.20', NULL);
    INSERT INTO `test_log` VALUES (2, 'info', '访问测试登录', '127.0.0.1', '/CSDN/test/aop/login.do', 'GET', 'username=xuxiaowei&password=', NULL, '2018-10-30 15:16:51', '0:0:0.71', 1);
    INSERT INTO `test_log` VALUES (3, 'info', '访问测试首页', '127.0.0.1', '/CSDN/test/aop/index.do', 'GET', '', NULL, '2018-10-30 15:17:25', '0:0:0.0', 1);
    INSERT INTO `test_log` VALUES (4, 'info', '访问测试首页', '127.0.0.1', '/CSDN/test/aop/index.do', 'GET', '', NULL, '2018-10-30 15:21:26', '0:0:0.27', NULL);
    INSERT INTO `test_log` VALUES (5, 'info', '访问测试登录', '127.0.0.1', '/CSDN/test/aop/login.do', 'GET', 'username=xuxiaowei&password=', NULL, '2018-10-30 15:21:28', '0:0:0.69', 1);
    INSERT INTO `test_log` VALUES (6, 'error', '异常测试', '127.0.0.1', '/CSDN/test/aop/err.do', 'GET', '', 'java.lang.ArithmeticException: / by zero', '2018-10-30 15:21:47', '0:0:0.0', 1);
    
    -- ----------------------------
    -- Table structure for test_user
    -- ----------------------------
    DROP TABLE IF EXISTS `test_user`;
    CREATE TABLE `test_user`  (
      `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '工号',
      `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '账号',
      `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
      `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码',
      `sex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '性别',
      `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '邮箱',
      `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '手机',
      `locked` tinyint(4) DEFAULT NULL COMMENT '是否被锁定',
      `organizationId` int(11) DEFAULT NULL COMMENT '部门ID仅用户接受参数',
      `loginIp` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '最后登入IP',
      `loginDate` datetime(0) DEFAULT NULL COMMENT '最后登入日期',
      `photo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '头像',
      `oldLoginIp` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上次登入IP',
      `oldLoginDate` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上次登入日期',
      `createBy` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建者ID',
      `updateBy` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新者ID',
      `createDate` datetime(0) DEFAULT NULL COMMENT '创建日期',
      `updateDate` datetime(0) DEFAULT NULL COMMENT '更新日期',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of test_user
    -- ----------------------------
    INSERT INTO `test_user` VALUES (1, 'xuxiaowei', NULL, '123456', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    
    SET FOREIGN_KEY_CHECKS = 1;
    
  14. 测试日志:

     
  15. 相关类:
    以下类均为测试使用,可在上面的配置中删除。
    1. net.csdn.aop.annotation.TestSystemControllerLog:
      系统日志切片相关,自定义注解,拦截Controller,用于记操作日志:
      package net.csdn.aop.annotation;
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      /**
       * 自定义注解 拦截Controller
       * 
       * @author xuxiaowei
       *
       */
      @Target({ ElementType.PARAMETER, ElementType.METHOD })
      @Retention(RetentionPolicy.RUNTIME)
      public @interface TestSystemControllerLog {
      
      	/**
      	 * 获取描述description
      	 * 
      	 * @SystemControllerLog(description = "登入系统")
      	 * 
      	 * @return
      	 */
      	String description() default "";
      
      }
      
    2. net.csdn.aop.aspect.TestSystemLogAspect:
      系统日志切点类:
      package net.csdn.aop.aspect;
      
      import java.lang.reflect.Method;
      import java.text.SimpleDateFormat;
      import java.util.Date;
      import java.util.Map;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpSession;
      
      import org.aspectj.lang.JoinPoint;
      import org.aspectj.lang.annotation.After;
      import org.aspectj.lang.annotation.AfterThrowing;
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Before;
      import org.aspectj.lang.annotation.Pointcut;
      import org.aspectj.lang.reflect.MethodSignature;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.core.NamedThreadLocal;
      import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
      import org.springframework.stereotype.Component;
      
      //import com.layui.test.entity.TestLog;
      //import com.layui.test.entity.TestUser;
      //import com.layui.test.service.TestLogService;
      //import com.layui.test.util.UuidUtils;
      
      import net.csdn.aop.annotation.TestSystemControllerLog;
      import net.csdn.entity.TestLog;
      import net.csdn.entity.TestUser;
      import net.csdn.service.TestLogService;
      import net.csdn.util.date.DateUtils;
      import net.csdn.util.string.StringUtils;
      
      /**
       * 系统日志切点类
       * 
       * @author xuxiaowei
       *
       */
      @Aspect
      @Component
      public class TestSystemLogAspect {
      
      	/**
      	 * 
      	 */
      	private static final Logger logger = LoggerFactory.getLogger(TestSystemLogAspect.class);
      
      	/**
      	 * 本地线程开始时间
      	 */
      	private static final ThreadLocal<Date> beginTimeThreadLocal = new NamedThreadLocal<Date>("ThreadLocal beginTime");
      
      	/**
      	 * 本地线程日志
      	 */
      	private static final ThreadLocal<TestLog> logThreadLocal = new NamedThreadLocal<TestLog>("ThreadLocal log");
      
      	/**
      	 * 当前用户
      	 */
      	private static final ThreadLocal<TestUser> currentUser = new NamedThreadLocal<>("ThreadLocal user");
      
      	/**
      	 * 全局变量,同一个请求
      	 */
      	@Autowired(required = false)
      	private HttpServletRequest request;
      
      	/**
      	 * 线程池任务执行程序
      	 */
      	@Autowired
      	private ThreadPoolTaskExecutor threadPoolTaskExecutor;
      
      	/**
      	 * 日志储存service
      	 */
      	@Autowired
      	private TestLogService logService;
      
      //	/**
      //	 * Service层切点
      //	 */
      //	@Pointcut("@annotation(cn.wimcn.test.annotation.SystemServiceLog)")
      //	public void serviceAspect() {
      //		System.out.println("+++++++++++++Service层切点+++++++++++++");
      //	}
      
      	/**
      	 * Controller层切点 注解拦截
      	 */
      	@Pointcut("@annotation(net.csdn.aop.annotation.TestSystemControllerLog)")
      	public void testControllerAspect() {
      		System.out.println("+++++++++++++Controller层切点 注解拦截+++++++++++++");
      	}
      
      	/**
      	 * 方法规则拦截
      	 */
      	@Pointcut("execution(* net.csdn.controller.*.*(..))")
      	public void controllerPointerCut() {
      		logger.debug("+++++++++++++方法规则拦截+++++++++++++");
      	}
      
      	/**
      	 * 前置通知 用于拦截Controller层记录用户的操作的开始时间
      	 * 
      	 * @param joinPoint 切点
      	 * @throws InterruptedException
      	 */
      	@Before("testControllerAspect()")
      	public void doBefore(JoinPoint joinPoint) throws InterruptedException {
      
      		Date beginTime = new Date();
      
      		// 设置本地线程开始时间
      		beginTimeThreadLocal.set(beginTime);
      
      		// debug模式下 显式打印开始时间用于调试
      		// 在log4j中开启本类的debug
      
      		if (logger.isDebugEnabled()) {
      			logger.debug("开始计时: {}  URI: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(beginTime),
      					request.getRequestURI());
      		}
      
      		// 读取session中的用户
      		HttpSession session = request.getSession();
      		TestUser user = (TestUser) session.getAttribute("ims_user");
      		currentUser.set(user);
      
      	}
      
      	/**
      	 * 后置通知 用于拦截Controller层记录用户的操作
      	 * 
      	 * @param joinPoint 切点
      	 */
      	@After("testControllerAspect()")
      	public void doAfter(JoinPoint joinPoint) {
      
      		TestUser user = currentUser.get();
      
      		// 登入login操作 前置通知时用户未校验 所以session中不存在用户信息
      		if (user == null) {
      			HttpSession session = request.getSession();
      			user = (TestUser) session.getAttribute("ims_user");
      			if (user == null) {
      				user = new TestUser();
      			}
      		}
      
      		Object[] args = joinPoint.getArgs();
      		System.out.println("joinPoint-args:" + args.toString());
      
      		String title = "";
      		String type = "info"; // 日志类型(info:入库,error:错误)
      		String remoteAddr = request.getRemoteAddr();// 请求的IP
      		String requestUri = request.getRequestURI();// 请求的Uri
      		String method = request.getMethod(); // 请求的方法类型(post/get)
      		Map<String, String[]> params = request.getParameterMap(); // 请求提交的参数
      
      		try {
      			title = getControllerMethodDescription2(joinPoint);
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      
      		// debu模式下打印JVM信息。
      		long beginTime = beginTimeThreadLocal.get().getTime();// 得到线程绑定的局部变量(开始时间)
      		long endTime = System.currentTimeMillis(); // 2、结束时间
      
      		if (logger.isDebugEnabled()) {
      			logger.debug("计时结束:{}  URI: {}  耗时: {}   最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m",
      					new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(endTime), request.getRequestURI(),
      					DateUtils.formatDateTime(endTime - beginTime), Runtime.getRuntime().maxMemory() / 1024 / 1024,
      					Runtime.getRuntime().totalMemory() / 1024 / 1024, Runtime.getRuntime().freeMemory() / 1024 / 1024,
      					(Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory()
      							+ Runtime.getRuntime().freeMemory()) / 1024 / 1024);
      		}
      
      		TestLog testLog = new TestLog();
      //		testLog.setLogid(UuidUtils.creatUUID());
      		testLog.setTitle(title);
      		testLog.setType(type);
      		testLog.setRemoteAddr(remoteAddr);
      		testLog.setRequestUri(requestUri);
      		testLog.setMethod(method);
      		testLog.setParams(StringUtils.getMapToParams(params));
      //		testLog.setUserid(user.getId());
      		testLog.setUserId(user.getId());
      		Date operateDate = beginTimeThreadLocal.get();
      		testLog.setOperateDate(operateDate);
      		testLog.setTimeout(DateUtils.formatDateTime(endTime - beginTime));
      
      		// 1.直接执行保存操作
      		// this.logService.createSystemLog(log);
      
      		// 2.优化:异步保存日志
      		// new SaveLogThread(log, logService).start();
      
      		// 3.再优化:通过线程池来执行日志保存
      		threadPoolTaskExecutor.execute(new SaveLogThread(testLog, logService));
      		logThreadLocal.set(testLog);
      
      	}
      
      	/**
      	 * 异常通知
      	 * 
      	 * @param joinPoint
      	 * @param e
      	 */
      	@AfterThrowing(pointcut = "testControllerAspect()", throwing = "e")
      	public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
      
      		TestLog testLog = logThreadLocal.get();
      
      		if (testLog != null) {
      			testLog.setType("error");
      			testLog.setException(e.toString());
      			new UpdateLogThread(testLog, logService).start();
      		}
      	}
      
      	/**
      	 * 获取注解中对方法的描述信息 用于Controller层注解
      	 * 
      	 * @param joinPoint 切点
      	 * @return 方法描述
      	 */
      	public static String getControllerMethodDescription2(JoinPoint joinPoint) {
      
      		/**
      		 * Returns the signature at the join point. 返回连接点处的签名。
      		 * getStaticPart().getSignature() returns the same object 返回相同的对象
      		 */
      		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      
      		Method method = signature.getMethod();
      
      		TestSystemControllerLog controllerLog = method.getAnnotation(TestSystemControllerLog.class);
      
      		String discription = controllerLog.description();
      
      		return discription;
      	}
      
      	/**
      	 * 保存日志线程
      	 * 
      	 * @author xuxiaowei
      	 *
      	 */
      	private static class SaveLogThread implements Runnable {
      		private TestLog testLog;
      		private TestLogService testLogService;
      
      		public SaveLogThread(TestLog testLog, TestLogService testLogService) {
      			this.testLog = testLog;
      			this.testLogService = testLogService;
      		}
      
      		@Override
      		public void run() {
      			testLogService.insert(testLog);
      		}
      	}
      
      	/**
      	 * 日志更新线程
      	 * 
      	 * @author xuxiaowei
      	 *
      	 */
      	private static class UpdateLogThread extends Thread {
      		private TestLog testLog;
      		private TestLogService logService;
      
      		public UpdateLogThread(TestLog testLog, TestLogService logService) {
      			super(UpdateLogThread.class.getSimpleName());
      			this.testLog = testLog;
      			this.logService = logService;
      		}
      
      		@Override
      		public void run() {
      			this.logService.updateByPrimaryKeySelective(testLog);
      		}
      	}
      }
      
    3. net.csdn.controller.TestAopController:
      测试Controller:
      package net.csdn.controller;
      
      import java.util.List;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.RequestMapping;
      
      import io.swagger.annotations.Api;
      import io.swagger.annotations.ApiOperation;
      import net.csdn.aop.annotation.TestSystemControllerLog;
      import net.csdn.entity.TestUser;
      import net.csdn.entity.TestUserExample;
      import net.csdn.entity.TestUserExample.Criteria;
      import net.csdn.service.TestUserService;
      
      /**
       * 测试AOP
       * 
       * @author xuxiaowei
       *
       */
      @Api(value = "/test", tags = "系统登入接口")
      @Controller
      @RequestMapping("/test/aop")
      public class TestAopController {
      
      	private static final Logger logger = LoggerFactory.getLogger(TestAopController.class);
      
      	@Autowired
      	private TestUserService testUserService;
      
      	/**
      	 * 测试主页
      	 * 
      	 * @param request
      	 * @param response
      	 * @return
      	 */
      	@TestSystemControllerLog(description = "访问测试首页")
      	@RequestMapping("/index.do")
      	public String test(HttpServletRequest request, HttpServletResponse response) {
      
      		System.out.println("/index.do");
      
      		logger.info("{} 访问测试首页", "xxx");
      
      		return "test/aop/index.jsp";
      	}
      
      	/**
      	 * 测试登录方法
      	 * 
      	 * @param request
      	 * @param response
      	 * @param test
      	 * @param model
      	 * @return
      	 */
      	@ApiOperation(value = "登入系统", notes = "登入系统", httpMethod = "POST")
      	@TestSystemControllerLog(description = "访问测试登录")
      	@RequestMapping("/login.do")
      	public String login(HttpServletRequest request, HttpServletResponse response, TestUser testUser, Model model) {
      
      		System.out.println("/login.do");
      
      		String username2 = testUser.getUsername();
      		String password2 = testUser.getPassword();
      
      		System.out.println(username2);
      		System.out.println(password2);
      
      		TestUserExample testUserExample = new TestUserExample();
      		Criteria createCriteria = testUserExample.createCriteria();
      
      		createCriteria.andUsernameEqualTo(username2);
      		createCriteria.andPasswordEqualTo(password2);
      
      		List<TestUser> testUsers = testUserService.selectByExample(testUserExample);
      
      		HttpSession session = request.getSession();
      
      		if (testUsers.size() > 0) {
      			logger.info("{} 登入系统成功!", username2);
      
      			String string = testUsers.toString();
      
      			System.out.println(string);
      
      			model.addAttribute("string", string);
      
      			session.setAttribute("ims_user", testUsers.get(0));
      
      		} else {
      			logger.info("{} 登入系统失败!", username2);
      		}
      
      		return "test/aop/main.jsp";
      	}
      
      	@TestSystemControllerLog(description = "异常测试")
      	@RequestMapping("/err.do")
      	public String err(HttpServletRequest request, HttpServletResponse response) {
      
      		System.out.println("/err.do");
      
      		logger.info("{} 访问页面异常测试", "xxx");
      
      		int i = 5 / 0;
      
      		System.out.println(i);
      
      		return "test/aop/index.jsp";
      	}
      }
      
    4. net.csdn.handlerInterceptor.CSDNHandlerInterceptor:
      拦截器:
      package net.csdn.handlerInterceptor;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      import org.springframework.web.servlet.HandlerInterceptor;
      import org.springframework.web.servlet.ModelAndView;
      
      /**
       * 
       * @author xuxiaowei
       *
       */
      public class CSDNHandlerInterceptor implements HandlerInterceptor {
      
      	@Override
      	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
      			ModelAndView modelAndView) throws Exception {
      		// TODO Auto-generated method stub
      		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
      	}
      
      	@Override
      	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      			throws Exception {
      		// TODO Auto-generated method stub
      		return HandlerInterceptor.super.preHandle(request, response, handler);
      	}
      
      	@Override
      	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      			throws Exception {
      		// TODO Auto-generated method stub
      		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
      	}
      
      }
      
    5. 实体类相关,自动生成:


       
    6. 工具类:用于生成entity、mapper、mapping、service、serviceImpl:

       
    7. net.csdn.servlet.ValidCode:
      验证码生成器:
      package net.csdn.servlet;
      
      import java.awt.Color;
      import java.io.IOException;
      import java.util.Random;
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      
      import com.github.bingoohuang.patchca.color.ColorFactory;
      import com.github.bingoohuang.patchca.custom.ConfigurableCaptchaService;
      import com.github.bingoohuang.patchca.filter.predefined.CurvesRippleFilterFactory;
      import com.github.bingoohuang.patchca.filter.predefined.DiffuseRippleFilterFactory;
      import com.github.bingoohuang.patchca.filter.predefined.DoubleRippleFilterFactory;
      import com.github.bingoohuang.patchca.filter.predefined.MarbleRippleFilterFactory;
      import com.github.bingoohuang.patchca.filter.predefined.WobbleRippleFilterFactory;
      import com.github.bingoohuang.patchca.font.RandomFontFactory;
      import com.github.bingoohuang.patchca.utils.encoder.EncoderHelper;
      import com.github.bingoohuang.patchca.word.RandomWordFactory;
      
      /**
       * github验证码
       * 
       * @author xuxiaowei
       *
       */
      public class ValidCode extends HttpServlet {
      
      	/**
      	 * 
      	 */
      	private static final long serialVersionUID = 1L;
      
      	private static ConfigurableCaptchaService cs = new ConfigurableCaptchaService();
      
      	private static Random random = new Random();
      
      	static {
      //        cs.setColorFactory(new SingleColorFactory(new Color(25, 60, 170)));
      
      		cs.setColorFactory(new ColorFactory() {
      			@Override
      			public Color getColor(int x) {
      				int[] c = new int[3];
      				int i = random.nextInt(c.length);
      				for (int fi = 0; fi < c.length; fi++) {
      					if (fi == i) {
      						c[fi] = random.nextInt(71);
      					} else {
      						c[fi] = random.nextInt(256);
      					}
      				}
      				return new Color(c[0], c[1], c[2]);
      			}
      		});
      
      		RandomWordFactory randomWordFactory = new RandomWordFactory();
      
      		// 字符范围
      		randomWordFactory.setCharacters("23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ");
      
      		// 字符数量范围
      		randomWordFactory.setMaxLength(5);
      		randomWordFactory.setMinLength(3);
      		cs.setWordFactory(randomWordFactory);
      
      		// 图片像素
      		cs.setHeight(40);
      		cs.setWidth(130);
      
      		// 字体大小范围
      		RandomFontFactory randomFontFactory = new RandomFontFactory();
      		randomFontFactory.setMaxSize(40);
      		randomFontFactory.setMinSize(30);
      		cs.setFontFactory(randomFontFactory);
      
      	}
      
      	@Override
      	protected void doGet(HttpServletRequest request, HttpServletResponse response)
      			throws ServletException, IOException {
      		switch (random.nextInt(5)) {
      		case 0:
      			cs.setFilterFactory(new CurvesRippleFilterFactory(cs.getColorFactory()));
      			break;
      		case 1:
      			cs.setFilterFactory(new MarbleRippleFilterFactory());
      			break;
      		case 2:
      			cs.setFilterFactory(new DoubleRippleFilterFactory());
      			break;
      		case 3:
      			cs.setFilterFactory(new WobbleRippleFilterFactory());
      			break;
      		case 4:
      			cs.setFilterFactory(new DiffuseRippleFilterFactory());
      			break;
      		}
      
      		HttpSession session = request.getSession();
      		session = request.getSession();
      
      		setResponseHeaders(response);
      		String token = EncoderHelper.getChallangeAndWriteImage(cs, "png", response.getOutputStream());
      
      		session.setAttribute("verifyCode", token);
      
      	}
      
      	protected void setResponseHeaders(HttpServletResponse response) {
      		response.setContentType("image/png");
      		response.setHeader("Cache-Control", "no-cache, no-store");
      		response.setHeader("Pragma", "no-cache");
      		long time = System.currentTimeMillis();
      		response.setDateHeader("Last-Modified", time);
      		response.setDateHeader("Date", time);
      		response.setDateHeader("Expires", time);
      	}
      
      	@Override
      	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		super.doPost(req, resp);
      	}
      
      }
    8. net.csdn.spring.SpringTool:
      通过该类即可在普通工具类里获取spring管理的bean:
      package net.csdn.spring;
      
      import org.springframework.beans.BeansException;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.ApplicationContextAware;
      
      /**
       * 通过该类即可在普通工具类里获取spring管理的bean
       * 
       * @author xuxiaowei
       * 
       */
      public final class SpringTool implements ApplicationContextAware {
      	private static ApplicationContext applicationContext = null;
      
      	@Override
      	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      		if (SpringTool.applicationContext == null) {
      			SpringTool.applicationContext = applicationContext;
      
      			System.out.println();
      
      			System.out.println("========" + "ApplicationContext配置成功,"
      					+ "在普通类可以通过调用ToolSpring.getAppContext()获取applicationContext对象," + "applicationContext="
      					+ applicationContext + "========");
      
      			System.out.println();
      		}
      	}
      
      	/**
      	 * 
      	 * @return
      	 */
      	public static ApplicationContext getApplicationContext() {
      		return applicationContext;
      	}
      
      	/**
      	 * 获取been
      	 * 
      	 * @param serviceName
      	 * @return
      	 */
      	public static Object getBean(String serviceName) {
      		return getApplicationContext().getBean(serviceName);
      	}
      }
    9. net.csdn.util.sql.SqlCostInterceptor:
      Sql执行时间记录拦截器:
      package net.csdn.util.sql;
      
      import java.sql.Statement;
      import java.util.Properties;
      
      import org.apache.ibatis.executor.statement.StatementHandler;
      import org.apache.ibatis.plugin.Interceptor;
      import org.apache.ibatis.plugin.Intercepts;
      import org.apache.ibatis.plugin.Invocation;
      import org.apache.ibatis.plugin.Plugin;
      import org.apache.ibatis.plugin.Signature;
      import org.apache.ibatis.session.ResultHandler;
      
      /**
       * Sql执行时间记录拦截器
       * 
       * @author xuxiaowei
       *
       */
      @Intercepts({
      		@Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class }),
      		@Signature(type = StatementHandler.class, method = "update", args = { Statement.class }),
      		@Signature(type = StatementHandler.class, method = "batch", args = { Statement.class }) })
      public class SqlCostInterceptor implements Interceptor {
      
      	@Override
      	public Object intercept(Invocation invocation) throws Throwable {
      
      		long startTime = System.currentTimeMillis();
      
      		try {
      			return invocation.proceed();
      		} finally {
      			long endTime = System.currentTimeMillis();
      			long sqlCost = endTime - startTime;
      			System.out.println("执行SQL耗时 : [" + sqlCost + "ms ] ");
      		}
      	}
      
      	@Override
      	public Object plugin(Object target) {
      		return Plugin.wrap(target, this);
      	}
      
      	@Override
      	public void setProperties(Properties properties) {
      
      	}
      
      }
      
    10. net.csdn.util.string.StringUtils:
      字符串工具类:
      package net.csdn.util.string;
      
      import java.io.UnsupportedEncodingException;
      import java.util.Map;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      import javax.servlet.http.HttpServletRequest;
      
      //deprecated as of 3.6, use commons-text
      //从3.6开始弃用,使用commons-text
      //import org.apache.commons.lang3.StringEscapeUtils;
      //commons-text-1.4.jar
      import org.apache.commons.text.StringEscapeUtils;
      
      /**
       * 字符串工具类
       * 
       * 继承org.apache.commons.lang3.StringUtils类
       * 
       * @author xuxiaowei
       * 
       */
      public class StringUtils extends org.apache.commons.lang3.StringUtils {
      
      	private static final char SEPARATOR = '_';
      	private static final String CHARSET_NAME = "UTF-8";
      
      	/**
      	 * 首字母小写
      	 * 
      	 * @param string
      	 * @return
      	 */
      	public static String lowerFirst(String string) {
      
      		char[] cs = string.toCharArray();
      
      		cs[0] += 32;
      
      		String valueOf = String.valueOf(cs);
      
      		return valueOf;
      	}
      
      	/**
      	 * 转换为字节数组
      	 * 
      	 * @param str
      	 * @return
      	 */
      	public static byte[] getBytes(String str) {
      
      		if (str != null) {
      			try {
      				return str.getBytes(CHARSET_NAME);
      			} catch (UnsupportedEncodingException e) {
      				return null;
      			}
      		} else {
      			return null;
      		}
      	}
      
      	/**
      	 * 转换为字节数组
      	 * 
      	 * @param str
      	 * @return
      	 */
      	public static String toString(byte[] bytes) {
      		try {
      			return new String(bytes, CHARSET_NAME);
      		} catch (UnsupportedEncodingException e) {
      			return EMPTY;
      		}
      	}
      
      	/**
      	 * 是否包含字符串
      	 * 
      	 * @param str  验证字符串
      	 * @param strs 字符串组
      	 * @return 包含返回true
      	 */
      	public static boolean inString(String str, String... strs) {
      		if (str != null) {
      			for (String s : strs) {
      				if (str.equals(trim(s))) {
      					return true;
      				}
      			}
      		}
      		return false;
      	}
      
      	/**
      	 * 替换掉HTML标签方法
      	 * 
      	 * @param html
      	 * @return
      	 */
      	public static String replaceHtml(String html) {
      		if (isBlank(html)) {
      			return "";
      		}
      		String regEx = "<.+?>";
      		Pattern p = Pattern.compile(regEx);
      		Matcher m = p.matcher(html);
      		String s = m.replaceAll("");
      		return s;
      	}
      
      	/**
      	 * 替换为手机识别的HTML,去掉样式及属性,保留回车。
      	 * 
      	 * @param html
      	 * @return
      	 */
      	public static String replaceMobileHtml(String html) {
      		if (html == null) {
      			return "";
      		}
      		return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
      	}
      
      //	/**
      //	 * 替换为手机识别的HTML,去掉样式及属性,保留回车。
      //	 * 
      //	 * @param txt
      //	 * @return
      //	 */
      //	public static String toHtml(String txt) {
      //		if (txt == null) {
      //			return "";
      //		}
      //		return replace(replace(Encodes.escapeHtml(txt), "\n", "<br/>"), "\t", "&nbsp; &nbsp; ");
      //	}
      
      	/**
      	 * 缩略字符串(不区分中英文字符)
      	 * 
      	 * @param str    目标字符串
      	 * @param length 截取长度
      	 * @return
      	 */
      	public static String abbr(String str, int length) {
      		if (str == null) {
      			return "";
      		}
      		try {
      			StringBuilder sb = new StringBuilder();
      			int currentLength = 0;
      			for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
      				currentLength += String.valueOf(c).getBytes("GBK").length;
      				if (currentLength <= length - 3) {
      					sb.append(c);
      				} else {
      					sb.append("...");
      					break;
      				}
      			}
      			return sb.toString();
      		} catch (UnsupportedEncodingException e) {
      			e.printStackTrace();
      		}
      		return "";
      	}
      
      	/**
      	 * 转换为Double类型
      	 * 
      	 * @param val
      	 * @return
      	 */
      	public static Double toDouble(Object val) {
      		if (val == null) {
      			return 0D;
      		}
      		try {
      			return Double.valueOf(trim(val.toString()));
      		} catch (Exception e) {
      			return 0D;
      		}
      	}
      
      	/**
      	 * 转换为Float类型
      	 * 
      	 * @param val
      	 * @return
      	 */
      	public static Float toFloat(Object val) {
      		return toDouble(val).floatValue();
      	}
      
      	/**
      	 * 转换为Long类型
      	 * 
      	 * @param val
      	 * @return
      	 */
      	public static Long toLong(Object val) {
      		return toDouble(val).longValue();
      	}
      
      	/**
      	 * 转换为Integer类型
      	 * 
      	 * @param val
      	 * @return
      	 */
      	public static Integer toInteger(Object val) {
      		return toLong(val).intValue();
      	}
      
      //	/**
      //	 * 获得i18n字符串
      //	 * 
      //	 * @param code
      //	 * @param args
      //	 * @return
      //	 */
      //	public static String getMessage(String code, Object[] args) {
      //		LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class);
      //		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
      //				.getRequest();
      //		Locale localLocale = localLocaleResolver.resolveLocale(request);
      //		return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale);
      //	}
      
      	/**
      	 * 获得用户远程地址
      	 * 
      	 * @param request
      	 * @return
      	 */
      	public static String getRemoteAddr(HttpServletRequest request) {
      		String remoteAddr = request.getHeader("X-Real-IP");
      		if (isNotBlank(remoteAddr)) {
      			remoteAddr = request.getHeader("X-Forwarded-For");
      		} else if (isNotBlank(remoteAddr)) {
      			remoteAddr = request.getHeader("Proxy-Client-IP");
      		} else if (isNotBlank(remoteAddr)) {
      			remoteAddr = request.getHeader("WL-Proxy-Client-IP");
      		}
      		return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
      	}
      
      	/**
      	 * 驼峰命名法工具
      	 * 
      	 * toCamelCase("hello_world") == "helloWorld"
      	 * toCapitalizeCamelCase("hello_world") == "HelloWorld"
      	 * toUnderScoreCase("helloWorld") = "hello_world"
      	 * 
      	 * @param s
      	 * @return
      	 */
      	public static String toCamelCase(String s) {
      		if (s == null) {
      			return null;
      		}
      
      		s = s.toLowerCase();
      
      		StringBuilder sb = new StringBuilder(s.length());
      		boolean upperCase = false;
      		for (int i = 0; i < s.length(); i++) {
      			char c = s.charAt(i);
      
      			if (c == SEPARATOR) {
      				upperCase = true;
      			} else if (upperCase) {
      				sb.append(Character.toUpperCase(c));
      				upperCase = false;
      			} else {
      				sb.append(c);
      			}
      		}
      
      		return sb.toString();
      	}
      
      	/**
      	 * 驼峰命名法工具
      	 * 
      	 * toCamelCase("hello_world") == "helloWorld"
      	 * toCapitalizeCamelCase("hello_world") == "HelloWorld"
      	 * toUnderScoreCase("helloWorld") = "hello_world"
      	 * 
      	 * @param s
      	 * @return
      	 */
      	public static String toCapitalizeCamelCase(String s) {
      		if (s == null) {
      			return null;
      		}
      		s = toCamelCase(s);
      		return s.substring(0, 1).toUpperCase() + s.substring(1);
      	}
      
      	/**
      	 * 驼峰命名法工具
      	 * 
      	 * toCamelCase("hello_world") == "helloWorld"
      	 * toCapitalizeCamelCase("hello_world") == "HelloWorld"
      	 * toUnderScoreCase("helloWorld") = "hello_world"
      	 * 
      	 * @param s
      	 * @return
      	 */
      	public static String toUnderScoreCase(String s) {
      		if (s == null) {
      			return null;
      		}
      
      		StringBuilder sb = new StringBuilder();
      		boolean upperCase = false;
      		for (int i = 0; i < s.length(); i++) {
      			char c = s.charAt(i);
      
      			boolean nextUpperCase = true;
      
      			if (i < (s.length() - 1)) {
      				nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
      			}
      
      			if ((i > 0) && Character.isUpperCase(c)) {
      				if (!upperCase || !nextUpperCase) {
      					sb.append(SEPARATOR);
      				}
      				upperCase = true;
      			} else {
      				upperCase = false;
      			}
      
      			sb.append(Character.toLowerCase(c));
      		}
      
      		return sb.toString();
      	}
      
      	/**
      	 * 驼峰转下划线 (暂不建议使用toUnderScoreCase)
      	 * 
      	 * @param camelCaseName
      	 * @return
      	 */
      	public static String toUnderscoreName(String camelCaseName) {
      		StringBuilder result = new StringBuilder();
      		if (camelCaseName != null && camelCaseName.length() > 0) {
      			result.append(camelCaseName.substring(0, 1).toLowerCase());
      			for (int i = 1; i < camelCaseName.length(); i++) {
      				char ch = camelCaseName.charAt(i);
      				if (Character.isUpperCase(ch)) {
      					result.append("_");
      					result.append(Character.toLowerCase(ch));
      				} else {
      					result.append(ch);
      				}
      			}
      		}
      		return result.toString();
      	}
      
      	/**
      	 * 如果不为空,则设置值
      	 * 
      	 * @param target
      	 * @param source
      	 */
      	public static void setValueIfNotBlank(String target, String source) {
      		if (isNotBlank(source)) {
      			target = source;
      		}
      	}
      
      	/**
      	 * 转换为JS获取对象值,生成三目运算返回结果
      	 * 
      	 * 例如:row.user.id
      	 * 
      	 * 返回:!row?'':!row.user?'':!row.user.id?'':row.user.id
      	 * 
      	 * @param objectString 对象串
      	 */
      	public static String jsGetVal(String objectString) {
      		StringBuilder result = new StringBuilder();
      		StringBuilder val = new StringBuilder();
      		String[] vals = split(objectString, ".");
      		for (int i = 0; i < vals.length; i++) {
      			val.append("." + vals[i]);
      			result.append("!" + (val.substring(1)) + "?'':");
      		}
      		result.append(val.substring(1));
      		return result.toString();
      	}
      
      	/**
      	 * 转换为utf-8字符串
      	 * 
      	 * @param s
      	 * @return
      	 */
      	public static String toUtf8String(String s) {
      		StringBuffer sb = new StringBuffer();
      		for (int i = 0; i < s.length(); i++) {
      			char c = s.charAt(i);
      			if (c >= 0 && c <= 255) {
      				sb.append(c);
      			} else {
      				byte[] b;
      				try {
      					b = Character.toString(c).getBytes("utf-8");
      				} catch (Exception ex) {
      					b = new byte[0];
      				}
      				for (int j = 0; j < b.length; j++) {
      					int k = b[j];
      					if (k < 0)
      						k += 256;
      					sb.append("%" + Integer.toHexString(k).toUpperCase());
      				}
      			}
      		}
      		return sb.toString();
      	}
      
      	/**
      	 * 
      	 * Map<String, String[]> 转 String
      	 * 
      	 * @param paramMap
      	 * @return
      	 */
      	public static String getMapToParams(Map<String, String[]> paramMap) {
      		if (paramMap == null) {
      			return "";
      		}
      		StringBuilder params = new StringBuilder();
      		for (Map.Entry<String, String[]> param : ((Map<String, String[]>) paramMap).entrySet()) {
      			params.append(("".equals(params.toString()) ? "" : "&") + param.getKey() + "=");
      			String paramValue = (param.getValue() != null && param.getValue().length > 0 ? param.getValue()[0] : "");
      			params.append(StringUtils.abbr(StringUtils.endsWithIgnoreCase(param.getKey(), "password") ? "" : paramValue,
      					100));
      		}
      		return params.toString();
      	}
      
      }
      
    11. net.csdn.util.date.DateUtils:
      日期工具类:
      package net.csdn.util.date;
      
      import java.text.ParseException;
      import java.util.Date;
      
      import org.apache.commons.lang3.time.DateFormatUtils;
      
      /**
       * 日期工具类
       * 
       * 继承org.apache.commons.lang3.time.DateUtils类
       * 
       * @author xuxiaowei
       * 
       */
      public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
      
      	private static String[] parsePatterns = { "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss",
      			"yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy.MM.dd HH:mm", "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd",
      			"yyyy-MM", "yyyy/MM", "yyyy.MM" };
      
      	/**
      	 * 得到当前日期字符串 格式(yyyy-MM-dd)
      	 * 
      	 * @return
      	 */
      	public static String getDate() {
      		return getDate("yyyy-MM-dd");
      	}
      
      	/**
      	 * 得到当前日期字符串 格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E"
      	 * 
      	 * @param pattern
      	 * @return
      	 */
      	public static String getDate(String pattern) {
      		return DateFormatUtils.format(new Date(), pattern);
      	}
      
      	/**
      	 * 得到日期字符串 默认格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E"
      	 * 
      	 * @param date
      	 * @param pattern
      	 * @return
      	 */
      	public static String formatDate(Date date, Object... pattern) {
      		String formatDate = null;
      		if (pattern != null && pattern.length > 0) {
      			formatDate = DateFormatUtils.format(date, pattern[0].toString());
      		} else {
      			formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
      		}
      		return formatDate;
      	}
      
      	/**
      	 * 得到日期时间字符串,转换格式(yyyy-MM-dd HH:mm:ss)
      	 * 
      	 * @param date
      	 * @return
      	 */
      	public static String formatDateTime(Date date) {
      		return formatDate(date, "yyyy-MM-dd HH:mm:ss");
      	}
      
      	/**
      	 * 得到当前时间字符串 格式(HH:mm:ss)
      	 * 
      	 * @return
      	 */
      	public static String getTime() {
      		return formatDate(new Date(), "HH:mm:ss");
      	}
      
      	/**
      	 * 得到当前日期和时间字符串 格式(yyyy-MM-dd HH:mm:ss)
      	 * 
      	 * @return
      	 */
      	public static String getDateTime() {
      		return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
      	}
      
      	/**
      	 * 得到当前年份字符串 格式(yyyy)
      	 * 
      	 * @return
      	 */
      	public static String getYear() {
      		return formatDate(new Date(), "yyyy");
      	}
      
      	/**
      	 * 得到当前月份字符串 格式(MM)
      	 * 
      	 * @return
      	 */
      	public static String getMonth() {
      		return formatDate(new Date(), "MM");
      	}
      
      	/**
      	 * 得到当天字符串 格式(dd)
      	 * 
      	 * @return
      	 */
      	public static String getDay() {
      		return formatDate(new Date(), "dd");
      	}
      
      	/**
      	 * 得到当前星期字符串 格式(E)星期几
      	 * 
      	 * @return
      	 */
      	public static String getWeek() {
      		return formatDate(new Date(), "E");
      	}
      
      	/**
      	 * 日期型字符串转化为日期格式
      	 * 
      	 * "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss",
      	 * "yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy.MM.dd HH:mm", "yyyy-MM-dd",
      	 * "yyyy/MM/dd", "yyyy.MM.dd", "yyyy-MM", "yyyy/MM", "yyyy.MM"
      	 * 
      	 * @param str
      	 * @return
      	 */
      	public static Date parseDate(Object str) {
      		if (str == null) {
      			return null;
      		}
      		try {
      			return parseDate(str.toString(), parsePatterns);
      		} catch (ParseException e) {
      			return null;
      		}
      	}
      
      	/**
      	 * 获取过去的天数
      	 * 
      	 * @param date
      	 * @return
      	 */
      	public static long pastDays(Date date) {
      		long t = new Date().getTime() - date.getTime();
      		return t / (24 * 60 * 60 * 1000);
      	}
      
      	/**
      	 * 获取过去的小时
      	 * 
      	 * @param date
      	 * @return
      	 */
      	public static long pastHour(Date date) {
      		long t = new Date().getTime() - date.getTime();
      		return t / (60 * 60 * 1000);
      	}
      
      	/**
      	 * 获取过去的分钟
      	 * 
      	 * @param date
      	 * @return
      	 */
      	public static long pastMinutes(Date date) {
      		long t = new Date().getTime() - date.getTime();
      		return t / (60 * 1000);
      	}
      
      	/**
      	 * 转换为时间(天,时:分:秒.毫秒)
      	 * 
      	 * @param timeMillis
      	 * @return
      	 */
      	public static String formatDateTime(long timeMillis) {
      		long day = timeMillis / (24 * 60 * 60 * 1000);
      		long hour = (timeMillis / (60 * 60 * 1000) - day * 24);
      		long min = ((timeMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
      		long s = (timeMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
      		long sss = (timeMillis - day * 24 * 60 * 60 * 1000 - hour * 60 * 60 * 1000 - min * 60 * 1000 - s * 1000);
      		return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + s + "." + sss;
      	}
      
      	/**
      	 * 获取两个日期之间的天数
      	 * 
      	 * @param before
      	 * @param after
      	 * @return
      	 */
      	public static double getDistanceOfTwoDate(Date before, Date after) {
      		long beforeTime = before.getTime();
      		long afterTime = after.getTime();
      		return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
      	}
      
      	/**
      	 * @param args
      	 * @throws ParseException
      	 */
      	public static void main(String[] args) throws ParseException {
      //		System.out.println(formatDate(parseDate("2010/3/6")));
      //		System.out.println(getDate("yyyy年MM月dd日 E"));
      //		long time = new Date().getTime()-parseDate("2012-11-19").getTime();
      //		System.out.println(time/(24*60*60*1000));
      	}
      }
      
  16. 项目源码:
    Spring 5 + Spring MVC 5 + MyBatis 3 的 Maven 项目集成 源码
     
  17. 本文参考:
    1. Spring AOP实现后台管理系统日志管理

相关链接:

MyEclipse CI 2018.9.0 配置 Apache Maven 3.5.4

在MyEclipse CI 2018.9.0 中使用 Maven 3.5.4 创建Maven项目

在MyEclipse中使用SVN提交(自动忽略 .settings .project .classpath等)、检出(无.settings .project .classpath文件等)Maven代码

猜你喜欢

转载自blog.csdn.net/qq_32596527/article/details/83302826