博客详情

springmybatis2.1.4项目 (原创)

作者: 朝如青丝暮成雪
发布时间:2019-06-15 03:08:10  文章分类:java编程   阅读(927)  评论(0)
[TOC]

一、创建springboot项目(2.1.4)

  1. 打开sts开发工具,new -> spring starter project( https://start.spring.io)

    选择java.version=8 , packaging=war(war为创建web项目,选择jar则为创建普通java工程) ,language=java

  2. 选择spirngboot版本:2.1.4 ,勾选devTool和web选项,点击finish,完成。

pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tingcream</groupId>
    <artifactId>springmybatis2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springmybatis2</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


    </dependencies>

    <build>
    <resources>
         <resource>
            <directory>src/main/java</directory>
            <includes>
             <include>**/*</include>
            </includes>
            <excludes>
               <exclude>**/*.java</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*</include>
            </includes>
            <excludes>
              <exclude>**/*.java</exclude>
            </excludes>
        </resource>
    </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-compiler-plugin</artifactId>
             <configuration>
                <target>1.8</target>   
                <source>1.8</source>
                <encoding>utf-8</encoding>
             </configuration>
          </plugin>
        </plugins>
    </build>

</project>

application.yml 配置

server:
  port: 8082
  servlet:
    context-path: /


spring: 
  #devtools配置
  devtools:
    restart:
      exclude: static/**
  application:
    name: springmybatis2

Springmybatis2Application.java

package com.tingcream.springmybatis2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class Springmybatis2Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Springmybatis2Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Springmybatis2Application.class);
    }     
}

application.yml日志的简单配置

#日志
logging: 
  level: 
    root: INFO
    org.springframework.web: INFO
    org.springframework.jdbc: DEBUG
    com.tingcream.springmybatis2: DEBUG
  file: /log/springmybatis/springmybatis2.log

二、集成jsp视图

1.pom.xml配置

<!--内嵌tomcat支持 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
    <optional>true</optional>
</dependency>
<!-- 引入jsp 、jstl支持  -->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
</dependency>

2.application.yml中配置jsp视图

spring: 
  mvc:
    view:
      prefix: /WEB-INF/pages
      #suffix: .jsp

3.controller示例代码

@Controller
public class MyController {

    @RequestMapping("/helloJsp")
    public ModelAndView  helloJsp() {
        ModelAndView mv =new ModelAndView("/helloJsp.jsp");
        mv.addObject("msg", "你好,springmybatis2!");
        return mv ;
    } 
}

4.helloJsp.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>${msg }</h1>
</body>
</html>

三、集成freemarker视图

1.pom.xml中引入starter

<!-- 引入freemarker的starter  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2.application.yml配置ftl视图

spring: 
  freemarker:
    cache: false
    charset: UTF-8
    content-type: text/html; charset=utf-8
    template-loader-path: /templates/
    request-context-attribute: request
    expose-request-attributes: true
    expose-session-attributes: true
    suffix: .ftl

3.controller示例代码

@Controller
public class MyController {
    @RequestMapping("/helloFtl")
    public ModelAndView  helloFtl() {
        ModelAndView mv =new ModelAndView("/helloFtl");
        List<TUser> list =new ArrayList<>();
        list.add(new TUser(1,"张三","北京"));
        list.add(new TUser(2,"李四","上海"));
        list.add(new TUser(3,"王五","广州"));
        mv.addObject("userList", list);
        return mv ;
    } 
}
package com.tingcream.springmybatis2.user.pojo;

import java.io.Serializable;

public class TUser implements Serializable {

   private static final long serialVersionUID = 1L;
   private Integer id ;
   private String name;
   private String addr;

    public TUser() {
    super();
   }

    public TUser(Integer id, String name, String addr) {
        super();
        this.id = id;
        this.name = name;
        this.addr = addr;
    }

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddr() {
        return addr;
    }
    public void setAddr(String addr) {
        this.addr = addr;
    }  
}

4.HelloFtl.ftl

<!DOCTYPE html>
<html>
<head lang="en">
<title></title>
</head>
<body>
  <div>
     <#list userList as user> 
      id:${user.id},姓名:${user.name},地址:${user.addr} <br />
     </#list>
  </div>
</body>
</html>

四、集成aop(cglib)动态代理支持

配置方式一:使用spring-boot-starter-aop自动化配置

使用spring-boot-starter-aop这种方式配置aop:

  1. 会自动引入spring-boot-starter.jar、aspectjweaver-1.9.2.jar、spring-aop-5.1.6.RELEASE.jar
  2. 不会强制使用cglib代理
  3. 可以配置spring.aop节点了。spring.aop.auto默认为true(开启),spring.aop.proxy-target-class默认为false。即使我们不配置spring.aop节点信息,aop也是开启的。

1.pom.xml配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.application.yml配置

spring:   
  aop:
    auto: true
    proxy-target-class: true

配置方式二:使用@EnableAspectJAutoProxy注解配置(推荐)

使用@EnableAspectJAutoProxy 注解这种方式配置aop:

  1. 需要手动引入spring-aspects、cglib的jar包
  2. 支持强制使用cglib,并且可以设置暴露目标对象

1.pom.xml中引入jar

<!-- spring的织入  aspects  cglib  -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version> 
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib-nodep</artifactId>
    <version>3.2.10</version>
</dependency>

2.springboot启动类配置

标记@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true)

package com.tingcream.springmybatis2;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true) 
public class Springmybatis2Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Springmybatis2Application.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Springmybatis2Application.class);
    } 
}

3.切面示例代码

MyAspect.java

package com.tingcream.springmybatis2.common.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.tingcream.springmybatis2.common.annotation.MyAnnotation;


@Aspect
@Component
@Order(1)
public class MyAspect {

    /** 
     * 切入的方法 表达式
     */
    @Pointcut("execution(public * com.tingcream.springmybatis2..*.*(..)) && "
+ "@annotation(com.tingcream.springmybatis2.common.annotation.MyAnnotation)")
    public void  around(){};


    /**
     * 环绕通知 
     */
    @Around("around()")
    public  Object  doArround(ProceedingJoinPoint point)throws Throwable{
         String methodName = point.getSignature().getName();//方法名称
         MethodSignature ms=  (MethodSignature) point.getSignature();//方法签名
         MyAnnotation anno= ms.getMethod().getAnnotation(MyAnnotation.class);
         String value=anno.value();//获取annotation上标记的value值
         System.out.println("方法名称:"+methodName);
         System.out.println("自定义注解传入的value:"+value);
         return point.proceed();
    }
}

