澳门新葡亰赌995577redis spring 集成

澳门新葡亰赌995577 47

使用Spring Boot搭建应用开发框架(一) —— 基础架构,spring应用开发

pom构建:

Spring的简史

第一阶段:XML配置,在Spring1.x时代,使用Spring开发满眼都是xml配置的Bean,随着项目的扩大,我们需要把xml配置文件分放到不同的配置文件里,那时候需要频繁的在开发的类和配置文件之间切换。

第二阶段:注解配置,在Spring2.x时代,Spring提供声明Bean的注解,大大减少了配置量。应用的基本配置用xml,业务配置用注解。

第三阶段:Java配置,从Spring3.x到现在,Spring提供了Java配置,使用Java配置可以让你更理解你所配置的Bean。

Spring Boot:使用“习惯优于配置”的理念让你的项目快速运行起来。使用Spring
Boot很容易创建一个独立运行、准生产级别的基于Spring框架的项目,使用Spring
Boot你可以不用或者只需要很少的Spring配置。

下面就来使用Spring
Boot一步步搭建一个前后端分离的应用开发框架,并且以后不断的去完善这个框架,往里面添加功能。后面以实战为主,不会介绍太多概念,取而代之的是详细的操作。

 

[html] view
plain
 copy

零、开发技术简介

开发平台:windows

开发工具:Intellij IDEA 2017.1

JDK:Java 8

Maven:maven-3.3.9

服务器:tomcat 8.0

数据库:MySQL 5.7

数据源:Druid1.1.6

缓存:Redis 3.2

日志框架:SLF4J+Logback

Spring Boot:1.5.7.RELEASE

ORM框架:MyBatis+通用Mapper

Spring Boot官方文档:Spring Boot Reference Guide

 

 print?

一、创建项目

这一节创建项目的基础结构,按照spring
boot的思想,将各个不同的功能按照starter的形式拆分开来,做到灵活组合,并简单介绍下Spring
Boot相关的东西。

  1. <modelVersion>4.0.0</modelVersion>  
  2. <groupId>com.x.redis</groupId>  
  3. <artifactId>springredis</artifactId>  
  4. <version>0.0.1-SNAPSHOT</version>  
  5.   
  6. <dependencies>  
  7.     <dependency>  
  8.         <groupId>org.springframework.data</groupId>  
  9.         <artifactId>spring-data-redis</artifactId>  
  10.         <version>1.0.2.RELEASE</version>  
  11.     </dependency>  
  12.     <dependency>  
  13.         <groupId>org.springframework</groupId>  
  14.         <artifactId>spring-test</artifactId>  
  15.         <version>3.1.2.RELEASE</version>  
  16.         <scope>test</scope>  
  17.     </dependency>  
  18.       
  19.     <dependency>  
  20.         <groupId>redis.clients</groupId>  
  21.         <artifactId>jedis</artifactId>  
  22.         <version>2.1.0</version>  
  23.     </dependency>  
  24.       
  25.      <dependency>  
  26.         <groupId>junit</groupId>  
  27.         <artifactId>junit</artifactId>  
  28.         <version>4.8.2</version>  
  29.         <scope>test</scope>  
  30.     </dependency>  
  31. </dependencies>  

1、创建工程

① 通过File > New > Project,新建工程,选择Spring
Initializr,然后Next。

澳门新葡亰赌995577 1


尽量为自己的框架想个好点的名字,可以去申请个自己的域名。我这里项目名称为Sunny,项目路径为com.lyyzoo.sunny。

澳门新葡亰赌995577 2

③ 这里先什么都不选,后面再去集成。注意我的Spring Boot版本为1.5.9。Next

澳门新葡亰赌995577 3


定义好工程的目录,用一个专用目录吧,不要在一个目录下和其它东西杂在一起。之后点击Finish。

澳门新葡亰赌995577 4

上面说的这么详细,只有一个目的,从一个开始就做好规范。

⑤ 生成的项目结构如下,可以自己去看下pom.xml里的内容。

澳门新葡亰赌995577 5

spring配置文件(applicationContext.xml):

2、创建Starter

先创建一个core核心、cache缓存、security授权认证,其它的后面再集成进去。

跟上面一样的方式,在Sunny下创建sunny-starter-core、sunny-starter-cache、sunny-starter-security子模块。

这样分模块后,我们以后需要哪个模块就引入哪个模块即可,如果哪个模块不满足需求,还可以重写该模块。

最终的项目结构如下:

澳门新葡亰赌995577 6

[html] view
plain
 copy

3、启动项目

首先在core模块下来启动并了解SpringBoot项目。


在com.lyyzoo.core根目录下,有一个SunnyStarterCoreApplication,这是SpringBoot的入口类,通常是*Application的命名。

入口类里有一个main方法,其实就是一个标准的Java应用的入口方法。在main方法中使用SpringApplication.run启动Spring
Boot项目。

然后看看@SpringBootApplication注解,@SpringBootApplication是Spring
Boot的核心注解,是一个组合注解。

@EnableAutoConfiguration让Spring
Boot根据类路径中的jar包依赖为当前项目进行自动配置。

Spring
Boot会自动扫描@SpringBootApplication所在类的同级包以及下级包里的Bean。

澳门新葡亰赌995577 7

澳门新葡亰赌995577 8

② 先启动项目,这里可以看到有一个Spring
Boot的启动程序,点击右边的按钮启动项目。看到控制台Spring的标志,就算是启动成功了。

澳门新葡亰赌995577 9

澳门新葡亰赌995577 10

③ 替换默认的banner

可以到http://patorjk.com/software/taag/这个网站生成一个自己项目的banner。创建banner.txt并放到resources根目录下。

澳门新葡亰赌995577 11

 print?

4、Spring Boot 配置

① 配置文件

Spring
Boot使用一个全局的配置文件application.properties或application.yaml,放置在src/main/resources目录下。我们可以在这个全局配置文件中对一些默认的配置值进行修改。

具体有哪些配置可到官网查找,有非常多的配置,不过大部分使用默认即可。Common
application properties

然后,需要为不同的环境配置不同的配置文件,全局使用application-{profile}.properties指定不同环境配置文件。

我这里增加了开发环境(dev)和生产环境(prod)的配置文件,并通过在application.properties中设置spring.profiles.active=dev来指定当前环境。

澳门新葡亰赌995577 12

② starter pom

Spring Boot为我们提供了简化开发绝大多数场景的starter
pom,只要使用了应用场景所需的starter
pom,无需繁杂的配置,就可以得到Spring Boot为我们提供的自动配置的Bean。

后面我们将会通过加入这些starter来一步步集成我们想要的功能。具体有哪些starter,可以到官网查看:Starters

③ 自动配置

Spring Boot关于自动配置的源码在spring-boot-autoconfigure中如下:

澳门新葡亰赌995577 13

我们可以在application.properties中加入debug=true,查看当前项目中已启用和未启用的自动配置。

澳门新葡亰赌995577 14

我们在application.properties中的配置其实就是覆盖spring-boot-autoconfigure里的默认配置,比如web相关配置在web包下。

常见的如HttpEncodingProperties配置http编码,里面自动配置的编码为UTF-8。

MultipartProperties,上传文件的属性,设置了上传最大文件1M。

ServerProperties,配置内嵌Servlet容器,配置端口、contextPath等等。

澳门新葡亰赌995577 15

之前说@SpringBootApplication是Spring
Boot的核心注解,但他的核心功能是由@EnableAutoConfiguration注解提供的。

@EnableAutoConfiguration注解通过@Import导入配置功能,在AutoConfigurationImportSelector中,通过SpringFactoriesLoader.loadFactoryNames扫描META-INF/spring.factories文件。

在spring.factories中,配置了需要自动配置的类,我们也可以通过这种方式添加自己的自动配置。

在spring-boot-autoconfigure下就有一个spring.factories,如下:

