Spring Boot整合MyBatis学习总结
公司的很多项目都陆陆续续引入了Spring Boot,通过对Spring Boot的接触了解发现其真的是大大地简化了开发、简化了依赖配置,很多功能注解一下就可以实现,真的是太方便了。下面记录了一个Spring Boot的入门程序实现,包括过滤器、servlet、定时器、全局异常处理、日志、Druid数据源的SQL监控配置。
1,pom.xml文件:
<projectxmlns="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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zws</groupId><artifactId>spring-boot</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>spring-boot</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.10.RELEASE</version></parent><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.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.46</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
可以看到这个文件内容并不多,但是却引入了很多需要的依赖。这里引入的Spring Boot版本为1.5.10.RELEASE,其中spring-boot-maven-plugin插件是Spring Boot提供的打包用的插件。mybatis-spring-boot-starter为MyBatis集成Spring Boot的依赖。druid-spring-boot-starter为阿里开源数据源Druid集成Spring Boot的依赖,它会下载对应的druid jar包,注意这里并没有直接引入Druid依赖,如果直接引入Druid依赖jar包,则druid的监控页面无法显示sql。
2,Spring Boot配置文件resources/application.properties:
server.port=8080server.context-path=/appspring.mvc.throw-exception-if-no-handler-found=truespring.resources.add-mappings=false#tomcat访问日志server.tomcat.basedir=logsserver.tomcat.accesslog.enabled=trueserver.tomcat.accesslog.directory=accessserver.tomcat.accesslog.pattern=%t%a"%r"%s%b(%Dms)datasource.druid.url=jdbc:mysql://localhost/db_boot?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=falsedatasource.druid.username=rootdatasource.druid.password=rootdatasource.druid.driver-class-name=com.mysql.jdbc.Driverdatasource.druid.initialSize=5datasource.druid.minIdle=5datasource.druid.maxActive=20datasource.druid.maxWait=60000datasource.druid.minEvictableIdleTimeMillis=300000datasource.druid.validationQuery=select'x'datasource.druid.testOnBorrow=falsedatasource.druid.testOnReturn=falsedatasource.druid.testWhileIdle=truedatasource.druid.poolPreparedStatements=falsedatasource.druid.maxPoolPreparedStatementPerConnectionSize=100datasource.druid.filters=stat,wall,log4jmybatis.config-location=classpath:mybatis/mybatis-config.xmlmybatis.mapper-locations=classpath:mybatis/mapper/*.xml
application.properties文件为Spring Boot的总配置文件,Spring Boot默认会加载resources目录下的application.properties文件。Spring Boot默认内嵌Tomcat作为web容器,server.port为端口,server.context-path为上下文路径。datasource开头的为druid数据源的配置。
3,MyBatis的配置文件resources/mybatis/mybatis-config.xml:
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><settingname="cacheEnabled"value="true"/><settingname="lazyLoadingEnabled"value="true"/><settingname="multipleResultSetsEnabled"value="true"/><settingname="useColumnLabel"value="true"/><settingname="useGeneratedKeys"value="false"/><settingname="autoMappingBehavior"value="PARTIAL"/><settingname="autoMappingUnknownColumnBehavior"value="WARNING"/><settingname="defaultExecutorType"value="SIMPLE"/><settingname="defaultStatementTimeout"value="25"/><settingname="defaultFetchSize"value="100"/><settingname="safeRowBoundsEnabled"value="false"/><settingname="mapUnderscoreToCamelCase"value="false"/><settingname="localCacheScope"value="SESSION"/><settingname="jdbcTypeForNull"value="OTHER"/><settingname="lazyLoadTriggerMethods"value="equals,clone,hashCode,toString"/></settings><typeAliases><packagename="com.zws.be.user.bean"/></typeAliases></configuration>
此配置文件的路径已经配置在了resources/application.properties文件内。
4,resources/mybatis/UserMapper.xml:
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.zws.be.user.mapper.UserMapper"><resultMapid="UserMap"type="User"><idcolumn="id"property="id"jdbcType="BIGINT"/><resultcolumn="name"property="name"jdbcType="VARCHAR"/><resultcolumn="pass"property="pass"jdbcType="VARCHAR"/><resultcolumn="create_date"property="createDate"/></resultMap><selectid="getAll"resultMap="UserMap">selectid,name,pass,create_datefromuser</select><selectid="getUserById"resultMap="UserMap"parameterType="long">selectid,name,pass,create_datefromuserwhereid=#{value}</select></mapper>
5,Sping Boot启动类Application.java:
packagecom.zws.be;importjavax.sql.DataSource;importorg.mybatis.spring.annotation.MapperScan;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.boot.web.servlet.ServletComponentScan;importorg.springframework.context.annotation.Bean;importorg.springframework.scheduling.annotation.EnableScheduling;importcom.alibaba.druid.pool.DruidDataSource;@SpringBootApplication@MapperScan(basePackages={"com.zws.be.*.mapper"})@ServletComponentScan@EnableSchedulingpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}@Bean("dataSource")@ConfigurationProperties("datasource.druid")publicDataSourcegetDruidDataSource(){returnDataSourceBuilder.create().type(DruidDataSource.class).build();}}
这个是程序启动的入口,里面有mian函数,运行此类即可启动Spring Boot。注解@MapperScan(basePackages = {"com.zws.be.*.mapper"})指定了映射mapper文件的接口所在的包。@EnableScheduling注解用于开启Spring的定时组件,下面会有例子。@ServletComponentScan注解搭配@WebServlet和@WebFilter注解使得定义servlet和filter时非常方便。
6,下面是定义一个简单的restful接口所需的各类:
com.zws.be.user.bean.User:
packagecom.zws.be.user.bean;importjava.util.Date;importorg.apache.ibatis.type.Alias;@Alias("User")publicclassUser{privateLongid;privateStringname;privateStringpass;privateDatecreateDate;publicLonggetId(){returnid;}publicvoidsetId(Longid){this.id=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStringgetPass(){returnpass;}publicvoidsetPass(Stringpass){this.pass=pass;}publicDategetCreateDate(){returncreateDate;}publicvoidsetCreateDate(DatecreateDate){this.createDate=createDate;}@OverridepublicStringtoString(){return"User[id="+id+",name="+name+",pass="+pass+",createDate="+createDate+"]";}}
com.zws.be.user.mapper.UserMapper:
packagecom.zws.be.user.mapper;importjava.util.List;importcom.zws.be.user.bean.User;publicinterfaceUserMapper{List<User>getAll();UsergetUserById(Longid);}
com.zws.be.user.service.UserService:
packagecom.zws.be.user.service;importjava.util.List;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importcom.zws.be.user.bean.User;importcom.zws.be.user.mapper.UserMapper;@ServicepublicclassUserService{@AutowiredprivateUserMapperuserMapper;publicList<User>getUsers(){returnuserMapper.getAll();}publicUsergetUser(Longid){returnuserMapper.getUserById(id);}}
com.zws.be.user.controller.UserController:
packagecom.zws.be.user.controller;importorg.apache.log4j.Logger;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.PathVariable;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestMethod;importorg.springframework.web.bind.annotation.RestController;importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.serializer.SerializerFeature;importcom.zws.be.user.bean.User;importcom.zws.be.user.service.UserService;@RestController@RequestMapping("/user")publicclassUserController{publicLoggerlogger=Logger.getLogger(UserController.class);@AutowiredprivateUserServiceuserService;@RequestMapping(value="/{id}",method=RequestMethod.GET,produces="application/json")publicStringhello(@PathVariableLongid){Useruser=userService.getUser(id);returnJSON.toJSONString(user,SerializerFeature.WriteDateUseDateFormat);}}
7,配置Druid的sql监控servlet:
packagecom.zws.be.filter;importjavax.servlet.annotation.WebServlet;importcom.alibaba.druid.support.http.StatViewServlet;/***DRUID的sql监控*@authorwensh.zhu*@2018-03-11*/@WebServlet(name="monitorSrvlet",urlPatterns={"/druid/*"})publicclassMonitorServletextendsStatViewServlet{privatestaticfinallongserialVersionUID=-2211104135110049275L;}
启动后访问http://localhost:8080/app/druid即可进入Druid的sql监控的监控页面。
8,过滤器例子:
packagecom.zws.be.filter;importjava.io.IOException;importjavax.servlet.Filter;importjavax.servlet.FilterChain;importjavax.servlet.FilterConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.annotation.WebFilter;importorg.apache.log4j.Logger;@WebFilter(filterName="filterDemo",urlPatterns={"/*"})publicclassFilterDemoimplementsFilter{privateLoggerlogger=Logger.getLogger(FilterDemo.class);@Overridepublicvoiddestroy(){}@OverridepublicvoiddoFilter(ServletRequestarg0,ServletResponsearg1,FilterChainchain)throwsIOException,ServletException{logger.info("FilterDemoisworking...");chain.doFilter(arg0,arg1);}@Overridepublicvoidinit(FilterConfigarg0)throwsServletException{}}
9,定时器例子:
packagecom.zws.be.timer;importorg.apache.log4j.Logger;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;@ComponentpublicclassTimerDemo{privateLoggerlogger=Logger.getLogger(getClass());@Scheduled(cron="0/30*****")publicvoidtimer(){logger.info("定时器例子");}}
10,全局异常处理:
packagecom.zws.be.exception;importorg.apache.log4j.Logger;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.ResponseBody;importorg.springframework.web.bind.annotation.RestControllerAdvice;/***全局异常处理*@authorwensh.zhu*@2018-03-11*/@RestControllerAdvicepublicclassExceptionAdvice{privateLoggerlogger=Logger.getLogger(getClass());privateStringpattern="抱歉,异常了:{0}";@ExceptionHandler(value={Exception.class})@ResponseBodypublicStringhandleAllException(Exceptione,HttpServletRequestreq,HttpServletResponseresp){logger.error("接口调用异常",e);if(einstanceofNoHandlerFoundException){StringreqURI=req.getRequestURI().toString();returnMessageFormat.format(pattern,"资源"+reqURI+"不存在!!!");}returnMessageFormat.format(pattern,e.getMessage());}}
11,log4j配置文件resources/log4j.properties:
log4j.rootLogger=INFO,stdout,infoLog,errorLoglog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.conversionPattern=%d{yyyy-MM-ddHH\:mm\:ss}|%p|%C|%M|%L|%m%nlog4j.appender.infoLog=com.zws.be.log.MyRollingFileAppenderlog4j.appender.infoLog.File=logs/info/info.loglog4j.appender.infoLog.Threshold=infolog4j.appender.infoLog.layout=org.apache.log4j.PatternLayoutlog4j.appender.infoLog.layout.ConversionPattern=%d{yyyy-MM-ddHH\:mm\:ss}|%p|%C|%M|%L|%m%nlog4j.appender.errorLog=com.zws.be.log.MyRollingFileAppenderlog4j.appender.errorLog.File=logs/error/error.loglog4j.appender.errorLog.Threshold=errorlog4j.appender.errorLog.layout=org.apache.log4j.PatternLayoutlog4j.appender.errorLog.layout.ConversionPattern=%d{yyyy-MM-ddHH\:mm\:ss}|%p|%C|%M|%L|%m%n
自定义日志生成文件名称:
packagecom.zws.be.log;importjava.io.File;importjava.io.IOException;importjava.io.InterruptedIOException;importorg.apache.log4j.Priority;importorg.apache.log4j.RollingFileAppender;importorg.apache.log4j.helpers.CountingQuietWriter;importorg.apache.log4j.spi.LoggingEvent;publicclassMyRollingFileAppenderextendsRollingFileAppender{privatelongnextRollover=0L;publicvoidrollOver(){Filetarget,file;if(qw!=null){longsize=((CountingQuietWriter)qw).getCount();nextRollover=size+maxFileSize;}booleanrenameSuccessed=true;if(maxBackupIndex>0){file=newFile(getRollingFileName(fileName,maxBackupIndex));if(file.exists()){renameSuccessed=file.delete();}for(inti=maxBackupIndex-1;i>=1&&renameSuccessed;i--){file=newFile(getRollingFileName(fileName,i));if(file.exists()){target=newFile(getRollingFileName(fileName,i+1));renameSuccessed=file.renameTo(target);}}if(renameSuccessed){target=newFile(getRollingFileName(fileName,1));closeFile();renameSuccessed=file.renameTo(target);if(!renameSuccessed){try{setFile(fileName,true,bufferedIO,bufferSize);}catch(IOExceptione){if(einstanceofInterruptedIOException){Thread.currentThread().interrupt();}}}}}}privateStringgetRollingFileName(StringfileName,intindex){StringfName="";StringnewIndex=index<10?("0"+index):String.valueOf(index);if(index>0){fName=fileName.replace(".log","")+"_"+newIndex+".log";}else{fName=fileName;}returnfName;}@OverrideprotectedvoidsubAppend(LoggingEventevent){super.subAppend(event);if(fileName!=null&&qw!=null){longsize=((CountingQuietWriter)qw).getCount();if(size>=maxFileSize&&size>=nextRollover){rollOver();}}}@OverridepublicbooleanisAsSevereAsThreshold(Prioritypriority){Stringlevel=priority.toString();if("ERROR".equals(level)){returngetThreshold().equals(priority);}returnsuper.isAsSevereAsThreshold(priority);}}
12,Spring MVC请求参数以及返回信息自动日志的辅助类:
packagecom.zws.be.log;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.text.MessageFormat;importorg.apache.log4j.Logger;importorg.springframework.core.MethodParameter;importorg.springframework.http.MediaType;importorg.springframework.http.converter.HttpMessageConverter;importorg.springframework.http.server.ServerHttpRequest;importorg.springframework.http.server.ServerHttpResponse;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/***用于请求参数、响应信息的自动日志。*@authorwensh.zhu*@2018-03-11*/@ControllerAdvice(basePackages={"com.zws.be"})publicclassLogResponseBodyAdviceimplementsResponseBodyAdvice<String>{privateStringpattern="\n---BEGIN---\nReqURI:{0}\nParams:{1}\nMethod:{2}\nReturn:{3}\n---END---";privateLoggerlogger=Logger.getLogger(LogResponseBodyAdvice.class);@OverridepublicStringbeforeBodyWrite(StringrtnMsg,MethodParameterparam,MediaTypearg2,Class<?extendsHttpMessageConverter<?>>arg3,ServerHttpRequestreq,ServerHttpResponseresp){StringclazName=param.getDeclaringClass().getName();StringmtdName=param.getMethod().getName();StringreqURI=req.getURI().toString();StringreqParams=getReqParams(req);Stringlog=getLog(reqURI,reqParams,clazName+"."+mtdName,rtnMsg);logger.info(log);returnrtnMsg;}@Overridepublicbooleansupports(MethodParameterarg0,Class<?extendsHttpMessageConverter<?>>arg1){returntrue;}privateStringgetLog(StringreqURI,StringreqParams,StringproMethod,StringrtnMsg){returnMessageFormat.format(pattern,reqURI,reqParams,proMethod,rtnMsg);}privateStringgetReqParams(ServerHttpRequestreq){StringBuilderbody=newStringBuilder();Stringline=null;BufferedReaderreader=null;try{reader=newBufferedReader(newInputStreamReader(req.getBody(),"UTF-8"));while((line=reader.readLine())!=null){body.append(line);}}catch(IOExceptione){logger.error("I/Oerror",e);}finally{try{if(reader!=null){reader.close();}}catch(IOExceptione){logger.error("I/Oerror",e);}}returnbody.toString();}}
此类功能为将Spring MVC接受到请求的参数、处理请求对应的方法、请求返回内容自动打印到日志文件内,在接口出现问题的时候方便排查,日志输出样例:
---BEGIN---ReqURI:http://localhost:8080/app/user/1Params:Method:com.zws.be.user.controller.UserController.helloReturn:{"createDate":"2018-03-0415:44:25","id":1,"name":"zhangsan","pass":"zhangsan@123"}---END---
13,运行Application,访问http://localhost:8080/app/user/1,如下图:
查看druid的监控:
项目目录结构图:
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。