MyAnnotation.java

package com.tingcream.springmybatis.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})//target为method表示该注解只能标记在方法上
public @interface MyAnnotation {
   String value() default "";
}

MyController.java

package com.tingcream.springmybatis2.user.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.tingcream.springmybatis2.common.RetMsg;
import com.tingcream.springmybatis2.common.annotation.MyAnnotation;
import com.tingcream.springmybatis2.user.pojo.TUser;

@Controller
public class MyController {

    @ResponseBody
    @RequestMapping("/")
    public RetMsg index() {
        return RetMsg.success();
    }

    @MyAnnotation("test1")
    @RequestMapping("/helloJsp")
    public ModelAndView  helloJsp() {
        ModelAndView mv =new ModelAndView("/helloJsp.jsp");
        mv.addObject("msg", "你好,springmybatis2!");
        return mv ;
    }

    @MyAnnotation("test2")
    @RequestMapping("/helloFtl")
    public ModelAndView  helloFtl() {
        ModelAndView mv =new ModelAndView("/helloFtl");
        List<TUser> list =new ArrayList<>();
        list.add(new TUser(1,"张三","北京"));
        list.add(new TUser(2,"李四","上海"));
        list.add(new TUser(3,"王五","广州"));
        mv.addObject("userList", list);
        return mv ;
    } 

}

五、集成测试框架(缺省集成)

创建项目时默认已配置

  1. pom.xml中引入
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  1. Springmybatis2ApplicationTests测试类
package com.tingcream.springmybatis2;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Springmybatis2ApplicationTests {

    @Test
    public void contextLoads() {
    } 
}

六、引入jdbc访问数据库

1.pom.xml中引入jdbc的starter

<!-- jdbc starter引入 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- jdbc mysql驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2.application.yml中配置jdbc连接

spring:   
  datasource: 
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/springmybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8

3.jdbc的java测试代码

package com.tingcream.springmybatis2;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.tingcream.springmybatis2.user.dao.StudentDao;
import com.tingcream.springmybatis2.user.model.Student;

@RunWith(SpringRunner.class)
@SpringBootTest
public class Springmybatis2ApplicationTests {

    @Autowired
    private StudentDao studentDao ;

    @Test
    public void test1() {
        Student student = studentDao.findById(1);
        System.out.println(student);
    }
}

springboot2.x中引入的mysql jdbc驱动包是8.x版本。如果报了 DBEAVER连接MySQL运行报错The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more than one time zone 的错误 ,有两种解决办法:

  1. 在jdbc的连接url上拼接参数 serverTimezone=GMT%2B8
  2. 修改mysql的ini配置文件,指定默认时区
[mysqld]
default-time-zone='+08:00'

七、集成druid+mybatis+事务

1.在pom.xml中引入相应jar包

<!-- jdbc starter引入 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- jdbc mysql驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- 引入druid连接池  -->  
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>  

<!-- 引入mybatis的starter  -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>

2.application.yml配置

spring: 
  datasource:
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: 123456
      url: jdbc:mysql://localhost:3306/springmybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false
      initial-size: 5 #初始化连接数
      max-active: 10  #最大活跃连接数
      min-idle: 5 #最小空闲连接数
      max-wait: 60000 #最大连接等待时间 毫秒
      remove-abandoned: true #超过时间限制是否回收
      removeAbandonedTimeout: 1800 #超时丢弃连接 1800秒即30分钟
      timeBetweenEvictionRunsMillis: 60000 #配置时间间隔进行一次检测,毫秒
      validationQuery: SELECT 1 FROM DUAL #用来检测连接是否有效的sql,要求是一个查询语句 
      testWhileIdle: true  #申请连接的时候检测
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true #打开PSCache,并且指定每个连接上PSCache的大小
      maxPoolPreparedStatementPerConnectionSize: 20
      maxOpenPreparedStatements: 20