说了这么多,只为说明一点,Spring
Boot为我们做了很多自动化的配置,搭建快速方便。

但是,正因为它为我们做了很多事情,就有很多坑,有时候,出了问题,我们可能很难找出问题所在,这时候,我们可能就要考虑下是否是自动配置导致的,有可能配置冲突了,或者没有使用上自定义的配置等等。

  1. <?xml version=”1.0″ encoding=”UTF-8″?>  
  2. <beans xmlns=”http://www.springframework.org/schema/beans”  
  3.     xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:p=”http://www.springframework.org/schema/p”  
  4.     xmlns:context=”http://www.springframework.org/schema/context”  
  5.     xmlns:jee=”http://www.springframework.org/schema/jee” xmlns:tx=”http://www.springframework.org/schema/tx”  
  6.     xmlns:aop=”http://www.springframework.org/schema/aop”  
  7.     xsi:schemaLocation=”  
  8.             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
  9.             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"&gt;  
  10.   
  11.     <context:property-placeholder location=”classpath:redis.properties” />  
  12.   
  13.     <bean id=”poolConfig” class=”redis.clients.jedis.JedisPoolConfig”>  
  14.         <property name=”maxIdle” value=”${redis.maxIdle}” />  
  15.         <property name=”maxActive” value=”${redis.maxActive}” />  
  16.         <property name=”maxWait” value=”${redis.maxWait}” />  
  17.         <property name=”testOnBorrow” value=”${redis.testOnBorrow}” />  
  18.     </bean>  
  19.       
  20.     <bean id=”connectionFactory” class=”org.springframework.data.redis.connection.jedis.JedisConnectionFactory”  
  21.         p:host-name=”${redis.host}” p:port=”${redis.port}” p:password=”${redis.pass}”  p:pool-config-ref=”poolConfig”/>  
  22.       
  23.     <bean id=”redisTemplate” class=”org.springframework.data.redis.core.StringRedisTemplate”>  
  24.         <property name=”connectionFactory”   ref=”connectionFactory” />  
  25.     </bean>         
  26.       
  27.     <bean id=”userDao” class=”com.x.dao.impl.UserDao” />   
  28. </beans>  

5、项目结构划分

core是项目的核心模块,结构初步规划如下:

 base是项目的基础核心,定义一些基础类,如BaseController、BaseService等;

    cache是缓存相关;

    config是配置中心,模块所有的配置放到config里统一管理;

    constants里定义系统的常量。

    exception里封装一些基础的异常类;

 system是系统模块;

    util里则是一些通用工具类;

澳门新葡亰赌995577 16

 

redis.properties

二、基础结构功能

[html] view
plain
 copy

1、web支持

只需在pom.xml中加入spring-boot-starter-web的依赖即可。

之后,查看POM的依赖树(插件:Maven
Helper),可以看到引入了starter、tomcat、web支持等。可以看出,Sping
Boot内嵌了servlet容器,默认tomcat。

自动配置在WebMvcAutoConfiguration和WebMvcProperties里,可自行查看源码,一般我们不需添加其他配置就可以启动这个web项目了。

澳门新葡亰赌995577 17

澳门新葡亰赌995577 18

 print?

2、基础功能

在core中添加一些基础的功能支持。

① 首先引入一些常用的依赖库,主要是一些常用工具类,方便以后的开发。

澳门新葡亰赌995577 19
1 <!– *******************************
常用依赖库
**********************************
–> 2 <!– 针对开发IO流功能的工具类库 –> 3 <dependency>
4 <groupId>commons-io</groupId> 5
<artifactId>commons-io</artifactId> 6
<version>${commons.io.version}</version> 7
</dependency> 8 <!– 文件上传 –> 9 <dependency> 10
<groupId>commons-fileupload</groupId> 11
<artifactId>commons-fileupload</artifactId> 12
<version>${commons.fileupload.version}</version> 13
<exclusions> 14 <exclusion> 15
<groupId>commons-io</groupId> 16
<artifactId>commons-io</artifactId> 17 </exclusion> 18
</exclusions> 19 </dependency> 20 <!–
常用的集合操作,丰富的工具类 –> 21 <dependency> 22
<groupId>commons-collections</groupId> 23
<artifactId>commons-collections</artifactId> 24
<version>${commons.collections.version}</version> 25
</dependency> 26 <!– 操作javabean的工具包 –> 27
<dependency> 28 <groupId>commons-beanutils</groupId>
29 <artifactId>commons-beanutils</artifactId> 30
<version>${commons.beanutils.version}</version> 31
<exclusions> 32 <exclusion> 33
<groupId>commons-collections</groupId> 34
<artifactId>commons-collections</artifactId> 35
</exclusion> 36 </exclusions> 37 </dependency> 38
<!– 包含一些通用的编码解码算法. 如:MD5、SHA1、Base64等 –> 39
<dependency> 40 <groupId>commons-codec</groupId> 41
<artifactId>commons-codec</artifactId> 42
<version>${commons.codec.version}</version> 43
</dependency> 44 <!– 包含丰富的工具类如 StringUtils –> 45
<dependency> 46 <groupId>org.apache.commons</groupId>
47 <artifactId>commons-lang3</artifactId> 48
<version>${commons.lang3.version}</version> 49
</dependency> 50 <!– 51
Guava工程包含了若干被Google的Java项目广泛依赖的核心库.
集合[collections] 、缓存[caching] 、原生类型支持[primitives
support] 、 52 并发库[concurrency libraries] 、通用注解[common
annotations] 、字符串处理[string processing] 、I/O 等等。 53 –>
54 <dependency> 55 <groupId>com.google.guava</groupId>
56 <artifactId>guava</artifactId> 57
<version>${guava.version}</version> 58 </dependency>
View Code

版本号如下:

澳门新葡亰赌995577 20


在base添加一个Result类,作为前端的返回对象,Controller的直接返回对象都是Result。

澳门新葡亰赌995577 19package
com.lyyzoo.core.base; import
com.fasterxml.jackson.annotation.JsonInclude; import
java.io.Serializable; /** * 前端返回对象 * * @version 1.0 *
@author bojiangzhou 2017-12-28 */ public class Result implements
Serializable { private static final long serialVersionUID =
1430633339880116031L; /** * 成功与否标志 */ private boolean success
= true; /** *
返回状态码,为空则默认200.前端需要拦截一些常见的状态码如403、404、500等
*/ @JsonInclude(JsonInclude.Include.NON_NULL) private Integer status;
/** * 编码,可用于前端处理多语言,不需要则不用返回编码 */
@JsonInclude(JsonInclude.Include.NON_NULL) private String code; /**
* 相关消息 */ @JsonInclude(JsonInclude.Include.NON_NULL) private
String msg; /** * 相关数据 */
@JsonInclude(JsonInclude.Include.NON_NULL) private Object data; public
Result() {} public Result(boolean success) { this.success = success; }
public Result(boolean success, Integer status) { this.success = success;
this.status = status; } public Result(boolean success, String code,
String msg){ this(success); this.code = code; this.msg = msg; } public
Result(boolean success, Integer status, String code, String msg) {
this.success = success; this.status = status; this.code = code; this.msg
= msg; } public Result(boolean success, String code, String msg, Object
data){ this(success); this.code = code; this.msg = msg; this.data =
data; } public boolean isSuccess() { return success; } public void
setSuccess(boolean success) { this.success = success; } public Integer
getStatus() { return status; } public void setStatus(Integer status) {
this.status = status; } public String getCode() { return code; } public
void setCode(String code) { this.code = code; } public String getMsg() {
return msg; } public void setMsg(String msg) { this.msg = msg; } public
Object getData() { return data; } public void setData(Object data) {
this.data = data; } } View
Code

之后在util添加生成Result的工具类Results,用于快速方便的创建Result对象。

