打开sts开发工具,new -> spring starter project( https://start.spring.io)
选择java.version=8 , packaging=war(war为创建web项目,选择jar则为创建普通java工程) ,language=java
选择spirngboot版本:2.1.4 ,勾选devTool和web选项,点击finish,完成。
<?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>
server: port: 8082 servlet: context-path: / spring: #devtools配置 devtools: restart: exclude: static/** application: name: springmybatis2
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); } }
#日志 logging: level: root: INFO org.springframework.web: INFO org.springframework.jdbc: DEBUG com.tingcream.springmybatis2: DEBUG file: /log/springmybatis/springmybatis2.log
<!--内嵌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>
spring: mvc: view: prefix: /WEB-INF/pages #suffix: .jsp
@Controller public class MyController { @RequestMapping("/helloJsp") public ModelAndView helloJsp() { ModelAndView mv =new ModelAndView("/helloJsp.jsp"); mv.addObject("msg", "你好,springmybatis2!"); return mv ; } }
<%@ 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的starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
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
@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; } }
<!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>
使用spring-boot-starter-aop这种方式配置aop:
- 会自动引入spring-boot-starter.jar、aspectjweaver-1.9.2.jar、spring-aop-5.1.6.RELEASE.jar
- 不会强制使用cglib代理
- 可以配置spring.aop节点了。spring.aop.auto默认为true(开启),spring.aop.proxy-target-class默认为false。即使我们不配置spring.aop节点信息,aop也是开启的。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
spring: aop: auto: true proxy-target-class: true
使用@EnableAspectJAutoProxy 注解这种方式配置aop:
- 需要手动引入spring-aspects、cglib的jar包
- 支持强制使用cglib,并且可以设置暴露目标对象
<!-- 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>
标记@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); } }
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 ; } }
创建项目时默认已配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
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 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>
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
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 的错误 ,有两种解决办法:
- 在jdbc的连接url上拼接参数 serverTimezone=GMT%2B8
- 修改mysql的ini配置文件,指定默认时区
[mysqld] default-time-zone='+08:00'
<!-- 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>
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
<?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>
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); } }
1、经过以上的配置,会让容器自动托管一个类型PlatformTransactionManager的bean,其具体实现类为org.springframework.jdbc.DataSourceTransactionManager。也就是说,经过以上配置后,我们可以在业务代码中使用@Autowired注解注入DataSourceTransactionManager 这个bean了。
2、经过以上的配置,@Transactional注解也可以正常工作使用了。
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--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.3</version> </dependency>
pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql
/** * 分页查询 * @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>
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接口,覆盖我们想覆盖的方法即可。
<!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>
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(); } }
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提供的实现。
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); } }
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; } }
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的starter引入 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
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 配置项。
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 类型的对象。
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)); } }
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); } } }); } }
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); } }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
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有些不同。
- springboot1.x中是application.yml中配置spring.redis.pool项目,而springboot2.x中是配置spring.redis.jedis.pool项
- springboot1.x中配置 RedisCacheManger这个bean 时,需要在构造方法中传入RedisTemplate 对象;而springboot2.x中需要RedisCacheWriter 、 RedisCacheConfiguration等对象
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(); } } }
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(); } }
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); }
<?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 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> <dependency> <groupId>org.messaginghub</groupId> <artifactId>pooled-jms</artifactId> </dependency>
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
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); } }
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; } }
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); } }
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时,有所不同
- pom.xml中需要引入jar不同,springboot2.1.x中为spring-boot-starter-activemq、pooled-jms
- ActiveMQConfig的配置类中注入的connectionFactory对象不同。springboot2.1.x中为 JmsPoolConnectionFactory connectionFactory;
Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1