mybatis:
  config-location: classpath:SqlMapConfig.xml

3.SqlMapConfig.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>
  <settings>
    <!-- 启动延迟加载  积极加载false -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
  </settings>

   <typeAliases>
     <!--   <package name="com.tingcream.springmybatis.model"/> -->
     <!-- 配置实体bean包及其子包,别名为类名的简单名称,首字母大小写均可。如Student或student均可 -->
       <package name="com.tingcream.springmybatis2"/>  
   </typeAliases>

    <mappers>
    <!--配置mapper接口和mapper.xml所在包(包含子包)-->
      <package name="com.tingcream.springmybatis2"/>
    </mappers>

</configuration>

4. springboot启动类配置,标记@MapperScan注解

package com.tingcream.springmybatis2;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy=true,proxyTargetClass=true) 
@MapperScan(basePackages= {"com.tingcream.springmybatis2"})//可多个,含子包,支持通配符
public class Springmybatis2Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Springmybatis2Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Springmybatis2Application.class);
    }     
}

5.事务(@Transactional)已支持

1、经过以上的配置,会让容器自动托管一个类型PlatformTransactionManager的bean,其具体实现类为org.springframework.jdbc.DataSourceTransactionManager。也就是说,经过以上配置后,我们可以在业务代码中使用@Autowired注解注入DataSourceTransactionManager 这个bean了。

2、经过以上的配置,@Transactional注解也可以正常工作使用了。

八、service事务切面的配置(可选)

配置TransactionAopConfig类

package com.tingcream.springmybatis2.configuration;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 * service层的事务切面配置
 * @author jelly
 */
@Component
@Configuration
public class TransactionAopConfig {
      //切面表达式: 切入com.tingcream.springmybatis2下或子包下的service目录下的所有的public级别的方法
      private static final String AOP_POINTCUT_EXPRESSION = "execution (public * com.tingcream.springmybatis2..service.*.*(..))";
      @Autowired
      private PlatformTransactionManager transactionManager;
      @Bean
      public TransactionInterceptor txAdvice() {
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(RuntimeException.class)));
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        requiredTx.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);

        Map<String, TransactionAttribute> txMap = new HashMap<>();
        txMap.put("add*", requiredTx);//需要事务
        txMap.put("save*", requiredTx);//需要事务
        txMap.put("update*", requiredTx);//需要事务
        txMap.put("delete*", requiredTx);//需要事务
        txMap.put("get*", readOnlyTx);//只读事务
        txMap.put("find*", readOnlyTx);//只读事务
        source.setNameMap( txMap );
        TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
        return txAdvice;
      }
      @Bean
      public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
      }
}

九、集成pageHelper(mybatis)分页插件

1.在pom.xml中引入jar

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

2.application.yml中配置

pagehelper:
  helperDialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql

3.示例代码

/**
* 分页查询
* @param page
* @return
*/
public PageInfo<Student> findStudentList(Page page) {
    PageHelper.startPage(page.getPageNum(), page.getPageSize());
    List<Student> list = studentMapper.findList();
    return new PageInfo<Student>(list);
}
<select id="findList" resultType="Student">
     select * from t_student 
 </select>

十、配置全站允许CORS跨域请求(可选)

1.配置WebConfig类

package com.tingcream.springmybatis2.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * web配置信息,可配置mvc拦截器,web过滤器 等
 * @author jelly
 */
@Configuration
public class WebConfig implements WebMvcConfigurer{

       /**
        * 配置全站允许CORS跨域访问
        */
        @Override
        public void addCorsMappings(CorsRegistry registry) {   
            registry.addMapping("/**") 
                    .allowedOrigins("*") //允许的来源域  如http://www.demo.com 
                    .allowedMethods("GET", "POST")
                    .allowCredentials(false).maxAge(3600);
        }
}

在springboot2.x中,因为大量使用到了JDK8的新特性,springboot团队给WebMvcConfigurer接口方法都声明为了default方法了。因此,这里我们不需要继承WebMvcConfigurerAdapter 这个缺省适配器类。实际上,WebMvcConfigurerAdapter 已被标记为过时的类了。我们直接实现WebMvcConfigurer接口,覆盖我们想覆盖的方法即可。

2.测试代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
          <button onclick="req()">请求服务器</button>    
    </body>
</html>
<script src="../js/jQuery-2.1.4.min.js"></script>
<script>
     function req(){
         $.ajax({
             type:"post",
             url:"http://localhost:8081/",
             async:true,
             success:function(data){
                 console.log(data);
             }
         });
     }
</script>

十一、配置controller层参数校验(JSR303)

1.配置ValidatorConfig配置类