澳门新葡亰赌995577 19package
com.lyyzoo.core.util; import com.lyyzoo.core.base.Result; /** *
Result生成工具类 * * @version 1.0 * @author bojiangzhou 2017-12-28
*/ public class Results { protected Results() {} public static Result
newResult() { return new Result(); } public static Result
newResult(boolean success) { return new Result(success); } // //

  1. # Redis settings  
  2. redis.host=localhost  
  3. redis.port=6379  
  4. redis.pass=java2000_wl  
  5.   
  6.   
  7. redis.maxIdle=300  
  8. redis.maxActive=600  
  9. redis.maxWait=1000  
  10. redis.testOnBorrow=true  

业务调用成功 //

public static Result success() { return new Result(); } public static
Result success(String msg) { return new Result(true, null, msg); }
public static Result success(String code, String msg) { return new
Result(true, code, msg); } public static Result
successWithStatus(Integer status) { return new Result(true, status); }
public static Result successWithStatus(Integer status, String msg) {
return new Result(true, status, null, msg); } public static Result
successWithData(Object data) { return new Result(true, null, null,
data); } public static Result successWithData(Object data, String msg) {
return new Result(true, null, msg, data); } public static Result
successWithData(Object data, String code, String msg) { return new

java代码:

Result(true, code, msg, data); } // // 业务调用失败 //

public static Result failure() { return new Result(false); } public
static Result failure(String msg) { return new Result(false, null, msg);
} public static Result failure(String code, String msg) { return new
Result(false, code, msg); } public static Result
failureWithStatus(Integer status) { return new Result(false, status); }
public static Result failureWithStatus(Integer status, String msg) {
return new Result(false, status, null, msg); } public static Result
failureWithData(Object data) { return new Result(false, null, null,
data); } public static Result failureWithData(Object data, String msg) {
return new Result(false, null, msg, data); } public static Result
failureWithData(Object data, String code, String msg) { return new
Result(false, code, msg, data); } } View Code

③ 在base添加BaseEnum<K, V>枚举接口,定义了获取值和描述的接口。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.base; 2 3 /** 4 * 基础枚举接口 5 * 6 *
@version 1.0 7 * @author bojiangzhou 2017-12-31 8 */ 9 public
interface BaseEnum<K, V> { 10 11 /** 12 * 获取编码 13 * 14 *
@return 编码 15 */ 16 K code(); 17 18 /** 19 * 获取描述 20 * 21 *
@return 描述 22 */ 23 V desc(); 24 25 } View Code

然后在constants下定义一个基础枚举常量类,我们把一些描述信息维护到枚举里面,尽量不要在代码中直接出现魔法值(如一些编码、中文等),以后的枚举常量类也可以按照这种模式来写。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.constants; 2 3 import
com.lyyzoo.core.base.BaseEnum; 4 5 import java.util.HashMap; 6 import
java.util.Map; 7 8 /** 9 * 基础枚举值 10 * 11 * @version 1.0 12 *
@author bojiangzhou 2018-01-01 13 */ 14 public enum BaseEnums
implements BaseEnum<String, String> { 15 16
SUCCESS(“request.success”, “请求成功”), 17 18 FAILURE(“request.failure”,
“请求失败”), 19 20 OPERATION_SUCCESS(“operation.success”, “操作成功”),
21 22 OPERATION_FAILURE(“operation.failure”, “操作失败”), 23 24
ERROR(“system.error”, “系统异常”), 25 26 NOT_FOUND(“not_found”,
“请求资源不存在”), 27 28 FORBIDDEN(“forbidden”, “无权限访问”), 29 30
VERSION_NOT_MATCH(“record_not_exists_or_version_not_match”,
“记录版本不存在或不匹配”), 31 32
PARAMETER_NOT_NULL(“parameter_not_be_null”, “参数不能为空”); 33 34
private String code; 35 36 private String desc; 37 38 private static
Map<String, String> allMap = new HashMap<>(); 39 40
BaseEnums(String code, String desc) { 41 this.code = code; 42 this.desc
= desc; 43 } 44 45 static { 46 for(BaseEnums enums :
BaseEnums.values()){ 47 allMap.put(enums.code, enums.desc); 48 } 49 } 50
51 @Override 52 public String code() { 53 return code; 54 } 55 56
@Override 57 public String desc() { 58 return desc; 59 } 60 61 public
String desc(String code) { 62 return allMap.get(code); 63 } 64 65 }
View Code


