@SendLin
2018-07-11T09:10:45.000000Z
字数 51639
阅读 1491
Springboot 配置文件读取 properties jpa 自定义异常
Springboot 项目的Application.java文件是程序的入口所以其位置应与所有的Java文件的"包"同级,以防止bean未被扫描到@Autowired注入失败粗体文本
1、http://start.spring.io/ 下载自己想要的模板,注意各种jar版本问题
2、关于SpringBoot的热部署配置及依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><version>2.0.2.RELEASE</version><optional>true</optional><scope>true</scope></dependency><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork></configuration></plugin>
application.propertiesapplication.properties
#tomcat portserver.port=8080server.servlet.context-path=/spring-boot/
Java
@Autowiredprivate Environment environment;@RequestMapping("context")Object getContext(){return environment.getProperty("server.port");}
config.properties(文件名随意)config.properties
config.ip=192.168.1.1config.port=8080
java代码domain
@Component@PropertySource(value = "classpath:/config.properties")//由于@ConfigurationProperties的locations 属性被移除所以无法指定配置文件路径,由此藉由@PropertySource方法代替@ConfigurationProperties(prefix="config")public class config {@NotEmptyprivate String ip;private int port;public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}public int getPort() {return port;}public void setPort(int port) {this.port = port;}}
Java代码Controller
@Autowiredprivate config config;@RequestMapping("/configPorperties")Object getport(){return config;}
import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.ImportResource;@Configuration//相当于<beans>标签可以与@bean(相当于<bean>)配合@ImportResource(locations = {"classpath:MyXml.xml"})//指定文件路径即可加载XML文件配置public class AllConfigs {}
pom依赖
<!--返回xml格式的内容--><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.jaxrs/jackson-jaxrs-xml-provider --><dependency><groupId>com.fasterxml.jackson.jaxrs</groupId><artifactId>jackson-jaxrs-xml-provider</artifactId><version>2.9.5</version></dependency>
在controller的类上加@RestController注解默认输出JSON格式的数据,导入以上jar包可输出xml格式
spring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.jpa.properties.hibernate.hbm2ddl.auto=updatespring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialectspring.jpa.show-sql= true
其实这个hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构,有四个值:
create: 每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
@Entitypublic class User implements Serializable {private static final long serialVersionUID = 1L;@Id@GeneratedValueprivate Long id;@Column(nullable = false, unique = true)private String userName;@Column(nullable = false)private String passWord;@Column(nullable = false, unique = true)private String email;@Column(nullable = true, unique = true)private String nickName;@Column(nullable = false)private String regTime;//省略getter settet方法、构造方法}
dao只要继承JpaRepository类就可以,几乎可以不用写方法,还有一个特别有尿性的功能非常赞,就是可以根据方法名来自动的生产SQL,比如findByUserName 会自动生产一个以 userName 为参数的查询方法,比如 findAlll 自动会查询表里面的所有数据,比如自动分页等等。。
Entity中不映射成列的字段得加@Transient 注解,不加注解也会映射成列
public interface UserRepository extends JpaRepository<User, Long> {User findByUserName(String userName);User findByUserNameOrEmail(String username, String email);List<User> findAllByUserName(String userName);List<User> findByUserNameAndRegTime(String name,String time);List<User> findByUserNameOrRegTime(String name,String time);@Transactional//不加Transactional会报错@Modifying@Query("update User u set u.userName = ?1 where u.userName = ?2")//sql语句拼写的方式是以对象名.属性的方式进行查询int modifyByUserName(String userName,String userName1);
Controller代码
@RequestMapping(value = "getUserList/{zz}/{size}", method = RequestMethod.GET)public List<User> getUserList(@PathVariable(name = "zz") Integer zz, @PathVariable(name = "size") Integer size) {List lst = new ArrayList<>();Pageable pageable = new PageRequest(zz, size);Page<User> page = userRepository.findAll(pageable);Iterator<User> iterator = page.iterator();while (iterator.hasNext()) {lst.add(iterator.next());}lst.add(String.format("=========第 %s 页===========", pageable.getPageNumber()));lst.add(String.format("=========有 %s 条数据===========", pageable.getPageSize()));return lst;}@RequestMapping(value = "Delete/{id}", method = RequestMethod.GET)public Object DeleteUser(@PathVariable(name = "id") Long id) {userRepository.deleteById(id);return "SUCCESS";}@RequestMapping(value = "Count",method = RequestMethod.GET)public Object contUser(){return userRepository.count();}@RequestMapping(value = "findAnd/{name}/{time}",method = RequestMethod.GET)public Object findAnd(@PathVariable(name = "name")String name,@PathVariable(name = "time") String time){return userRepository.findByUserNameAndRegTime(name, time);}@RequestMapping(value = "findOr/{name}/{time}",method = RequestMethod.GET)public Object findOr(@PathVariable(name = "name")String name,@PathVariable(name = "time") String time){return userRepository.findByUserNameOrRegTime(name, time);}@RequestMapping(value = "updateUser/{name}/{name1}",method = RequestMethod.GET)public Object updateUser(@PathVariable(name = "name")String name,@PathVariable(name = "name1") String name1){int num = userRepository.modifyByUserName(name,name1);return num > 0 ? "SUCCESS" : "FAILURE";}//利用该对象进行@PersistenceUnitprivate EntityManagerFactory entityManagerFactory;@RequestMapping("/leftJoin")public Object LeftJoin() {String sql = "select u.id,u.userName,u.passWord,u.email,u.nickName,u.regTime,i.id,i.message,i.user from User u left join Interest i on u.id = i.user";//sql是以对象.属性的方法进行语句拼写return entityManagerFactory.createEntityManager().createQuery(sql).getResultList();}
使用注解的方法生成外键约束
package com.example.demo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import javax.persistence.*;import java.io.Serializable;@Entity@AllArgsConstructor//生成全参构造器@Data//生成get set toString equal 方法@NoArgsConstructor //生成无参构造器public class User implements Serializable{@Transientprivate static final long serialVersionUID = 1L;@Id@GeneratedValueprivate Long id;@Column(nullable = false, unique = true)private String userName;@Column(nullable = false)private String passWord;@Column(nullable = false, unique = true)private String email;@Column(nullable = true, unique = true)private String nickName;@Column(nullable = false)private String regTime;}-----------------------------------------------------------------package com.example.demo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import javax.persistence.*;import java.io.Serializable;@Data@NoArgsConstructor@AllArgsConstructor@Entitypublic class Interest implements Serializable{@Id@GeneratedValue@Column(name = "Interest_id")private Long id;@OneToOne//声明表与表的关系@JoinColumn(name = "user_id")//声明外键约束额字段名private User user;//声明外键约束的对应实体类@Column()private String message;}
controller类的方法
@RequestMapping("/saveIn")public Object saveInterest() {User user = new User(17L, "211", "211", "121", "211", "121");interestRepository.save(new Interest(11111L, user, "this is messagie"));return "SUCCESS";}
实体类声明@Entity 关系型数据库支持类型、声明@Document为mongodb支持类型,不同的数据源使用不同的实体就可以了,但如果一个类同时是两个数据库类型的映射类,那么两个注解也能同时混用,也可以通过对不同的包路径进行声明,比如A包路径下使用mysql,B包路径下使用mongoDB
@EnableJpaRepositories(basePackages = "com.neo.repositories.jpa")@EnableMongoRepositories(basePackages = "com.neo.repositories.mongo")interface Configuration { }
package com.example.util;public class GlobalException extends Exception {private int code;public int getCode() {return code;}public void setCode(int code) {this.code = code;}public GlobalException(String message) {super(message);}public GlobalException(String message,int code){super(message);this.code = code;}}//自定义枚举异常代码package com.example.util;public enum ResponseCode {PARAM_ERROR_CODE(400),SERVER_ERROR_CODE(500);private int code;public int getCode() {return code;}public void setCode(int code) {this.code = code;}private ResponseCode(int code) {this.code = code;}}//自定义异常package com.example.util;public class ResponseDate {private Boolean status = true;private int code = 200;private String message;private Object data;public ResponseDate(Object data){this.data = data;}public static ResponseDate ok(Object data){return new ResponseDate(data);}public ResponseDate(){}public Boolean getStatus() {return status;}public void setStatus(Boolean status) {this.status = status;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}}//自定义异常package com.example.util;public enum ResponseCode {PARAM_ERROR_CODE(400),SERVER_ERROR_CODE(500);private int code;public int getCode() {return code;}public void setCode(int code) {this.code = code;}private ResponseCode(int code) {this.code = code;}}//自定义异常package com.example.util;public class ResponseDate {private Boolean status = true;private int code = 200;private String message;private Object data;public ResponseDate(Object data){this.data = data;}public static ResponseDate ok(Object data){return new ResponseDate(data);}public ResponseDate(){}public Boolean getStatus() {return status;}public void setStatus(Boolean status) {this.status = status;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}}//自定义异常适配器package com.example.util;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;@ControllerAdvicepublic class GlobalExceptionHandler {@ExceptionHandler(GlobalException.class)@ResponseBodypublic ResponseDate jsonErrorHandler(HttpServletRequest request ,GlobalException e) throws Exception{ResponseDate r = new ResponseDate();r.setMessage(e.getMessage());r.setCode(e.getCode());r.setData(null);r.setStatus(false);return r;}}
spring boot提供了四种事件类型:
1、ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕。2、ApplicationPreparedEvent:spring boot上下文context创建完成。3、ApplicationStartedEvent :spring boot启动开始时执行的事件。4、ApplicationFailedEvent:spring boot启动异常时执行事件。
以上顺序是按照起订Springboot启动时各方法的打印顺序顺序,但是ApplicationStartedEvent应该是第一位启动啊...
以下是Java代码
package com.example.listener;import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;import org.springframework.context.ApplicationListener;public class ApplicationListenerEnvironmentPrepared implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{/*** Handle an application event.** @param event the event to respond to*/@Overridepublic void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {//可以通过ApplicationEnvironmentPreparedEvent获取到SpringApplication、ConfigurableEnvironment等等信息, 可以通过ConfigurableEnvironment实例对象来修改以及获取默认的环境信息。SpringApplication springApplication = event.getSpringApplication();ConfigurableEnvironment environment = event.getEnvironment();long timestamp = event.getTimestamp();Object source = event.getSource();System.out.println(String.format("自定义标识 2 :----%s----",getClass().getSimpleName()));}}package com.example.listener;import org.springframework.boot.context.event.ApplicationPreparedEvent;import org.springframework.context.ApplicationListener;public class ApplicationListenerPrepared implements ApplicationListener<ApplicationPreparedEvent> {/*** Handle an application event.** @param event the event to respond to*/@Overridepublic void onApplicationEvent(ApplicationPreparedEvent event) {System.out.println(String.format("自定义标识 3 :----%s----",getClass().getSimpleName()));}}package com.example.listener;import org.springframework.boot.context.event.ApplicationStartedEvent;import org.springframework.context.ApplicationListener;public class ApplicationListenerStarted implements ApplicationListener<ApplicationStartedEvent> {/*** Handle an application event.** @param event the event to respond to*/@Overridepublic void onApplicationEvent(ApplicationStartedEvent event) {//可以在SpringApplication启动之前做一些手脚,比如修改SpringApplication实例对象中的属性值SpringApplication springApplication = event.getSpringApplication();//springApplication.setShowBanner(false);System.out.println(String.format("自定义标识 1 :----%s----",getClass().getSimpleName()));}}package com.example.listener;import org.springframework.boot.context.event.ApplicationFailedEvent;import org.springframework.context.ApplicationListener;public class ApplicationListenerFailed implements ApplicationListener<ApplicationFailedEvent> {@Overridepublic void onApplicationEvent(ApplicationFailedEvent event) {//可以通过ApplicationFailedEvent 获取Throwable实例对象获取异常信息并处理。Throwable exception = event.getException();System.out.println(String.format("自定义标识 4 :----%s----",getClass().getSimpleName()));}}
Application.properties中使监听器生效的代码
context.listener.classes=com.example.listener.ApplicationListenerStarted,com.example.listener.ApplicationListenerEnvironmentPrepared,com.example.listener.ApplicationListenerFailed,com.example.listener.ApplicationListenerPrepared
复制类路径,以逗号分割,需要注意的是采用配置的方式ApplicationStartedEvent是起不了作用的,当框架加载到配置文件的时候其实项目已经启动了,所以这个事件是无效的。
所以在Application.java中配置如下
package com.example;import com.example.listener.ApplicationListenerEnvironmentPrepared;import com.example.listener.ApplicationListenerFailed;import com.example.listener.ApplicationListenerPrepared;import com.example.listener.ApplicationListenerStarted;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@EnableAutoConfiguration@ComponentScan(basePackages = {"com.example"})public class Application {public static void main(String[] args) {/*** 采用代码方式注册监听器<br>* 或者通过增加配置context.listener.classes=com.cxytiandi.listener.ApplicationListenerStarted* 多个用逗号隔开*/SpringApplication application = new SpringApplication(Application.class);application.addListeners(new ApplicationListenerStarted());application.addListeners(new ApplicationListenerEnvironmentPrepared());application.addListeners(new ApplicationListenerPrepared());application.addListeners(new ApplicationListenerFailed());application.run(args);//SpringApplication.run(Application.class, args);}}
package com.example.Filter;import org.apache.catalina.filters.RemoteIpFilter;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import java.io.IOException;@Configurationpublic class WebConfiguration {//这个好像无用@Beanpublic RemoteIpFilter remoteIpFilter(){return new RemoteIpFilter();}//在这里进行过滤器的配置@Beanpublic FilterRegistrationBean testRegistrationBean(){FilterRegistrationBean registrationBean = new FilterRegistrationBean();registrationBean.setFilter(new MyFilter());registrationBean.addUrlPatterns("/*");registrationBean.addInitParameter("paramName","paramValue");registrationBean.setName("MyFFFFFFF");registrationBean.setOrder(1);return registrationBean;}public class MyFilter implements Filter{@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("------------init----------");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("this is my filter ,url = " + ((HttpServletRequest) request).getRequestURI());chain.doFilter(request,response);}@Overridepublic void destroy() {System.out.println("---------destory---------");}}}
当有多个过滤器是需要设置执行顺序,只需要在FilterRegistrationBean类的setOrder()加入int类型的数字,服务器会根据其大小,按照 从小到大的顺序进行加载
package com.example.Filter;import org.springframework.core.annotation.Order;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import java.io.IOException;@WebFilter(filterName="LoginFilter",urlPatterns="*")@Order(3)//在这里设置filter的加载级别//注意使用注解方式设置Filter过滤器需要在启动类Application.Java添加`@ServletComponentScan`注解public class LoginFilter1 implements Filter{@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("我是后来后来来的过滤器");chain.doFilter(request,response);}@Overridepublic void destroy() {}}
package com.example.controller;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.multipart.MultipartHttpServletRequest;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.util.List;@Controllerpublic class FileController {@RequestMapping("/greeting")public String greeting(@RequestParam(value = "name", required = false, defaultValue = "World") String name, Model model) {model.addAttribute("name", name);return "greeting";}private static final Logger logger = LoggerFactory.getLogger(FileController.class);//文件上传相关代码@RequestMapping(value = "upload")@ResponseBodypublic String upload(@RequestParam("test") MultipartFile file) {if (file.isEmpty()) {return "文件为空";}// 获取文件名String fileName = file.getOriginalFilename();logger.info("上传的文件名为:" + fileName);// 获取文件的后缀名String suffixName = fileName.substring(fileName.lastIndexOf("."));logger.info("上传的后缀名为:" + suffixName);// 文件上传后的路径String filePath = "E://test//";// 解决中文问题,liunx下中文路径,图片显示问题// fileName = UUID.randomUUID() + suffixName;File dest = new File(filePath + fileName);// 检测是否存在目录if (!dest.getParentFile().exists()) {dest.getParentFile().mkdirs();}try {file.transferTo(dest);return "上传成功";} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return "上传失败";}//文件下载相关代码@RequestMapping("/download")public String downloadFile(org.apache.catalina.servlet4preview.http.HttpServletRequest request, HttpServletResponse response) {String fileName = "FileUploadTests.java";if (fileName != null) {//当前是从该工程的WEB-INF//File//下获取文件(该目录可以在下面一行代码配置)然后下载到C:\\users\\downloads即本机的默认下载的目录String realPath = request.getServletContext().getRealPath("//WEB-INF//");File file = new File(realPath, fileName);if (file.exists()) {response.setContentType("application/force-download");// 设置强制下载不打开response.addHeader("Content-Disposition","attachment;fileName=" + fileName);// 设置文件名byte[] buffer = new byte[1024];FileInputStream fis = null;BufferedInputStream bis = null;try {fis = new FileInputStream(file);bis = new BufferedInputStream(fis);OutputStream os = response.getOutputStream();int i = bis.read(buffer);while (i != -1) {os.write(buffer, 0, i);i = bis.read(buffer);}System.out.println("success");} catch (Exception e) {e.printStackTrace();} finally {if (bis != null) {try {bis.close();} catch (IOException e) {e.printStackTrace();}}if (fis != null) {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}}}return null;}//多文件上传@RequestMapping(value = "/batch/upload", method = RequestMethod.POST)@ResponseBodypublic String handleFileUpload(HttpServletRequest request) {List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");MultipartFile file = null;String fielPath = "C:/Users/Administrator/Desktop/";BufferedOutputStream stream = null;for (int i = 0; i < files.size(); ++i) {file = files.get(i);if (!file.isEmpty()) {try {byte[] bytes = file.getBytes();stream = new BufferedOutputStream(new FileOutputStream(new File(fielPath+file.getOriginalFilename())));stream.write(bytes);stream.close();} catch (Exception e) {stream = null;return "You failed to upload " + i + " => "+ e.getMessage();}} else {return "You failed to upload " + i+ " because the file was empty.";}}return "upload successful";}}
index.html
<!DOCTYPE html><html lang="en"><head><title>Getting Started: Serving Web Content</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><p>Get your greeting <a href="/greeting">here</a></p><form action="/upload" method="POST" enctype="multipart/form-data">文件:<input type="file" name="test"/><input type="submit" /></form><a href="/download">下载test</a><p>多文件上传</p><form method="POST" enctype="multipart/form-data" action="/batch/upload"><p>文件1:<input type="file" name="file" /></p><p>文件2:<input type="file" name="file" /></p><p><input type="submit" value="上传" /></p></form></html>
框架对文件上传的大小做了限制,可以通过在application.properties文件添加自定义的大小
spring.servlet.multipart.max-file-size=20000MBspring.servlet.multipart.max-request-size=20000MB
Application.java需要加上注解@EnableCaching开启缓存@Cacheable(value = "value",key="#user.id",condition="#user.id%2==0")当该注解在一个方法上使用时,会将该方法的返回值存储到起来,当下次再次调用的时候,不会再执行方法,而是将方法的返回值从缓存中取出使用,因为Spring储存缓存都是以键值对的方式进行储存的value相当于储存时的key。key属性是用来指定Spring缓存方法的返回结果时对应的key的。condition对缓存的对象进行限制,满足条件为true时,才进行缓存。@CachePut注解无论如何都会始终执行方法,然后将返回的数据进行缓存,其属性与@Cacheable注解方法属性一致。@CacheEvict是用来清除缓存的,与@Cacheable属性一致,另外有allEntries和beforeInvocation两个属性allEntries是Boolean属性,默认为false当为true时会将所有的缓存清空。由于allEntries是方法执行成功时才会执行,相对的当方法报错时不会执行,所以beforeInvocation为true时清空缓存的操作会在方法执行之前执行。@Caching(cacheable = @Cacheable("users"), evict={@CacheEvict("cache2"), @CacheEvict(value = "cache3", allEntries = true) })@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。application.properties配置redis链接
# REDIS (RedisProperties)# Redis数据库索引(默认为0)spring.redis.database=0# Redis服务器地址spring.redis.host=192.168.133.111# Redis服务器连接端口spring.redis.port=6379# Redis服务器连接密码(默认为空)spring.redis.password=# 连接池最大连接数(使用负值表示没有限制)#多线程情况下是非线程安全的#spring.redis.jedis.pool.max-active=#多线程情况下是线程安全的spring.redis.lettuce.pool.max-active=8# 连接池最大阻塞等待时间(使用负值表示没有限制)spring.redis.lettuce.pool.max-wait=-1ms# 连接池中的最大空闲连接spring.redis.lettuce.pool.max-idle=8# 连接池中的最小空闲连接spring.redis.lettuce.pool.min-idle=0# 连接超时时间(毫秒)spring.redis.timeout=5000ms
<!--Springboot Redis--><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.0.2.RELEASE</version></dependency>
package com.example.controller;import com.example.dao.UserRepository;import com.example.demo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.cache.annotation.EnableCaching;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@EnableAutoConfiguration//@EnableCachingpublic class RedisController {@Autowiredprivate UserRepository userRepository;@Autowiredprivate RedisTemplate redisTemplate;public ValueOperations<String, User> getValueOperations() {return redisTemplate.opsForValue();}@RequestMapping("User")@Cacheable(value = "getUser")public Object getUser(User aa){User user = getValueOperations().get("aa");System.out.println("out --------------------------");System.out.println(user);return user;}@RequestMapping("SaveAA")public Object save(){getValueOperations().set("aa",new User("aa","bb","cc","dd","ee"));System.out.println("SUCCESS");return "SUCCESS";}}
<dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>
@Configuration@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)public class SessionConfig {}
maxInactiveIntervalInSeconds: 设置Session失效时间,使用Redis Session之后,原Boot的server.session.timeout属性不再生效
@RequestMapping("/uid")String uid(HttpSession session){UUID uid = (UUID) session.getAttribute("uid");if(uid == null){uid = UUID.randomUUID();}session.setAttribute("uid",uid);return session.getId();}
当该接口被访问时会在redis数据库储存如下数据
127.0.0.1:6379> keys *session*1) "spring:session:expirations:1529562420000"//session失效时间2) "spring:session:sessions:a7b08ae6-667c-4b9d-bd10-456b203da2b8"//是sessionID3) "spring:session:sessions:expires:a7b08ae6-667c-4b9d-bd10-456b203da2b8"
实现共享的方法就是在另一个项目中链接同一个redis服务器进行相同的配置即可实现Session共享。
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version></dependency>
mybatis.type-aliases-package=com.neo.entityspring.datasource.driverClassName = com.mysql.jdbc.Driverspring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8spring.datasource.username = rootspring.datasource.password = root
如果未在启动类(Application.java)配置@MapperScan("com.example.Mapper"),就需要在每一个Mepper类上加@Mapper注解
package com.example.Mapper;import com.example.demo.User;import org.apache.ibatis.annotations.*;import java.util.List;public interface UserMapper {@Select("Select * from user")@Results({//peoperty代表实体类的属性名,column代表字段名//当实体类的属性与对应的字段名不同时需要使用该注解@Results@Result(property = "nickName",column = "nick_name"),@Result(property = "passWord",column = "pass_word"),@Result(property = "regTime",column = "reg_time"),@Result(property = "userName",column = "user_name")})List<User> getAll();@Results({@Result(property = "nickName",column = "nick_name"),@Result(property = "passWord",column = "pass_word"),@Result(property = "regTime",column = "reg_time"),@Result(property = "userName",column = "user_name")})@Select("Select * from user where id = #{id}")User getUser(int id );@Insert("insert into user(email,nick_name,pass_word,reg_time,user_name) values(" +"#{email},#{nickName},#{passWord},#{regTime},#{userName})")int saveUser(User user);@Update("update user set email=#{email},nick_name=#{nickName},pass_word=#{passWord},reg_time=#{regTime}," +"user_name=#{userName} where id = #{id}")int updateUser(User user);@Delete("DELETE from user where id = #{id}")void DeleteUser(Long id);}
@Select 是查询类的注解,所有的查询均使用这个@Result 修饰返回的结果集,关联实体类属性和数据库字段一一对应,如果实体类属性和数据库属性名保持一致,就不需要这个属性来修饰。@Insert 插入数据库使用,直接传入实体类会自动解析属性到对应的值@Update 负责修改,也可以直接传入对象@delete 负责删除
package com.example.controller;import com.example.Mapper.UserMapper;import com.example.demo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("/user")public class UserMapperController {@Autowiredprivate UserMapper userMapper;@RequestMapping("/selectAll")public List<User> selectAll() {return userMapper.getAll();}@RequestMapping("/selectOne")public User selectOne(int id) {return userMapper.getUser(id);}@RequestMapping("/saveUser")public String saveUser(User user) {return userMapper.saveUser(user) > 0 ? "SUCCESS" : "FFFFFFF";}@RequestMapping("/updateUser")public String updateUser(User user) {return userMapper.updateUser(user) > 0 ? "SUCCESS" : "FFFFFFF";}@RequestMapping("/deleteUser")public String deleteUser(Long id){userMapper.DeleteUser(id);return "SUCCESS";}}
application.properties新增以下配置
mybatis.config-locations=classpath:mybatis/mybatis-config.xmlmybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis-config.xml 配置
<configuration><typeAliases><typeAlias alias="Integer" type="java.lang.Integer" /><typeAlias alias="Long" type="java.lang.Long" /><typeAlias alias="HashMap" type="java.util.HashMap" /><typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /><typeAlias alias="ArrayList" type="java.util.ArrayList" /><typeAlias alias="LinkedList" type="java.util.LinkedList" /></typeAliases></configuration>
添加User的映射文件
<mapper namespace="com.neo.mapper.UserMapper" ><resultMap id="BaseResultMap" type="com.neo.entity.UserEntity" ><id column="id" property="id" jdbcType="BIGINT" /><result column="userName" property="userName" jdbcType="VARCHAR" /><result column="passWord" property="passWord" jdbcType="VARCHAR" /><result column="user_sex" property="userSex" javaType="com.neo.enums.UserSexEnum"/><result column="nick_name" property="nickName" jdbcType="VARCHAR" /></resultMap><sql id="Base_Column_List" >id, userName, passWord, user_sex, nick_name</sql><select id="getAll" resultMap="BaseResultMap" >SELECT<include refid="Base_Column_List" />FROM users</select><select id="getOne" parameterType="java.lang.Long" resultMap="BaseResultMap" >SELECT<include refid="Base_Column_List" />FROM usersWHERE id = #{id}</select><insert id="insert" parameterType="com.neo.entity.UserEntity" >INSERT INTOusers(userName,passWord,user_sex)VALUES(#{userName}, #{passWord}, #{userSex})</insert><update id="update" parameterType="com.neo.entity.UserEntity" >UPDATEusersSET<if test="userName != null">userName = #{userName},</if><if test="passWord != null">passWord = #{passWord},</if>nick_name = #{nickName}WHEREid = #{id}</update><delete id="delete" parameterType="java.lang.Long" >DELETE FROMusersWHEREid =#{id}</delete></mapper>
DAO层
public interface UserMapper {List<UserEntity> getAll();UserEntity getOne(Long id);void insert(UserEntity user);void update(UserEntity user);void delete(Long id);}
在启动类加注解@EnableScheduling。
pom依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
management:server:port: 9001 #配置端口号endpoints:web:exposure:include: '*' #开放API,可以获取到信息
package com.example.exe;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Component;import java.text.SimpleDateFormat;import java.util.Date;@Componentpublic class Scheduler2TaskTime {private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");@Scheduled(fixedRate = 6000)public void reportCurrentTime() {System.out.println("现在时间:" + dateFormat.format(new Date()));}}package com.example.exe;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Component;@Componentpublic class SchedulerTaskTime {private int count=0;@Scheduled(cron="*/6 * * * * ?")private void process(){System.out.println("this is scheduler task runing "+(count++));}}
this is scheduler task runing 0现在时间:15:06:44this is scheduler task runing 1现在时间:15:06:50this is scheduler task runing 2现在时间:15:06:56this is scheduler task runing 3现在时间:15:07:02this is scheduler task runing 4现在时间:15:07:08this is scheduler task runing 5现在时间:15:07:14
@Scheduled 参数可以接受两种定时的设置,一种是我们常用的cron="*/6 * * * * ?",一种是 fixedRate = 6000,两种都表示每隔六秒打印一下内容。fixedRate 说明@Scheduled(fixedRate = 6000) :上一次开始执行时间点之后6秒再执行@Scheduled(fixedDelay = 6000) :上一次执行完毕时间点之后6秒再执行@Scheduled(initialDelay=1000, fixedRate=6000) :第一次延迟1秒后执行,之后按fixedRate的规则每6秒执行一次
该方法默认使用单线程,多个微服务时需要加配置ThreadPoolTaskScheduler??quartz??分布式锁了解下??
MongoDB+Springboot的配置使用
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency></dependencies>
#MongoDB配置spring.data.mongodb.uri=mongodb://renwb:123456@192.168.133.111:27017/test#renwb:代表链接的账户#123456:代表密码
package com.example.demo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;@Data@NoArgsConstructor@AllArgsConstructorpublic class MongoDBUser implements Serializable {private Long id;private String userName;private String passWord;}
package com.example.dao;import com.example.demo.MongoDBUser;import com.mongodb.client.result.DeleteResult;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.mongodb.MongoDbFactory;import org.springframework.data.mongodb.core.MongoTemplate;import org.springframework.data.mongodb.core.query.Criteria;import org.springframework.data.mongodb.core.query.Query;import org.springframework.data.mongodb.core.query.Update;import org.springframework.stereotype.Component;@Componentpublic class MongoDBUserDAO {@Autowiredprivate MongoTemplate mongoTemplate;public void testSaveUser(MongoDBUser mongoDBUser){mongoTemplate.save(mongoDBUser);}public MongoDBUser findUser(String userName){Query query = new Query(Criteria.where("userName").is(userName));MongoDBUser mongoDBUser = mongoTemplate.findOne(query,MongoDBUser.class);return mongoDBUser;}public void updateUser(MongoDBUser mongoDBUser){Query query = new Query(Criteria.where("id").is(mongoDBUser.getId()));Update update = new Update().set("userName",mongoDBUser.getUserName()).set("password",mongoDBUser.getPassWord());mongoTemplate.updateFirst(query,update,MongoDBUser.class);}public void deleteUserById(Long id){Query query = new Query(Criteria.where("id").is(id));//mongoTemplate.remove(query); 这个方法不可用会报错DeleteResult deleteResult = mongoTemplate.remove(query,MongoDBUser.class,"mongoDBUser");//System.out.println("这是什么 ? " + DeleteResult.unacknowledged().getDeletedCount());}}
package test.MongoDBTest;import com.example.Application;import com.example.dao.MongoDBUserDAO;import com.example.demo.MongoDBUser;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;@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class)public class MongoDBTest {@Autowiredprivate MongoDBUserDAO mongoDBUserDAO;@Testpublic void TestMongoDB(){MongoDBUser user = new MongoDBUser(233L,"老明","123456");mongoDBUserDAO.testSaveUser(user);System.out.println("第一次查询 :" + mongoDBUserDAO.findUser("老明"));MongoDBUser user1 = new MongoDBUser(233L,"老红","654321");;mongoDBUserDAO.updateUser(user1);System.out.println("第二次查询 :" + mongoDBUserDAO.findUser("老红"));mongoDBUserDAO.deleteUserById(233L);System.out.println("第三次查询 :" + mongoDBUserDAO.findUser("老红"));}}
2018-06-08 16:59:32.773 INFO 6692 --- [ main] org.mongodb.driver.connection : Opened connection [connectionId{localValue:3, serverValue:125}] to 192.168.133.111:27017第一次查询 :MongoDBUser(id=233, userName=老明, passWord=123456)第二次查询 :MongoDBUser(id=233, userName=老红, passWord=123456)第三次查询 :null
application.yml的内容
mongodb:primary:host: 192.168.133.111port: 27017database: testsecondary:host: 192.168.133.111port: 27017database: test1
package com.example.config;import lombok.Data;import org.springframework.boot.autoconfigure.mongo.MongoProperties;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@Data@Component@ConfigurationProperties(prefix = "mongodb")public class MultipleMongoProperties {private MongoProperties primary = new MongoProperties();private MongoProperties secondary = new MongoProperties();}
application.properties的配置
#主数据库spring.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8spring.datasource.ds1.username=rootspring.datasource.ds1.password=rootspring.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver#从数据库#由于Spring Boot2.0 使用 HikariCP 作为默认的连接池 它使用的是jdbc-url,所以不是spring.datasource.ds2.urlspring.datasource.ds2.jdbc-url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8spring.datasource.ds2.username=rootspring.datasource.ds2.password=rootspring.datasource.ds2.driver-class-name=com.mysql.jdbc.Driver
主数据配置
package com.example.config;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.SqlSessionTemplate;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;import java.io.IOException;//主数据配置@Configuration@MapperScan(basePackages = "com.example.Mapper.Test1",sqlSessionTemplateRef = "test1SqlSessionTemplate")public class DataSourceConfig {@Bean(name = "test1DataSource")@ConfigurationProperties(prefix = "spring.datasource.ds1")@Primary//该注解表示这个是主数据库,是默认的数据库public DataSource testDataSource(){return DataSourceBuilder.create().build();}@Bean(name = "test1SqlSessionFactory")@Primarypublic SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource")DataSource dataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);//注意配置文件应在resource包下,否则IDEA是不会将Java包下的配置文件编译到项目里去!!!!!bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:Hibernate/Test1/*.xml"));return bean.getObject();}@Bean("transactionManager")//这个名字是好像是固定的 如果不是这个编译时会报错@Primarypublic DataSourceTransactionManager testDataSourceTranscationManage(@Qualifier("test1DataSource")DataSource dataSource){return new DataSourceTransactionManager(dataSource);}//这个name应与该类上@MapperScan(sqlSessionTemplateRef = "test1SqlSessionTemplate")一样@Bean(name = "test1SqlSessionTemplate")@Primarypublic SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory){return new SqlSessionTemplate(sqlSessionFactory);}}
从数据库配置
package com.example.config;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.SqlSessionTemplate;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;import java.io.IOException;@Configuration//这个相当于xml里的<beans>标签@MapperScan(basePackages = "com.example.Mapper.Test2", sqlSessionTemplateRef = "test2SqlSessionTemplate")public class DataSourceConfig2 {@Bean(name = "test2DataSource")@ConfigurationProperties(prefix = "spring.datasource.ds2")public DataSource testDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "test2SqlSessionFactory")//这个注解是<bean>标签public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:Hibernate/Test2/*.xml"));return bean.getObject();}@Bean("test2TransactionManager")public DataSourceTransactionManager testDataSourceTranscationManage(@Qualifier("test2DataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "test2SqlSessionTemplate")public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}}
map.xml配置
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.Mapper.Test1.Test1Mapper"><resultMap id="BaseResultMap" type="com.example.demo.User"><id column="id" property="id" jdbcType="BIGINT"/><result column="user_name" property="userName"/><result property="passWord" column="pass_word"/><result property="email" column="email"/><result property="nickName" column="nick_name"/><result property="regTime" column="reg_time"/></resultMap><sql id="allSql">id,user_name,pass_word,email,nick_name,reg_time</sql><select id="getAll" resultMap="BaseResultMap">SELECT<include refid="allSql"/>FROM USER</select></mapper>
map.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.example.Mapper.Test2.Test2Mapper"><resultMap id="BaseResultMap" type="com.example.demo.User"><id column="id" property="id" jdbcType="BIGINT"/><result column="user_name" property="userName"/><result property="passWord" column="pass_word"/><result property="email" column="email"/><result property="nickName" column="nick_name"/><result property="regTime" column="reg_time"/></resultMap><sql id="allSql">user_name,pass_word,email,nick_name,reg_time</sql><select id="saveUser" parameterType="com.example.demo.User">INSERTINTOUSER(<include refid="allSql"/>)VALUES(#{userName},#{passWord},#{email},#{nickName},#{regTime})</select></mapper>
package com.example.Mapper.Test1;import com.example.demo.User;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic interface Test1Mapper {List<User> getAll();}
package com.example.Mapper.Test2;import com.example.demo.User;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic interface Test2Mapper {void saveUser(User user);}
src下的配置文件解决的方法在pom文件添加如下代码
<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources></build>
pom依赖
<!--消息队列RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
application.properties配置
#RabbitMQ配置spring.application.name=spirng-boot-rabbitmqspring.rabbitmq.host=192.168.133.111#注意端口号web端访问MQ时端口号为 15672 程序访问时为 5672spring.rabbitmq.port=5672spring.rabbitmq.username=adminspring.rabbitmq.password=123456spring.rabbitmq.connection-timeout=10000ms
package com.example.config;import org.springframework.amqp.core.Queue;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class RabbitMQConfig {@Beanpublic Queue queue(){return new Queue("hello");}@Beanpublic Queue queue1(){return new Queue("hello1");}@Beanpublic Queue queue2(){return new Queue("hello2");}}
package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.core.AmqpTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.util.Date;@Componentpublic class HelloSender {@Autowiredprivate AmqpTemplate amqpTemplate;public void send(Student student){String conetxt = "hello" + new Date();System.out.println("Sender : " + conetxt);this.amqpTemplate.convertAndSend("hello",student);}public void oneToMany(){config config1 = new config();config1.setIp("10.10.1.1");config1.setPort(255);for (int i = 0; i < 100 ; i++){this.amqpTemplate.convertAndSend("hello",config1);this.amqpTemplate.convertAndSend("hello1","message ------ " + i);}}}
package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = "hello")//单个信道声明的格式public class HelloReceiver {public int count;@RabbitHandler//如果生产者发送的是对象的换,消费者形参要是同类型public void process(Student hello){count++;System.out.println(this.getClass().getName()+" hello接收到的消息 " + hello);System.out.println(this.getClass().getName()+" hello接收到了"+ hello+"条消息的消息 " );System.out.println();}}package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = {"hello","hello1"})//多个信道的声明方式public class HelloReceiver2 {public int count;@RabbitHandlerpublic void process(Student hello){count++;System.out.println(this.getClass().getName()+" 接收到的消息 " + hello);System.out.println(this.getClass().getName()+" 接收到了"+ hello+"条消息的消息 " );System.out.println();}}
topic 是RabbitMQ中最灵活的一种方式,可以根据routing_key自由的绑定不同的队列*
1)、TopicConfigBean
package com.example.config;import org.springframework.amqp.core.*;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class TopicRabbitConfig {final static String MESSAGE = "topic.message";final static String MESSAGES = "topic.messages";@Beanpublic Queue queueMessage() {return new Queue(TopicRabbitConfig.MESSAGE);}@Beanpublic Queue queueMessages() {return new Queue(TopicRabbitConfig.MESSAGES);}@Beanpublic Exchange exchange() {return new TopicExchange("exchange");}@Beanpublic Exchange exchange1() {return new TopicExchange("exchange1");}@BeanBinding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");}@BeanBinding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange1) {return BindingBuilder.bind(queueMessages).to(exchange1).with("topic.messages");}}
2)、Topic生产者
public void send1() {String context = "hi, i am message 1";System.out.println("Sender : " + context);this.amqpTemplate.convertAndSend("exchange", "topic.message", context);}public void send2() {String context = "hi, i am messages 2";System.out.println("Sender : " + context);this.amqpTemplate.convertAndSend("exchange1", "topic.messages", context);}
3)、消费者
package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = {"topic.message"})public class HelloReceiver {public int count;@RabbitHandlerpublic void process(String hello){count++;System.out.println(this.getClass().getName()+" hello接收到的消息 " + hello);System.out.println(this.getClass().getName()+" hello接收到了"+ hello+"条消息的消息 " );System.out.println();}}----package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = "topic.messages")public class HelloReceiver1 {public int count;@RabbitHandlerpublic void process(String hello){count++;System.out.println(this.getClass().getName()+" helloOne接收到的消息 " + hello);System.out.println(this.getClass().getName()+" helloOne接收到了"+ hello+"条消息的消息 " );System.out.println();}}
4)、测试代码
package test.RabbitMQTest;import com.example.Application;import com.example.demo.Student;import com.example.exe.HelloReceiver;import com.example.exe.HelloReceiver1;import com.example.exe.HelloReceiver2;import com.example.exe.HelloSender;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;@RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class)public class RabbitMQTest {@Autowiredprivate HelloSender helloSender;@Testpublic void hello() throws Exception{Student student = new Student("student","name");helloSender.send1();helloSender.send2();}}
5)、输出结果
Sender : hi, i am message 1Sender : hi, i am messages 2com.example.exe.HelloReceiver1 helloOne接收到的消息 hi, i am messages 2com.example.exe.HelloReceiver1 helloOne接收到了hi, i am messages 2条消息的消息com.example.exe.HelloReceiver hello接收到的消息 hi, i am message 1com.example.exe.HelloReceiver hello接收到了hi, i am message 1条消息的消息
Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。
1)、配置
package com.example.config;import org.springframework.amqp.core.Binding;import org.springframework.amqp.core.BindingBuilder;import org.springframework.amqp.core.FanoutExchange;import org.springframework.amqp.core.Queue;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class FanoutRabbitMQConfig {@Beanpublic Queue AMessage(){return new Queue("fanout.A");}@Beanpublic Queue BMessage(){return new Queue("fanout.B");}@Beanpublic Queue CMessage(){return new Queue("fanout.C");}@BeanFanoutExchange fanoutExchange(){return new FanoutExchange("fanoutExchange");}@BeanBinding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange){return BindingBuilder.bind(AMessage).to(fanoutExchange);}@BeanBinding bindingExchangeB(Queue BMessage,FanoutExchange fanoutExchange){return BindingBuilder.bind(BMessage).to(fanoutExchange);}@BeanBinding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange){return BindingBuilder.bind(CMessage).to(fanoutExchange);}}
2)、生产者
public void sendFanout(){String context = "hi, fanout msg ";System.out.println("Sender : " + context);//订阅模式routing_key无需声明队列名,因为会被忽略this.amqpTemplate.convertAndSend("fanoutExchange","", context);}
3)、消费者
package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = "fanout.A")public class HelloReceiver {public int count;@RabbitHandlerpublic void process(String hello){count++;System.out.println(this.getClass().getName()+" hello接收到的消息 " + hello);System.out.println(this.getClass().getName()+" hello接收到了"+ hello+"条消息的消息 " );System.out.println();}}package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = "fanout.B")public class HelloReceiver1 {public int count;@RabbitHandlerpublic void process(String hello){count++;System.out.println(this.getClass().getName()+" helloOne接收到的消息 " + hello);System.out.println(this.getClass().getName()+" helloOne接收到了"+ hello+"条消息的消息 " );System.out.println();}}package com.example.exe;import com.example.demo.Student;import com.example.demo.config;import org.springframework.amqp.rabbit.annotation.RabbitHandler;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.stereotype.Component;@Component@RabbitListener(queues = {"fanout.C"})public class HelloReceiver2 {public int count;@RabbitHandlerpublic void process(String hello){count++;System.out.println(this.getClass().getName()+" 接收到的消息 " + hello);System.out.println(this.getClass().getName()+" 接收到了"+ hello+"条消息的消息 " );System.out.println();}}
4)、输出
com.example.exe.HelloReceiver1 helloOne接收到的消息 hi, fanout msgcom.example.exe.HelloReceiver1 helloOne接收到了hi, fanout msg 条消息的消息com.example.exe.HelloReceiver hello接收到的消息 hi, fanout msgcom.example.exe.HelloReceiver hello接收到了hi, fanout msg 条消息的消息com.example.exe.HelloReceiver2 接收到的消息 hi, fanout msgcom.example.exe.HelloReceiver2 接收到了hi, fanout msg 条消息的消息