package com.tingcream.springmybatis2.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

/**
 * 参数校验配置
 * @author jelly
 */
@Configuration
public class ValidatorConfig {
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }
}

2.controller层代码

package com.tingcream.springmybatis2.user.controller;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tingcream.springmybatis2.common.RetMsg;
import com.tingcream.springmybatis2.user.model.UserAddReq;

/**
 * 用户管理 controller
 * @author jelly
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/add")
    public  RetMsg add(@Validated UserAddReq req) {
        System.out.println("请求/user/add");
        return RetMsg.success();
    }
}
package com.tingcream.springmybatis2.user.model;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

//import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
//import org.hibernate.validator.constraints.NotBlank;

/**
 * 用户添加req对象
 * @author jelly
 *
 */
public class UserAddReq  {
    @NotBlank(message="用户名不能为空")
    @Length(min=1,max=32,message="用户名长度为1~32位")
    private String username;

    @NotBlank(message="密码不能为空")
    @Pattern(regexp="^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,32}$",
    message="密码长度为6~32位,且必须包含字母和数字") 
    private String password;

    @NotBlank(message="手机号不能为空")
    @Pattern(regexp = "^(13|14|15|16|17|18|19)[0-9]{9}$", message = "手机号格式错误")
    private String phone;

    @NotBlank(message="邮箱号不能为空")
    @Email(message="邮箱号格式错误")
    @Length(min=1,max=50,message="邮箱号长度为1~50位")
    private String email;

    @NotBlank(message="地址不能为空")
    @Length(message="地址长度为1~50位")
    private String addr;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getAddr() {
        return addr;
    }
    public void setAddr(String addr) {
        this.addr = addr;
    }    
}

springboot2.x 中JSR303验证规范中,使用javax.validation.constraints标准的Email、NotBlank注解代替了hibernate提供的实现。

3.全局异常处理器(BindException)

GlobalExceptionHandler.java 处理BindException异常

package com.tingcream.springmybatis2.common.exception;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.tingcream.springmybatis2.common.RetMsg;

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
    private Logger logger =LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(BindException.class)
    public RetMsg  handleBindException(BindException e,HttpServletRequest request) {
        logger.error(e.getMessage(),e);//记录完整错误信息
        Map<String,String> map=new HashMap<String,String>();
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        errors.stream().forEach((ObjectError err)->{
            String field= ((FieldError)err).getField();
            String msg =err.getDefaultMessage();
            map.put(field,msg);
        });
        return new RetMsg(999, "请求参数验证失败", map);
    }
}

十二、springTask定时任务使用(可选)

1.配置SchedulerConfig类

package com.tingcream.springmybatis2.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
@EnableScheduling// 开启定时任务调度
public class SchedulerConfig {
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        //线程池大小
        scheduler.setPoolSize(10);
        //线程名字前缀
        scheduler.setThreadNamePrefix("spring-task-thread");
        return scheduler;
    }
}

2.业务job

package com.tingcream.springmybatis2.job;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * spring任务bean
 */
@Component
public class MyJob {
    private int count=0;
    @Scheduled(cron="*/2 * * * * ?")
    private void run(){
         count++;
        System.out.println("[" + Thread.currentThread().getName() + "]" + "MyJob 执行次数: "+(count));
    }
}

十三、集成redis

1.pom.xml中引入redis的starter

<!-- redis的starter引入 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.application.yml配置

spring:   
  redis: 
    host: 192.168.11.10
    port: 6379
    password: 123456
    ssl: false
    database: 0
    timeout: 6000
    jedis:
      pool:
        max-active: 8 #缺省值8
        max-idle: 8 #缺省值8
        min-idle: 0 #缺省值0
        max-wait: 3000 #缺省值-1

注意:springboot2.x中集成redis中,原来的spring.redis.pool配置项改为了spring.redis.jedis.pool 配置项。

3.配置RedisConfig类

package com.tingcream.springmybatis2.configuration;

import java.io.Serializable;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;

import com.tingcream.springmybatis2.common.redis.MyRedisKeySerializer;
import com.tingcream.springmybatis2.common.redis.RedisHelper;

@Configuration
public class RedisConfig {

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Bean
    public RedisTemplate<Serializable, Object> redisTemplate(RedisConnectionFactory  connectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        //StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        MyRedisKeySerializer  myRedisKeySerializer =new MyRedisKeySerializer();

        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(myRedisKeySerializer);//键
        redisTemplate.setHashKeySerializer(myRedisKeySerializer);//键
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);//值
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);//值
        return redisTemplate;
    }

    @Bean
    public RedisHelper redisHelper(RedisTemplate<Serializable, Object> redisTemplate) {
        RedisHelper redisHelper = new RedisHelper();

        redisHelper.setRedisTemplate(redisTemplate);
        return redisHelper;
    }

}

注意:在springboot2.x中集成redis,配置RedisTemplate bean时,接收的方法参数为RedisConnectionFactory类型的对象而不是JedisConnectionFactory 类型的对象。

4.MyRedisKeySerializer.java