再添加一个常用的日期工具类对象,主要包含一些常用的日期时间格式化,后续可再继续往里面添加一些公共方法。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.util; 2 3 4 import
org.apache.commons.lang3.StringUtils; 5 import
org.apache.commons.lang3.time.DateUtils; 6 7 import
java.text.ParseException; 8 import java.text.SimpleDateFormat; 9 import
java.util.Date; 10 11 /** 12 * 日期时间工具类 13 * 14 * @version
1.0 15 * @author bojiangzhou 2017-12-28 16 */ 17 public class Dates {
18 19 /** 20 * 日期时间匹配格式 21 */ 22 public interface Pattern {

[java] view
plain
 copy

23 // 24 // 常规模式 25 //

26 /** 27 * yyyy-MM-dd 28 */ 29 String DATE = “yyyy-MM-dd”; 30 /**
31 * yyyy-MM-dd HH:mm:ss 32 */ 33 String DATETIME = “yyyy-MM-dd
HH:mm:ss”; 34 /** 35 * yyyy-MM-dd HH:mm 36 */ 37 String DATETIME_MM
= “yyyy-MM-dd HH:mm”; 38 /** 39 * yyyy-MM-dd HH:mm:ss.SSS 40 */ 41
String DATETIME_SSS = “yyyy-MM-dd HH:mm:ss.SSS”; 42 /** 43 * HH:mm
44 */ 45 String TIME = “HH:mm”; 46 /** 47 * HH:mm:ss 48 */ 49

 print?

String TIME_SS = “HH:mm:ss”; 50 51 // 52 // 系统时间格式 53 //

54 /** 55 * yyyy/MM/dd 56 */ 57 String SYS_DATE = “yyyy/MM/dd”; 58
/** 59 * yyyy/MM/dd HH:mm:ss 60 */ 61 String SYS_DATETIME =
“yyyy/MM/dd HH:mm:ss”; 62 /** 63 * yyyy/MM/dd HH:mm 64 */ 65 String
SYS_DATETIME_MM = “yyyy/MM/dd HH:mm”; 66 /** 67 * yyyy/MM/dd
HH:mm:ss.SSS 68 */ 69 String SYS_DATETIME_SSS = “yyyy/MM/dd

  1. package com.x.entity;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. /**  
  6.  * @author http://blog.csdn.net/java2000\_wl  
  7.  * @version <b>1.0</b>  
  8.  */   
  9. public class User implements Serializable {  
  10.       
  11.     private static final long serialVersionUID = -6011241820070393952L;  
  12.   
  13.     private String id;  
  14.       
  15.     private String name;  
  16.       
  17.     private String password;  
  18.   
  19.     /** 
  20.      * <br>——————————<br> 
  21.      */  
  22.     public User() {  
  23.           
  24.     }  
  25.       
  26.     /** 
  27.      * <br>——————————<br> 
  28.      */  
  29.     public User(String id, String name, String password) {  
  30.         super();  
  31.         this.id = id;  
  32.         this.name = name;  
  33.         this.password = password;  
  34.     }  
  35.   
  36.     /** 
  37.      * 获得id 
  38.      * @return the id 
  39.      */  
  40.     public String getId() {  
  41.         return id;  
  42.     }  
  43.   
  44.     /** 
  45.      * 设置id 
  46.      * @param id the id to set 
  47.      */  
  48.     public void setId(String id) {  
  49.         this.id = id;  
  50.     }  
  51.   
  52.     /** 
  53.      * 获得name 
  54.      * @return the name 
  55.      */  
  56.     public String getName() {  
  57.         return name;  
  58.     }  
  59.   
  60.     /** 
  61.      * 设置name 
  62.      * @param name the name to set 
  63.      */  
  64.     public void setName(String name) {  
  65.         this.name = name;  
  66.     }  
  67.   
  68.     /** 
  69.      * 获得password 
  70.      * @return the password 
  71.      */  
  72.     public String getPassword() {  
  73.         return password;  
  74.     }  
  75.   
  76.     /** 
  77.      * 设置password 
  78.      * @param password the password to set 
  79.      */  
  80.     public void setPassword(String password) {  
  81.         this.password = password;  
  82.     }  
  83. }  

HH:mm:ss.SSS”; 70 71 // 72 // 无连接符模式 73 //

74 /** 75 * yyyyMMdd 76 */ 77 String NONE_DATE = “yyyyMMdd”; 78
/** 79 * yyyyMMddHHmmss 80 */ 81 String NONE_DATETIME =
“yyyyMMddHHmmss”; 82 /** 83 * yyyyMMddHHmm 84 */ 85 String
NONE_DATETIME_MM = “yyyyMMddHHmm”; 86 /** 87 * yyyyMMddHHmmssSSS 88
*/ 89 String NONE_DATETIME_SSS = “yyyyMMddHHmmssSSS”; 90 } 91 92
public static final String DEFAULT_PATTERN = Pattern.DATETIME; 93 94
public static final String[] PARSE_PATTERNS = new String[]{ 95
Pattern.DATE, 96 Pattern.DATETIME, 97 Pattern.DATETIME_MM, 98
Pattern.DATETIME_SSS, 99 Pattern.SYS_DATE, 100 Pattern.SYS_DATETIME,
101 Pattern.SYS_DATETIME_MM, 102 Pattern.SYS_DATETIME_SSS 103 }; 104
105 /** 106 * 格式化日期时间 107 * 108 * @param date 日期时间 109
* 110 * @return yyyy-MM-dd HH:mm:ss 111 */ 112 public static String
format(Date date) { 113 return format(date, DEFAULT_PATTERN); 114 } 115
116 /** 117 * 格式化日期 118 * 119 * @param date 日期(时间) 120 *
121 * @param pattern 匹配模式 参考:{@link Dates.Pattern} 122 * 123 *
@return 格式化后的字符串 124 */ 125 public static String format(Date
date, String pattern) { 126 if (date == null) { 127 return null; 128 }
129 pattern = StringUtils.isNotBlank(pattern) ? pattern :
DEFAULT_PATTERN; 130 SimpleDateFormat sdf = new
SimpleDateFormat(pattern); 131 return sdf.format(date); 132 } 133 134
/** 135 * 解析日期 136 * 137 * @param date 日期字符串 138 * 139 *
@return 解析后的日期 默认格式:yyyy-MM-dd HH:mm:ss 140 */ 141 public
static Date parseDate(String date) { 142 if (StringUtils.isBlank(date))
{ 143 return null; 144 } 145 try { 146 return DateUtils.parseDate(date,
PARSE_PATTERNS); 147 } catch (ParseException e) { 148
e.printStackTrace(); 149 } 150 return null; 151 } 152 153 /** 154 *
解析日期 155 * 156 * @param date 日期 157 * 158 * @param pattern
格式 参考:{@link Dates.Pattern} 159 * 160 * @return
解析后的日期,默认格式:yyyy-MM-dd HH:mm:ss 161 */ 162 public static
Date parseDate(String date, String pattern) { 163 if
(StringUtils.isBlank(date)) { 164 return null; 165 } 166 String[]
parsePatterns; 167 parsePatterns = StringUtils.isNotBlank(pattern) ? new
String[]{pattern} : PARSE_PATTERNS; 168 try { 169 return
DateUtils.parseDate(date, parsePatterns); 170 } catch (ParseException e)
{ 171 e.printStackTrace(); 172 } 173 return null; 174 } 175 176 177 178
} View Code

⑤ Constants定义系统级的通用常量。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.constants; 2 3 import
com.google.common.base.Charsets; 4 5 import java.nio.charset.Charset; 6
7 /** 8 * 系统级常量类 9 * 10 * @version 1.0 11 * @author
bojiangzhou 2017-12-28 12 */ 13 public class Constants { 14 15 public
static final String APP_NAME = “sunny”; 16 17 /** 18 * 系统编码 19
*/ 20 public static final Charset CHARSET = Charsets.UTF_8; 21 22
/** 23 * 标识:是/否、启用/禁用等 24 */ 25 public interface Flag {
26 27 Integer YES = 1; 28 29 Integer NO = 0; 30 } 31 32 /** 33 *
操作类型 34 */ 35 public interface Operation { 36 /** 37 * 添加 38
*/ 39 String ADD = “add”; 40 /** 41 * 更新 42 */ 43 String UPDATE =
“update”; 44 /** 45 * 删除 46 */ 47 String DELETE = “delete”; 48 }
49 50 /** 51 * 性别 52 */ 53 public interface Sex { 54 /** 55 *
男 56 */ 57 Integer MALE = 1; 58 /** 59 * 女 60 */ 61 Integer
FEMALE = 0; 62 } 63 64 } View
Code


在base添加空的BaseController、BaseDTO、Service、Mapper,先定义好基础结构,后面再添加功能。

BaseDTO:标准的who字段、版本号、及10个扩展字段。

因为这里用到了@Transient注解,先引入java持久化包:

澳门新葡亰赌995577 27

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.base; 2 3 import
com.fasterxml.jackson.annotation.*; 4 import com.lyyzoo.core.Constants;
5 import com.lyyzoo.core.util.Dates; 6 import
org.apache.commons.lang3.builder.ToStringBuilder; 7 import
org.apache.commons.lang3.builder.ToStringStyle; 8 9 import
javax.persistence.Transient; 10 import java.io.Serializable; 11 import
java.util.Date; 12 import java.util.HashMap; 13 import java.util.Map; 14
15 /** 16 * 基础实体类 17 * 18 * @version 1.0 19 * @author
bojiangzhou 2017-12-29 20 */ 21 public class BaseDTO implements
Serializable { 22 private static final long serialVersionUID =
-4287607489867805101L; 23 24 public static final String FIELD_OPERATE =
“operate”; 25 public static final String FIELD_OBJECT_VERSION_NUMBER
= “versionNumber”; 26 public static final String FIELD_CREATE_BY =
“createBy”; 27 public static final String FIELD_CREATOR = “creator”; 28
public static final String FIELD_CREATE_DATE = “createDate”; 29 public
static final String FIELD_UPDATE_BY = “updateBy”; 30 public static
final String FIELD_UPDATER = “updater”; 31 public static final String
FIELD_UPDATE_DATE = “updateDate”; 32 33 34 /** 35 *
操作类型,add/update/delete 参考:{@link Constants.Operation} 36 */ 37
@Transient 38 private String _operate; 39 40 /** 41 *
数据版本号,每发生update则自增,用于实现乐观锁. 42 */ 43 private Long

[java] view
plain
 copy

versionNumber; 44 45 // 46 // 下面是标准 WHO 字段 47 //

48 /** 49 * 创建人用户名 50 */ 51
@JsonInclude(JsonInclude.Include.NON_NULL) 52 private Long createBy; 53
/** 54 * 创建人名称 55 */ 56
@JsonInclude(JsonInclude.Include.NON_NULL) 57 @Transient 58 private
String creator; 59 /** 60 * 创建时间 61 */ 62
@JsonInclude(JsonInclude.Include.NON_NULL) 63 @JsonFormat(pattern =
Dates.DEFAULT_PATTERN) 64 private Date createDate; 65 66 /** 67 *
更新人用户名 68 */ 69 @JsonInclude(JsonInclude.Include.NON_NULL) 70
private Long updateBy; 71 /** 72 * 更新人名称 73 */ 74
@JsonInclude(JsonInclude.Include.NON_NULL) 75 @Transient 76 private
String updater; 77 /** 78 * 更新时间 79 */ 80
@JsonInclude(JsonInclude.Include.NON_NULL) 81 @JsonFormat(pattern =
Dates.DEFAULT_PATTERN) 82 private Date updateDate; 83 84 /** 85 *
其它属性 86 */ 87 @JsonIgnore 88 @Transient 89 protected Map<String,
Object> innerMap = new HashMap<>(); 90 91 // 92 //

 print?

下面是扩展属性字段 93 //

94 95 @JsonInclude(JsonInclude.Include.NON_NULL) 96 private String
attribute1; 97 98 @JsonInclude(JsonInclude.Include.NON_NULL) 99 private
String attribute2; 100 101 @JsonInclude(JsonInclude.Include.NON_NULL)
102 private String attribute3; 103 104
@JsonInclude(JsonInclude.Include.NON_NULL) 105 private String
attribute4; 106 107 @JsonInclude(JsonInclude.Include.NON_NULL) 108
private String attribute5; 109 110
@JsonInclude(JsonInclude.Include.NON_NULL) 111 private String
attribute6; 112 113 @JsonInclude(JsonInclude.Include.NON_NULL) 114
private String attribute7; 115 116
@JsonInclude(JsonInclude.Include.NON_NULL) 117 private String
attribute8; 118 119 @JsonInclude(JsonInclude.Include.NON_NULL) 120
private String attribute9; 121 122
@JsonInclude(JsonInclude.Include.NON_NULL) 123 private String
attribute10; 124 125 public String get_operate() { 126 return
_operate; 127 } 128 129 public void set_operate(String _operate) {
130 this._operate = _operate; 131 } 132 133 @Override 134 public
String toString() { 135 return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE); 136 } 137 138 public String
toJSONString() { 139 return ToStringBuilder.reflectionToString(this,
ToStringStyle.JSON_STYLE); 140 } 141 142 public Long getVersionNumber()
{ 143 return versionNumber; 144 } 145 146 public void
setVersionNumber(Long versionNumber) { 147 this.versionNumber =
versionNumber; 148 } 149 150 public Long getCreateBy() { 151 return
createBy; 152 } 153 154 public void setCreateBy(Long createBy) { 155
this.createBy = createBy; 156 } 157 158 public String getCreator() { 159
return creator; 160 } 161 162 public void setCreator(String creator) {
163 this.creator = creator; 164 } 165 166 public Date getCreateDate() {
167 return createDate; 168 } 169 170 public void setCreateDate(Date
createDate) { 171 this.createDate = createDate; 172 } 173 174 public
Long getUpdateBy() { 175 return updateBy; 176 } 177 178 public void
setUpdateBy(Long updateBy) { 179 this.updateBy = updateBy; 180 } 181 182
public String getUpdater() { 183 return updater; 184 } 185 186 public
void setUpdater(String updater) { 187 this.updater = updater; 188 } 189
190 public Date getUpdateDate() { 191 return updateDate; 192 } 193 194
public void setUpdateDate(Date updateDate) { 195 this.updateDate =
updateDate; 196 } 197 198 @JsonAnyGetter 199 public Object
getAttribute(String key) { 200 return innerMap.get(key); 201 } 202 203
@JsonAnySetter 204 public void setAttribute(String key, Object obj) {
205 innerMap.put(key, obj); 206 } 207 208 public String getAttribute1()
{ 209 return attribute1; 210 } 211 212 public void setAttribute1(String
attribute1) { 213 this.attribute1 = attribute1; 214 } 215 216 public
String getAttribute2() { 217 return attribute2; 218 } 219 220 public
void setAttribute2(String attribute2) { 221 this.attribute2 =
attribute2; 222 } 223 224 public String getAttribute3() { 225 return
attribute3; 226 } 227 228 public void setAttribute3(String attribute3) {
229 this.attribute3 = attribute3; 230 } 231 232 public String
getAttribute4() { 233 return attribute4; 234 } 235 236 public void
setAttribute4(String attribute4) { 237 this.attribute4 = attribute4; 238
} 239 240 public String getAttribute5() { 241 return attribute5; 242 }
243 244 public void setAttribute5(String attribute5) { 245
this.attribute5 = attribute5; 246 } 247 248 public String
getAttribute6() { 249 return attribute6; 250 } 251 252 public void
setAttribute6(String attribute6) { 253 this.attribute6 = attribute6; 254
} 255 256 public String getAttribute7() { 257 return attribute7; 258 }
259 260 public void setAttribute7(String attribute7) { 261
this.attribute7 = attribute7; 262 } 263 264 public String
getAttribute8() { 265 return attribute8; 266 } 267 268 public void
setAttribute8(String attribute8) { 269 this.attribute8 = attribute8; 270
} 271 272 public String getAttribute9() { 273 return attribute9; 274 }
275 276 public void setAttribute9(String attribute9) { 277
this.attribute9 = attribute9; 278 } 279 280 public String
getAttribute10() { 281 return attribute10; 282 } 283 284 public void
setAttribute10(String attribute10) { 285 this.attribute10 = attribute10;
286 } 287 288 } View Code

同时,重写了toString方法,增加了toJsonString方法,使得可以格式化输出DTO的数据:

澳门新葡亰赌995577 29

直接打印DTO,输出的格式大概就是这个样子:

澳门新葡亰赌995577 30

⑦ 在exception添加BaseException,定义一些基础异常类

基础异常类都继承自运行时异常类(RunntimeException),尽可能把受检异常转化为非受检异常,更好的面向接口编程,提高代码的扩展性、稳定性。

BaseException:添加了一个错误编码,其它自定义的异常应当继承该类。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.exception; 2 3 /** 4 * 基础异常类 5 * 6 *
@version 1.0 7 * @author bojiangzhou 2017-12-31 8 */ 9 public class
BaseException extends RuntimeException { 10 private static final long
serialVersionUID = -997101946070796354L; 11 12 /** 13 * 错误编码 14
*/ 15 protected String code; 16 17 public BaseException() {} 18 19
public BaseException(String message) { 20 super(message); 21 } 22 23
public BaseException(String code, String message) { 24 super(message);
25 this.code = code; 26 } 27 28 public String getCode() { 29 return
code; 30 } 31 32 public void setCode(String code) { 33 this.code = code;
34 } 35 } View Code

ServiceException:继承BaseException,Service层往Controller抛出的异常。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.exception; 2 3 /** 4 * Service层异常 5 * 6
* @version 1.0 7 * @author bojiangzhou 2017-12-31 8 */ 9 public class
ServiceException extends BaseException { 10 private static final long
serialVersionUID = 6058294324031642376L; 11 12 public ServiceException()
{} 13 14 public ServiceException(String message) { 15 super(message); 16
} 17 18 public ServiceException(String code, String message) { 19
super(code, message); 20 } 21 22 } View Code

  1. package com.x.dao;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.data.redis.core.RedisTemplate;  
  5. import org.springframework.data.redis.serializer.RedisSerializer;  
  6.   
  7. /**  
  8.  * AbstractBaseRedisDao 
  9.  * @author http://blog.csdn.net/java2000\_wl  
  10.  * @version <b>1.0</b>  
  11.  */   
  12. public abstract class AbstractBaseRedisDao<K, V> {  
  13.       
  14.     @Autowired  
  15.     protected RedisTemplate<K, V> redisTemplate;  
  16.   
  17.     /** 
  18.      * 设置redisTemplate 
  19.      * @param redisTemplate the redisTemplate to set 
  20.      */  
  21.     public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {  
  22.         this.redisTemplate = redisTemplate;  
  23.     }  
  24.       
  25.     /** 
  26.      * 获取 RedisSerializer 
  27.      * <br>——————————<br> 
  28.      */  
  29.     protected RedisSerializer<String> getRedisSerializer() {  
  30.         return redisTemplate.getStringSerializer();  
  31.     }  
  32. }  