package com.tingcream.springmybatis2.common.redis;

import java.io.Serializable;
import java.nio.charset.Charset;

import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

/**
 * 自定义的redis key序列化类
 *  key的可以为 String 、Integer、 Long 类型
 * @author jelly
 *
 */
public class MyRedisKeySerializer  implements RedisSerializer<Serializable> {

    private final Charset charset=Charset.forName("UTF8");

    @Override
    public byte[] serialize(Serializable t) throws SerializationException {
           if( t instanceof String) {
               String s = (String)t;
               return  (s == null ? null : s.getBytes(charset));
           }else if( t instanceof Integer) {
               String s=  String.valueOf((Integer) t);
               return  (s == null ? null : s.getBytes(charset));
           }else if( t instanceof Long) {
               String s=  String.valueOf((Long) t);
               return  (s == null ? null : s.getBytes(charset));
           }
        return null;
    }

    @Override
    public Serializable deserialize(byte[] bytes) throws SerializationException {
        return (bytes == null ? null : new String(bytes, charset));
    }
}

5.RedisHelper.java

package com.tingcream.springmybatis2.common.redis;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

/**  
* redis 辅助工具类
* @author jelly
*/
public class RedisHelper {

      private RedisTemplate<Serializable, Object> redisTemplate; 
      public void setRedisTemplate(  RedisTemplate<Serializable, Object> redisTemplate) { 
        this.redisTemplate = redisTemplate; 
      } 
      public RedisTemplate<Serializable, Object> getRedisTemplate() {
        return redisTemplate;
      }

      /**
       * hash set
       * @param key
       * @param field
       * @param value
       */
      public  void     hset(String key ,String field,Object value){
            BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
            hashOperation.put(field, value);
      }    
      /**
       * hash  set  with ttlSec
       * @param key
       * @param field
       * @param value
       * @param ttl
       */
      public   void   hset(String key ,String field,Object value,long ttl){
            BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
            hashOperation.put(field, value);
            redisTemplate.expire(key, ttl, TimeUnit.SECONDS);
      }

      /**
       * hash  get
       * @param key
       * @param field
       * @return
       */
      public  Object   hget(String key,String field){
          BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
          return   hashOperation.get(field);
      }
      /**
       * hash  hdel  field
       * @param key
       * @param field
       */
      public  void hdel(String key,Object field){
          BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
           hashOperation.delete(field);
      }
      /**
       * hash  hdel  field1  field2
       * @param key
       * @param fields
       */
      public  void hdel(final String key,final Object... fields){
          BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
          hashOperation.delete(fields);
      }

      /**
       * hash hlen
       * @param key
       * @return
       */
      public  Long    hlen(String key){
          BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
         return  hashOperation.size();
      }
      /**
       * hash  hkeys
       * @author jelly
       * @date 2018年10月10日 下午5:04:57
       * @param key
       * @return
       */
      public  Set<String> hkeys(String key){
          BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
         return  hashOperation.keys();
      }
      /**
       * hash hvals
       * @param key
       * @return
       */
      public   List<Object> hvals(String key){
            BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
             return  hashOperation.values();
      }
      /**
       * hash  hgetall
       * @param key
       * @return
       */
      public   Map<String,Object> hgetall(String key){
               BoundHashOperations<Serializable, String, Object> hashOperation=  redisTemplate.boundHashOps(key);
             return  hashOperation.entries();
      }

      /**
       * 传入 多个key   
       * key1 key2 key3
       */
      public void remove(final String... keys) { 

        for (String key : keys) { 
          remove(key); 
        } 
      } 
      /** 
       * 批量删除key  根据匹配的parttern   
       * 如 mylist*   能匹配 mylist1 mylist2  
       */
      public void removePattern(final String pattern) { 
        Set<Serializable> keys = redisTemplate.keys(pattern); 
        if (keys.size() > 0) {
            redisTemplate.delete(keys);
        }

      } 

      /**
       * 删除key-Object  根据传入的key
       */
      public void remove(final String key) { 
          redisTemplate.delete(key); 
      } 

      /**
       * 判断缓存中是否存在 指定的key
       */
      public boolean exists(final String key) { 
        return redisTemplate.hasKey(key); 
      } 

      /** 
       * 读取缓存 
       * @param key 
       * @return 
       */
      public Object get(final String key) { 
        Object result = null; 
        ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); 
        result = operations.get(key); 
        return result; 
      } 

      /**
       * set 
       * @author jelly
       * @param key
       * @param value
       */
      public void set(final String key, Object value) { 
        try { 
          ValueOperations<Serializable, Object> operations = redisTemplate .opsForValue(); 
          operations.set(key, value); 
        } catch (Exception e) { 
           e.printStackTrace();
        } 
      } 

      /**
       * set 
       * @param key
       * @param value
       * @param ttl
       */
      public void set(final String key, Object value, Long ttl) { 
          ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); 
          operations.set(key, value, ttl, TimeUnit.SECONDS) ;
          redisTemplate.expire(key, ttl, TimeUnit.SECONDS);//
      } 
      public boolean expireKey(final String key, Long ttl){
          return  redisTemplate.expire(key, ttl, TimeUnit.SECONDS);
      }

      /**
       * 清空redis当前db
       */
      public void flushDB(){
          redisTemplate.execute(new RedisCallback<String>() {

                @Override
                public String doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    try {
                        connection.flushDb();
                        return "";
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                }

            });
      }
      /**
       * 清空redis所有 db
       */
      public void flushAll(){
          redisTemplate.execute(new RedisCallback<String>() {

                @Override
                public String doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    try {
                        connection.flushAll();
                        return "";
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                }

        });
      }
}