3、添加系统用户功能,使用Postman测试接口


在system模块下,再分成dto、controller、service、mapper、constants子包,以后一个模块功能开发就是这样一个基础结构。

User:系统用户

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.system.dto; 2 3 import
com.fasterxml.jackson.annotation.JsonFormat; 4 import
com.fasterxml.jackson.annotation.JsonInclude; 5 import
com.lyyzoo.core.base.BaseDTO; 6 import com.lyyzoo.core.util.Dates; 7 8
import java.util.Date; 9 10 /** 11 * 系统用户 12 * 13 * @version
1.0 14 * @author bojiangzhou 2017-12-31 15 */ 16
@JsonInclude(JsonInclude.Include.NON_NULL) 17 public class User extends
BaseDTO { 18 private static final long serialVersionUID =
-7395431342743009038L; 19 20 /** 21 * 用户ID 22 */ 23 private Long
userId; 24 /** 25 * 用户名 26 */ 27 private String username; 28
/** 29 * 密码 30 */ 31 private String password; 32 /** 33 * 昵称
34 */ 35 private String nickname; 36 /** 37 * 生日 38 */ 39
@JsonFormat(pattern = Dates.Pattern.DATE) 40 private Date birthday; 41
/** 42 * 性别:1-男/0-女 43 */ 44 private Integer sex; 45 /** 46
* 是否启用:1/0 47 */ 48 private Integer enabled; 49 50 public Long
getUserId() { 51 return userId; 52 } 53 54 public void setUserId(Long
userId) { 55 this.userId = userId; 56 } 57 58 public String
getUsername() { 59 return username; 60 } 61 62 public void
setUsername(String username) { 63 this.username = username; 64 } 65 66
public String getPassword() { 67 return password; 68 } 69 70 public void
setPassword(String password) { 71 this.password = password; 72 } 73 74
public String getNickname() { 75 return nickname; 76 } 77 78 public void
setNickname(String nickname) { 79 this.nickname = nickname; 80 } 81 82
public Date getBirthday() { 83 return birthday; 84 } 85 86 public void
setBirthday(Date birthday) { 87 this.birthday = birthday; 88 } 89 90
public Integer getSex() { 91 return sex; 92 } 93 94 public void
setSex(Integer sex) { 95 this.sex = sex; 96 } 97 98 public Integer
getEnabled() { 99 return enabled; 100 } 101 102 public void
setEnabled(Integer enabled) { 103 this.enabled = enabled; 104 } 105 106
} View Code

UserController:用户控制层;用@RestController注解,前后端分离,因为无需返回视图,采用Restful风格,直接返回数据。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.system.controller; 2 3 import
com.lyyzoo.core.Constants; 4 import com.lyyzoo.core.base.BaseController;
5 import com.lyyzoo.core.base.BaseEnums; 6 import
com.lyyzoo.core.base.Result; 7 import com.lyyzoo.core.system.dto.User; 8
import com.lyyzoo.core.util.Dates; 9 import
com.lyyzoo.core.util.Results; 10 import
org.springframework.web.bind.annotation.PathVariable; 11 import
org.springframework.web.bind.annotation.RequestMapping; 12 import
org.springframework.web.bind.annotation.RestController; 13 14 import
java.util.ArrayList; 15 import java.util.List; 16 17 /** 18 *
用户Controller 19 * 20 * @version 1.0 21 * @author bojiangzhou
2017-12-31 22 */ 23 @RequestMapping(“/sys/user”) 24 @RestController 25
public class UserController extends BaseController { 26 27 private
static List<User> userList = new ArrayList<>(); 28 29 //
先静态模拟数据 30 static { 31 User user1 = new User(); 32
user1.setUserId(1L); 33 user1.setUsername(“lufei”); 34
user1.setNickname(“蒙奇D路飞”); 35
user1.setBirthday(Dates.parseDate(“2000-05-05”)); 36
user1.setSex(Constants.Sex.MALE); 37
user1.setEnabled(Constants.Flag.YES); 38 userList.add(user1); 39 40 User
user2 = new User(); 41 user2.setUserId(2L); 42
user2.setUsername(“nami”); 43 user2.setNickname(“娜美”); 44
user2.setBirthday(Dates.parseDate(“2000/7/3”)); 45
user2.setSex(Constants.Sex.FEMALE); 46
user2.setEnabled(Constants.Flag.YES); 47 userList.add(user2); 48 } 49 50
@RequestMapping(“/queryAll”) 51 public Result queryAll(){ 52 return
Results.successWithData(userList, BaseEnums.SUCCESS.code(),
BaseEnums.SUCCESS.description()); 53 } 54 55
@RequestMapping(“/queryOne/{userId}”) 56 public Result
queryOne(@PathVariable Long userId){ 57 User user = null; 58 for(User u
: userList){ 59 if(u.getUserId().longValue() == userId){ 60 user = u; 61
} 62 } 63 return Results.successWithData(user); 64 } 65 } View Code

② Postman请求:请求成功,基础的HTTP服务已经实现了。

 

[java] view
plain
 copy

三、集成MyBatis,实现基础Mapper和Service

 print?

1、添加JDBC、配置数据源

添加spring-boot-starter-jdbc以支持JDBC访问数据库,然后添加MySql的JDBC驱动mysql-connector-java;

澳门新葡亰赌995577 35

在application.properties里配置mysql的数据库驱动

澳门新葡亰赌995577 36

之后在application-dev.properties里配置开发环境数据库的连接信息,添加之后,Springboot就会自动配置数据源了。

澳门新葡亰赌995577 37

  1. package com.x.dao;  
  2.   
  3. import java.util.List;  
  4.   
  5. import com.x.entity.User;  
  6.   
  7. /**  
  8.  * @author http://blog.csdn.net/java2000\_wl  
  9.  * @version <b>1.0</b>  
  10.  */   
  11. public interface IUserDao {  
  12.       
  13.     /** 
  14.      * 新增 
  15.      * <br>——————————<br> 
  16.      * @param user 
  17.      * @return 
  18.      */  
  19.     boolean add(User user);  
  20.       
  21.     /** 
  22.      * 批量新增 使用pipeline方式 
  23.      * <br>——————————<br> 
  24.      * @param list 
  25.      * @return 
  26.      */  
  27.     boolean add(List<User> list);  
  28.       
  29.     /** 
  30.      * 删除 
  31.      * <br>——————————<br> 
  32.      * @param key 
  33.      */  
  34.     void delete(String key);  
  35.       
  36.     /** 
  37.      * 删除多个 
  38.      * <br>——————————<br> 
  39.      * @param keys 
  40.      */  
  41.     void delete(List<String> keys);  
  42.       
  43.     /** 
  44.      * 修改 
  45.      * <br>——————————<br> 
  46.      * @param user 
  47.      * @return  
  48.      */  
  49.     boolean update(User user);  
  50.   
  51.     /** 
  52.      * 通过key获取 
  53.      * <br>——————————<br> 
  54.      * @param keyId 
  55.      * @return  
  56.      */  
  57.     User get(String keyId);  
  58. }  

2、集成MyBatis

MyBatis官方为了方便Springboot集成MyBatis,专门提供了一个符合Springboot规范的starter项目,即mybatis-spring-boot-starter。

澳门新葡亰赌995577 38

在application.properties里添加mybatis映射配置:

澳门新葡亰赌995577 39

[java] view
plain
 copy

3、添加MyBatis通用Mapper

通用Mapper可以极大的简化开发,极其方便的进行单表的增删改查。

澳门新葡亰赌995577 40

关于通用Mapper,参考网站地址:

  MyBatis通用Mapper

  MyBatis 相关工具