6.RedisController测试类

package com.tingcream.springmybatis2.user.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tingcream.springmybatis2.common.RetMsg;
import com.tingcream.springmybatis2.common.redis.RedisHelper;

/**
 * redis测试controller
 * @author jelly
 */
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisHelper redisHelper ;

    @RequestMapping("/hset")
    public RetMsg hset(String key,String field,String value) {

        redisHelper.hset(key, field, value);
        return RetMsg.success();
    }
    @RequestMapping("/hget")
    public RetMsg hget(String key,String field) {
        Object value = redisHelper.hget(key, field); 
        return RetMsg.success(value);
    }    
}

十四、集成spring cache(redis)

1.pom.xml中引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.SpringCacheConfig配置类

package com.tingcream.springmybatis2.configuration;



import java.time.Duration;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableCaching
@AutoConfigureAfter(RedisConfig.class)
public class SpringCacheConfig extends CachingConfigurerSupport  {

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        StringRedisSerializer keySerializer = new StringRedisSerializer();
        GenericJackson2JsonRedisSerializer valueSerializer=     new  GenericJackson2JsonRedisSerializer();

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(1800))//设置默认缓存key有效期30分钟
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
                //.disableKeyPrefix() //禁用缓存名称前缀 (cacheName::),在springboot2.1.4中默认情况下key是会自动拼接上前缀cacheName::的。
                .disableCachingNullValues();


        RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();

        return redisCacheManager;
    }


     /**
     * 自动生成redisKey规则
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(":");
            sb.append(method.getName());
            for (Object param : params) {
                sb.append(":" + param.toString());
            }
            String rediskey = sb.toString();
            System.out.println("自动生成redis key:"+rediskey);
            return rediskey;
        };
    }
}

注意:springboot2.x中配置redis和springCache与springboot1.x有些不同。

  1. springboot1.x中是application.yml中配置spring.redis.pool项目,而springboot2.x中是配置spring.redis.jedis.pool项
  2. springboot1.x中配置 RedisCacheManger这个bean 时,需要在构造方法中传入RedisTemplate 对象;而springboot2.x中需要RedisCacheWriter 、 RedisCacheConfiguration等对象

3.测试代码

UserController.java

package com.tingcream.springmybatis2.user.controller;

import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.tingcream.springmybatis2.common.RetMsg;
import com.tingcream.springmybatis2.user.model.User;
import com.tingcream.springmybatis2.user.service.UserService;

/**
 * 用户管理 controller
 * @author jelly
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private CacheManager cacheManager ;

    @RequestMapping("/add")
    public  RetMsg add(User user) {
         User u = userService.addUser(user);
        return RetMsg.success(u);
    }
    @RequestMapping("/update")
    public RetMsg  update(User user) {
         User u =userService.updateUser(user);
        return  RetMsg.success(u);

    }
    @RequestMapping("/findById")
    public RetMsg findById(Integer id) {
         User user = userService.findById(id);
         return  RetMsg.success(user);
    }
    @RequestMapping("/deleteById")
    public RetMsg deleteById(Integer id) {
        int  count= userService.deleteById(id);
        if(count>0) {
            return  RetMsg.success();
        }else {
            return RetMsg.fail();
        }
    }
    @RequestMapping("/deleteAll")
    public RetMsg deleteAll() {
        userService.deleteAll();
        return RetMsg.success();
    }

    @RequestMapping("/findUsers")
    public RetMsg findUsers(@RequestParam(defaultValue="") String username,
            @RequestParam(defaultValue="")String addr) {
       List<User> list=    userService.findUsers(username, addr);
       return RetMsg.success(list);
    }

    @RequestMapping("/getUserFromCache")
    public RetMsg getUserFromCache(Integer id) {
        Collection<String> cacheNames= cacheManager.getCacheNames();
        System.out.println("cacheNames:"+cacheNames);
        Cache cache = cacheManager.getCache("user");
        System.out.println(cache);
        ValueWrapper w =   cacheManager.getCache("user").get(id);
        if(w!=null) {
            return RetMsg.success(w.get());
        }else {
            return RetMsg.fail();
        }
    }    
}

UserService.java

package com.tingcream.springmybatis2.user.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.tingcream.springmybatis2.user.mapper.UserMapper;
import com.tingcream.springmybatis2.user.model.User;


@Service
@CacheConfig(cacheNames="user")
public class UserService {
     @Autowired
     private UserMapper userMapper ;

    /**
     * 新增  缓存key为用户id
     * @param user
     * @return
     */
    @CachePut(key="#result.userId")
    public User addUser(User user) {
        user.setCreateTime(new Date());
        userMapper.save(user);
        return user;
    }
    /**
     * 修改 缓存key为用户id
     * @param user
     * @return
     */
    @CachePut(key="#result.userId",condition="#user.userId!=null")
    public User updateUser(User user) {
          if(user.getUserId()==null) {
              throw new RuntimeException("修改用户,用户id不能为空");
          }
          userMapper.update(user);
          return userMapper.findById(user.getUserId());
    }

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @Cacheable(key="#id")
    public User findById(Integer id) {
        System.out.println("findById方法调用");
        return userMapper.findById(id);
    }

    /**
     * 根据id删除
     * @param id
     * @return
     */
    @CacheEvict(key="#id")
    public int deleteById(Integer id) {
        return userMapper.deleteById(id);
    }

    /**
     * 根据用户名、地址等条件模糊查询 用户列表
     * @param username 用户名
     * @param addr 地址
     * @return
     */
    @Cacheable(keyGenerator="keyGenerator")
    //注: 这个keyGenerator是在SpringCacheConfig配置类中配置了的bean(缺省使用),故这里也省略。否则需要我们配置自定义的key生成器bean以供使用。
    public List<User> findUsers(String username,String addr){
        System.out.println("findUsers方法执行");
         Map<String,Object> map =new HashMap<String,Object>();
         map.put("username", username);
         map.put("addr", addr);
         return  userMapper.findUsers(map);

    }

    /**
     * 清除所有
     */
    @CacheEvict(allEntries=true)
    public void deleteAll() {
        System.out.println("清除所有");
        userMapper.deleteAll();

    } 
}

UserMapper.java

package com.tingcream.springmybatis2.user.mapper;

import java.util.List;
import java.util.Map;

import com.tingcream.springmybatis2.user.model.User;

public interface UserMapper {
    public List<User> findAll();          
       public int save(User user);      
       public int update(User user);     
       public int deleteById(int id); 
       public User findById(int id);
    public void deleteAll();

    public List<User> findUsers(Map<String, Object> map);        
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper 
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.tingcream.springmybatis2.user.mapper.UserMapper" > 

   <insert id="save" parameterType="User" keyProperty="userId" useGeneratedKeys="true"> 
       INSERT INTO t_user(`userId`,`username`,`password`,`phone`,`email`,`addr`,`createTime`) 
       VALUES(#{userId},#{username},#{password},#{phone},#{email},#{addr},#{createTime}) 
   </insert>
   <select id="findAll" resultType="User">
        SELECT  * FROM t_user 
   </select> 
   <update id="update" parameterType="User"> 
       update  t_user t 
      <set>
      <if test="username!=null and username!='' " >
        t.username=#{username}, 
      </if>
      <if test="password!=null and password!='' " >
        t.password=#{password}, 
      </if>
      <if test="phone!=null and phone!='' " >
        t.phone=#{phone}, 
      </if>
      <if test="email!=null and email!='' " >
        t.email=#{email}, 
      </if>
      <if test="addr!=null and addr!='' " >
        t.addr=#{addr}, 
      </if>
      <if test="createTime!=null and createTime!='' " >
        t.createTime=#{createTime}, 
      </if>
     </set>
     where t.userId=#{userId} 
   </update>
   <select id="findById" parameterType="int" resultType="User"> 
      SELECT  * FROM `t_user` t WHERE t.`userId`=#{_parameter} 
    </select> 
   <delete id="deleteById" parameterType="int">  
      DELETE  FROM  t_user    WHERE userId=#{_parameter} 
   </delete> 
   <delete id="deleteAll">
     TRUNCATE TABLE t_user
   </delete>
   <select id="findUsers" parameterType="map" resultType="User">
      SELECT  * FROM `t_user` t  
      <where>
          <if test="username!=null and username!=''">
                   and  t.username like  concat('%',#{username},'%')
           </if>
          <if test="addr!=null and addr!=''">
                   and  t.addr like  concat('%',#{addr},'%')
           </if>
      </where>
    </select>
</mapper>

十五、集成activemq(JMS)

1.pom.xml中引入相关jar

<!-- 集成activemq -->
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-activemq</artifactId>  
</dependency>  
<dependency>
    <groupId>org.messaginghub</groupId>
    <artifactId>pooled-jms</artifactId>
</dependency>

2.application.yml配置

spring: 
  activemq: 
    broker-url: tcp://192.168.11.10:61616
    user: admin
    password: admin
    packages:
      trust-all: true 
    pool: 
      enabled: true
      max-connections: 50
      idle-timeout: 30000
  #默认情况下,activemq使用的是queue模式,如果要使用topic模式,必须设置为true
  jms:
    pub-sub-domain: true

3.ActiveMQConfig配置类

package com.tingcream.springmybatis2.configuration;

import javax.jms.Queue;
import javax.jms.Topic;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;


/**
 * activemq 配置
 * @author jelly
 */
@Configuration
public class ActiveMQConfig {

    @Autowired
    private JmsPoolConnectionFactory connectionFactory;

    public  final static String QUEUE_ORDER = "queue.order";//订单队列
    public  final static String QUEUE_ORDER_OUT = "queue.order.out";//订单回执队列

    public  final static String TOPIC_LOG = "topic.log";//日志收集  主题
    public  final static String JMS_LISTENER_CONTAINER_QUEUE="jmsListenerContainerQueue";
    public  final static String JMS_LISTENER_CONTAINER_TOPIC="jmsListenerContainerTopic";

    @Bean
    public Queue   queueOrder() {
         return  new ActiveMQQueue(QUEUE_ORDER);
    }

    @Bean
    public  Topic  topicLog() {
        return new ActiveMQTopic(TOPIC_LOG);
    }

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerQueue() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        return factory;
    }

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic( ) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true);
        return factory;
    }

    @Bean
    public JmsMessagingTemplate jmsMessagingTemplate() {
        return new JmsMessagingTemplate(connectionFactory);
    }

}

4.java示例代码

queue(订单队列)

package com.tingcream.springmybatis2.jms;

import javax.jms.Queue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

import com.tingcream.springmybatis2.configuration.ActiveMQConfig;

@Component
public class OrderProducer {
    private Logger logger =LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Autowired
    private Queue queueOrder ;//订单队列对象