之后,在core.base下创建自定义的Mapper,按需选择接口。

具体可参考:根据需要自定义接口

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.base; 2 3 import
tk.mybatis.mapper.common.BaseMapper; 4 import
tk.mybatis.mapper.common.ConditionMapper; 5 import
tk.mybatis.mapper.common.IdsMapper; 6 import
tk.mybatis.mapper.common.special.InsertListMapper; 7 8 /** 9 * 10 *
BaseMapper 11 * 12 * @name BaseMapper 13 * @version 1.0 14 * @author
bojiangzhou 2017-12-31 15 */ 16 public interface Mapper<T>
extends BaseMapper<T>, ConditionMapper<T>,
IdsMapper<T>, InsertListMapper<T> { 17 18 } View Code

定义好基础Mapper后,就具有下图中的基本通用方法了。每个实体类对应的*Mapper继承Mapper<T>来获得基本的增删改查的通用方法。

澳门新葡亰赌995577 42

在application.properties里配置自定义的基础Mapper

澳门新葡亰赌995577 43

 print?

4、添加分页插件PageHelper

澳门新葡亰赌995577 44

参考地址:

  MyBatis 分页插件 – PageHelper

  分页插件使用方法

分页插件配置,一般情况下,不需要做任何配置。

之后,我们就可以在代码中使用 PageHelper.startPage(1, 10)
对紧随其后的一个查询进行分页查询,非常方便。

澳门新葡亰赌995577 45

  1. package com.x.dao.impl;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.springframework.dao.DataAccessException;  
  7. import org.springframework.data.redis.connection.RedisConnection;  
  8. import org.springframework.data.redis.core.RedisCallback;  
  9. import org.springframework.data.redis.serializer.RedisSerializer;  
  10. import org.springframework.util.Assert;  
  11.   
  12. import com.x.dao.AbstractBaseRedisDao;  
  13. import com.x.dao.IUserDao;  
  14. import com.x.entity.User;  
  15.   
  16. /**  
  17.  * Dao 
  18.  * @author http://blog.csdn.net/java2000\_wl  
  19.  * @version <b>1.0</b>  
  20.  */   
  21. public class UserDao extends AbstractBaseRedisDao<String, User> implements IUserDao {  
  22.   
  23.     /**  
  24.      * 新增 
  25.      *<br>——————————<br> 
  26.      * @param user 
  27.      * @return 
  28.      */  
  29.     public boolean add(final User user) {  
  30.         boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
  31.             public Boolean doInRedis(RedisConnection connection)  
  32.                     throws DataAccessException {  
  33.                 RedisSerializer<String> serializer = getRedisSerializer();  
  34.                 byte[] key  = serializer.serialize(user.getId());  
  35.                 byte[] name = serializer.serialize(user.getName());  
  36.                 return connection.setNX(key, name);  
  37.             }  
  38.         });  
  39.         return result;  
  40.     }  
  41.       
  42.     /** 
  43.      * 批量新增 使用pipeline方式   
  44.      *<br>——————————<br> 
  45.      *@param list 
  46.      *@return 
  47.      */  
  48.     public boolean add(final List<User> list) {  
  49.         Assert.notEmpty(list);  
  50.         boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
  51.             public Boolean doInRedis(RedisConnection connection)  
  52.                     throws DataAccessException {  
  53.                 RedisSerializer<String> serializer = getRedisSerializer();  
  54.                 for (User user : list) {  
  55.                     byte[] key  = serializer.serialize(user.getId());  
  56.                     byte[] name = serializer.serialize(user.getName());  
  57.                     connection.setNX(key, name);  
  58.                 }  
  59.                 return true;  
  60.             }  
  61.         }, false, true);  
  62.         return result;  
  63.     }  
  64.       
  65.     /**  
  66.      * 删除 
  67.      * <br>——————————<br> 
  68.      * @param key 
  69.      */  
  70.     public void delete(String key) {  
  71.         List<String> list = new ArrayList<String>();  
  72.         list.add(key);  
  73.         delete(list);  
  74.     }  
  75.   
  76.     /** 
  77.      * 删除多个 
  78.      * <br>——————————<br> 
  79.      * @param keys 
  80.      */  
  81.     public void delete(List<String> keys) {  
  82.         redisTemplate.delete(keys);  
  83.     }  
  84.   
  85.     /** 
  86.      * 修改  
  87.      * <br>——————————<br> 
  88.      * @param user 
  89.      * @return  
  90.      */  
  91.     public boolean update(final User user) {  
  92.         String key = user.getId();  
  93.         if (get(key) == null) {  
  94.             throw new NullPointerException(“数据行不存在, key = ” + key);  
  95.         }  
  96.         boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {  
  97.             public Boolean doInRedis(RedisConnection connection)  
  98.                     throws DataAccessException {  
  99.                 RedisSerializer<String> serializer = getRedisSerializer();  
  100.                 byte[] key  = serializer.serialize(user.getId());  
  101.                 byte[] name = serializer.serialize(user.getName());  
  102.                 connection.set(key, name);  
  103.                 return true;  
  104.             }  
  105.         });  
  106.         return result;  
  107.     }  
  108.   
  109.     /**  
  110.      * 通过key获取 
  111.      * <br>——————————<br> 
  112.      * @param keyId 
  113.      * @return 
  114.      */  
  115.     public User get(final String keyId) {  
  116.         User result = redisTemplate.execute(new RedisCallback<User>() {  
  117.             public User doInRedis(RedisConnection connection)  
  118.                     throws DataAccessException {  
  119.                 RedisSerializer<String> serializer = getRedisSerializer();  
  120.                 byte[] key = serializer.serialize(keyId);  
  121.                 byte[] value = connection.get(key);  
  122.                 if (value == null) {  
  123.                     return null;  
  124.                 }  
  125.                 String name = serializer.deserialize(value);  
  126.                 return new User(keyId, name, null);  
  127.             }  
  128.         });  
  129.         return result;  
  130.     }  
  131. }  

5、配置自动扫描Mapper

在config下创建MyBatisConfig配置文件,通过mapperScannerConfigurer方法配置自动扫描Mapper文件。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.config; 2 3 import
org.springframework.context.annotation.Bean; 4 import
org.springframework.context.annotation.Configuration; 5 6 import
tk.mybatis.spring.mapper.MapperScannerConfigurer; 7 8 /** 9 *
MyBatis相关配置. 10 * 11 * @version 1.0 12 * @author bojiangzhou
2018-01-07 13 */ 14 @Configuration 15 public class MyBatisConfig { 16
17 /** 18 * Mapper扫描配置. 自动扫描将Mapper接口生成代理注入到Spring.
19 */ 20 @Bean 21 public static MapperScannerConfigurer
mapperScannerConfigurer() { 22 MapperScannerConfigurer
mapperScannerConfigurer = new MapperScannerConfigurer(); 23 //
注意这里的扫描路径: 1.不要扫描到自定义的Mapper;
2.定义的路径不要扫描到tk.mybatis.mapper(如定义**.mapper). 24 //
两个做法都会导致扫描到tk.mybatis的Mapper,就会产生重复定义的报错. 25
mapperScannerConfigurer.setBasePackage(“**.lyyzoo.**.mapper”); 26
return mapperScannerConfigurer; 27 } 28 29 } View Code

注意这里的 MapperScannerConfigurer
是tk.mybatis.spring.mapper.MapperScannerConfigurer,而不是org.mybatis,否则使用通用Mapper的方法时会报类似下面的这种错误

澳门新葡亰赌995577 47

[java] view
plain
 copy

6、定义基础Service

一般来说,我们不能在Controller中直接访问Mapper,因此我们需要加上Service,通过Service访问Mapper。

首先定义基础Service<T>接口,根据Mapper定义基本的增删改查接口方法。