     public void sendMsg(String msg) {
         jmsMessagingTemplate.convertAndSend(queueOrder, msg);
     }

     @JmsListener(destination = ActiveMQConfig.QUEUE_ORDER_OUT,containerFactory=ActiveMQConfig.JMS_LISTENER_CONTAINER_QUEUE)
     public void backMessage(String msg) {
         logger.info("订单回执消息 --> {} ", msg);
     }

}
package com.tingcream.springmybatis2.jms;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;

import com.tingcream.springmybatis2.configuration.ActiveMQConfig;

@Component
public class OrderConsumer {
    private Logger logger =LoggerFactory.getLogger(this.getClass());


    @JmsListener(destination = ActiveMQConfig.QUEUE_ORDER,containerFactory=ActiveMQConfig.JMS_LISTENER_CONTAINER_QUEUE)
    @SendTo(ActiveMQConfig.QUEUE_ORDER_OUT)  
    public String onQueueMessage(String msg) {
        logger.info("接收到queue.order消息:{}",msg);
        return "回执消息:"+msg;
    }     
}

topic(日志主题)

package com.tingcream.springmybatis2.jms;

import javax.jms.Topic;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

@Component
public class LogProducer {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Autowired
    private Topic topicLog;//

    public void sendMsg(String msg) {
        jmsMessagingTemplate.convertAndSend(topicLog, msg);
    }
}
package com.tingcream.springmybatis2.jms;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import com.tingcream.springmybatis2.configuration.ActiveMQConfig;

@Component
public class LogConsumer {
    private Logger logger =LoggerFactory.getLogger(this.getClass());

    @JmsListener(destination = ActiveMQConfig.TOPIC_LOG,containerFactory=ActiveMQConfig.JMS_LISTENER_CONTAINER_TOPIC)
    public void onMessage(String msg) {
        logger.info("接收到topic.log消息:{}",msg);
    }

}

JmsController

package com.tingcream.springmybatis2.user.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tingcream.springmybatis2.common.RetMsg;
import com.tingcream.springmybatis2.jms.LogProducer;
import com.tingcream.springmybatis2.jms.OrderProducer;

@RestController
@RequestMapping("/jms")
public class JmsController {
    @Autowired
    private OrderProducer orderProducer ;
    @Autowired
    private LogProducer LogProducer;

    /**
     * 订单消息 queue
     * @param msg
     * @return
     */
    @RequestMapping("/orderMsg")
    public RetMsg  orderMsg(String msg) {
        orderProducer.sendMsg(msg);
        return  RetMsg.success();
    }

    /**
     * 日志消息  topic
     * @param msg
     * @return
     */
    @RequestMapping("/logMsg")
    public RetMsg  logMsg(String msg) {
        LogProducer.sendMsg(msg);
        return  RetMsg.success();
    }    
}

注意事项

springboot2.1.x与springboot1.x在配置集成activemq时,有所不同

  1. pom.xml中需要引入jar不同,springboot2.1.x中为spring-boot-starter-activemq、pooled-jms
  2. ActiveMQConfig的配置类中注入的connectionFactory对象不同。springboot2.1.x中为 JmsPoolConnectionFactory connectionFactory;
关键字:  springmybatis
评论信息
暂无评论
发表评论

亲,您还没有登陆,暂不能评论哦! 去 登陆 | 注册

博主信息
   
数据加载中,请稍候...
文章分类
   
数据加载中,请稍候...
阅读排行
 
数据加载中,请稍候...
评论排行
 
数据加载中,请稍候...

Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1

鄂公网安备 42011102000739号