澳门新葡亰赌995577 19
1 package com.lyyzoo.core.base; 2 3 import java.util.List; 4 5 /** 6
* Service 基础通用接口 7 * 8 * @name BaseService 9 * @version 1.0 10
* @author bojiangzhou 2017-12-31 11 */ 12 public interface

 print?

Service<T> { 13 14 // 15 // insert 16 //

17 /** 18 * 保存一个实体,null的属性也会保存,不会使用数据库默认值 19
* 20 * @param record 21 * @return 22 */ 23 T insert(T record); 24 25
/** 26 * 批量插入,null的属性也会保存,不会使用数据库默认值 27 * 28
* @param recordList 29 * @return 30 */ 31 List<T>
insert(List<T> recordList); 32 33 /** 34 *
保存一个实体,null的属性不会保存,会使用数据库默认值 35 * 36 * @param
record 37 * @return 38 */ 39 T insertSelective(T record); 40 41 /**
42 * 批量插入,null的属性不会保存,会使用数据库默认值 43 * 44 *
@param recordList 45 * @return 46 */ 47 List<T>

  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3.   
  4. import junit.framework.Assert;  
  5.   
  6. import org.junit.Test;  
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.test.context.ContextConfiguration;  
  9. import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;  
  10.   
  11. import com.x.dao.IUserDao;  
  12. import com.x.entity.User;  
  13.   
  14. /**  
  15.  * 测试 
  16.  * @author http://blog.csdn.net/java2000\_wl  
  17.  * @version <b>1.0</b>  
  18.  */    
  19. @ContextConfiguration(locations = {“classpath*:applicationContext.xml”})  
  20. public class RedisTest extends AbstractJUnit4SpringContextTests {  
  21.       
  22.     @Autowired  
  23.     private IUserDao userDao;  
  24.       
  25.     /** 
  26.      * 新增 
  27.      * <br>——————————<br> 
  28.      */  
  29.     @Test  
  30.     public void testAddUser() {  
  31.         User user = new User();  
  32.         user.setId(“user1”);  
  33.         user.setName(“java2000_wl”);  
  34.         boolean result = userDao.add(user);  
  35.         Assert.assertTrue(result);  
  36.     }  
  37.       
  38.     /** 
  39.      * 批量新增 普通方式 
  40.      * <br>——————————<br> 
  41.      */  
  42.     @Test  
  43.     public void testAddUsers1() {  
  44.         List<User> list = new ArrayList<User>();  
  45.         for (int i = 10; i < 50000; i++) {  
  46.             User user = new User();  
  47.             user.setId(“user” + i);  
  48.             user.setName(“java2000_wl” + i);  
  49.             list.add(user);  
  50.         }  
  51.         long begin = System.currentTimeMillis();  
  52.         for (User user : list) {  
  53.             userDao.add(user);  
  54.         }  
  55.         System.out.println(System.currentTimeMillis() –  begin);  
  56.     }  
  57.       
  58.     /** 
  59.      * 批量新增 pipeline方式 
  60.      * <br>——————————<br> 
  61.      */  
  62.     @Test  
  63.     public void testAddUsers2() {  
  64.         List<User> list = new ArrayList<User>();  
  65.         for (int i = 10; i < 1500000; i++) {  
  66.             User user = new User();  
  67.             user.setId(“user” + i);  
  68.             user.setName(“java2000_wl” + i);  
  69.             list.add(user);  
  70.         }  
  71.         long begin = System.currentTimeMillis();  
  72.         boolean result = userDao.add(list);  
  73.         System.out.println(System.currentTimeMillis() – begin);  
  74.         Assert.assertTrue(result);  
  75.     }  
  76.       
  77.     /** 
  78.      * 修改 
  79.      * <br>——————————<br> 
  80.      */  
  81.     @Test  
  82.     public void testUpdate() {  
  83.         User user = new User();  
  84.         user.setId(“user1”);  
  85.         user.setName(“new_password”);  
  86.         boolean result = userDao.update(user);  
  87.         Assert.assertTrue(result);  
  88.     }  
  89.       
  90.     /** 
  91.      * 通过key删除单个 
  92.      * <br>——————————<br> 
  93.      */  
  94.     @Test  
  95.     public void testDelete() {  
  96.         String key = “user1”;  
  97.         userDao.delete(key);  
  98.     }  
  99.       
  100.     /** 
  101.      * 批量删除 
  102.      * <br>——————————<br> 
  103.      */  
  104.     @Test  
  105.     public void testDeletes() {  
  106.         List<String> list = new ArrayList<String>();  
  107.         for (int i = 0; i < 10; i++) {  
  108.             list.add(“user” + i);  
  109.         }  
  110.         userDao.delete(list);  
  111.     }  
  112.       
  113.     /** 
  114.      * 获取 
  115.      * <br>——————————<br> 
  116.      */  
  117.     @Test  
  118.     public void testGetUser() {  
  119.         String id = “user1”;  
  120.         User user = userDao.get(id);  
  121.         Assert.assertNotNull(user);  
  122.         Assert.assertEquals(user.getName(), “java2000_wl”);  
  123.     }  
  124.   
  125.     /** 
  126.      * 设置userDao 
  127.      * @param userDao the userDao to set 
  128.      */  
  129.     public void setUserDao(IUserDao userDao) {  
  130.         this.userDao = userDao;  
  131.     }  
  132. }
     

insertSelective(List<T> recordList); 48 49 // 50 // update 51 //

52 /** 53 * 根据主键更新实体全部字段,null值会被更新 54 * 55 *
@param record 56 * @return 57 */ 58 T update(T record); 59 60 /** 61
* 批量更新,根据主键更新实体全部字段,null值会被更新 62 * 63 * @param
recordList 64 * @return 65 */ 66 List<T> update(List<T>
recordList); 67 68 /** 69 * 根据主键更新属性不为null的值 70 * 71 *
@param record 72 * @return 73 */ 74 T updateSelective(T record); 75 76
/** 77 * 批量更新,根据主键更新属性不为null的值 78 * 79 * @param
recordList 80 * @return 81 */ 82 List<T>

updateSelective(List<T> recordList); 83 84 // 85 // delete 86 //

87 /** 88 * 根据主键删除 89 * 90 * @param id id不能为空 91 *
@return 92 */ 93 int delete(Long id); 94 95 /** 96 *
根据主键字符串进行删除,类中只有存在一个带有@Id注解的字段 97 * 98 *
@param ids 类似1,2,3 99 */ 100 int delete(String ids); 101 102 /**
103 * 根据主键删除多个实体,ID数组 104 * 105 * @param ids
类似[1,2,3],不能为空 106 */ 107 int delete(Long[] ids); 108 109
/** 110 * 根据实体属性作为条件进行删除 111 * 112 * @param record
113 * @return 114 */ 115 int delete(T record); 116 117 /** 118 *
根据主键删除多个实体 119 * 120 * @param recordList 121 * @return 122
*/ 123 int delete(List<T> recordList); 124 125 // 126 // insert

or update or delete 127 //

128 /** 129 * 根据实体的operate决定哪种操作.
null的属性也会保存,不会使用数据库默认值 130 * 131 * @param record 132
* @return 133 */ 134 T persist(T record); 135 136 /** 137 *
批量操作.根据实体的operate决定哪种操作.
null的属性也会保存,不会使用数据库默认值 138 * 139 * @param recordList
140 * @return 141 */ 142 List<T> persist(List<T>
recordList); 143 144 /** 145 * 根据实体的operate决定哪种操作.
根据主键更新属性不为null的值 146 * 147 * @param record 148 * @return
149 */ 150 T persistSelective(T record); 151 152 /** 153 *
批量操作.根据实体的operate决定哪种操作. 根据主键更新属性不为null的值 154
* 155 * @param recordList 156 * @return 157 */ 158 List<T>
persistSelective(List<T> recordList); 159 160 161 // 162 // select