@SendLin
2018-07-11T17:10:45.000000Z
字数 51639
阅读 1347
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.properties
application.properties
#tomcat port
server.port=8080
server.servlet.context-path=/spring-boot/
Java
@Autowired
private Environment environment;
@RequestMapping("context")
Object getContext(){
return environment.getProperty("server.port");
}
config.properties
(文件名随意)config.properties
config.ip=192.168.1.1
config.port=8080
java代码domain
@Component
@PropertySource(value = "classpath:/config.properties")
//由于@ConfigurationProperties的locations 属性被移除所以无法指定配置文件路径,由此藉由@PropertySource方法代替
@ConfigurationProperties(prefix="config")
public class config {
@NotEmpty
private 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
@Autowired
private 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/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
其实这个hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构,有四个值:
create: 每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
@Entity
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private 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";
}
//利用该对象进行
@PersistenceUnit
private 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{
@Transient
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private 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
@Entity
public 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;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(GlobalException.class)
@ResponseBody
public 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
*/
@Override
public 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
*/
@Override
public 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
*/
@Override
public 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> {
@Override
public 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;
@Configuration
public class WebConfiguration {
//这个好像无用
@Bean
public RemoteIpFilter remoteIpFilter(){
return new RemoteIpFilter();
}
//在这里进行过滤器的配置
@Bean
public 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{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("------------init----------");
}
@Override
public 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);
}
@Override
public 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{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("我是后来后来来的过滤器");
chain.doFilter(request,response);
}
@Override
public 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;
@Controller
public 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")
@ResponseBody
public 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)
@ResponseBody
public 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=20000MB
spring.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
//@EnableCaching
public class RedisController {
@Autowired
private UserRepository userRepository;
@Autowired
private 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"//是sessionID
3) "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.entity
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.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 {
@Autowired
private 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.xml
mybatis.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 users
WHERE id = #{id}
</select>
<insert id="insert" parameterType="com.neo.entity.UserEntity" >
INSERT INTO
users
(userName,passWord,user_sex)
VALUES
(#{userName}, #{passWord}, #{userSex})
</insert>
<update id="update" parameterType="com.neo.entity.UserEntity" >
UPDATE
users
SET
<if test="userName != null">userName = #{userName},</if>
<if test="passWord != null">passWord = #{passWord},</if>
nick_name = #{nickName}
WHERE
id = #{id}
</update>
<delete id="delete" parameterType="java.lang.Long" >
DELETE FROM
users
WHERE
id =#{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;
@Component
public 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;
@Component
public 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:44
this is scheduler task runing 1
现在时间:15:06:50
this is scheduler task runing 2
现在时间:15:06:56
this is scheduler task runing 3
现在时间:15:07:02
this is scheduler task runing 4
现在时间:15:07:08
this 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
@AllArgsConstructor
public 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;
@Component
public class MongoDBUserDAO {
@Autowired
private 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 {
@Autowired
private MongoDBUserDAO mongoDBUserDAO;
@Test
public 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.111
port: 27017
database: test
secondary:
host: 192.168.133.111
port: 27017
database: 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-8
spring.datasource.ds1.username=root
spring.datasource.ds1.password=root
spring.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
#从数据库
#由于Spring Boot2.0 使用 HikariCP 作为默认的连接池 它使用的是jdbc-url,所以不是spring.datasource.ds2.url
spring.datasource.ds2.jdbc-url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.ds2.username=root
spring.datasource.ds2.password=root
spring.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")
@Primary
public 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")//这个名字是好像是固定的 如果不是这个编译时会报错
@Primary
public DataSourceTransactionManager testDataSourceTranscationManage(@Qualifier("test1DataSource")DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
//这个name应与该类上@MapperScan(sqlSessionTemplateRef = "test1SqlSessionTemplate")一样
@Bean(name = "test1SqlSessionTemplate")
@Primary
public 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">
INSERT
INTO
USER
(<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;
@Service
public interface Test1Mapper {
List<User> getAll();
}
package com.example.Mapper.Test2;
import com.example.demo.User;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public 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-rabbitmq
spring.rabbitmq.host=192.168.133.111
#注意端口号web端访问MQ时端口号为 15672 程序访问时为 5672
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
spring.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;
@Configuration
public class RabbitMQConfig {
@Bean
public Queue queue(){
return new Queue("hello");
}
@Bean
public Queue queue1(){
return new Queue("hello1");
}
@Bean
public 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;
@Component
public class HelloSender {
@Autowired
private 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;
@RabbitHandler
public 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;
@Configuration
public class TopicRabbitConfig {
final static String MESSAGE = "topic.message";
final static String MESSAGES = "topic.messages";
@Bean
public Queue queueMessage() {
return new Queue(TopicRabbitConfig.MESSAGE);
}
@Bean
public Queue queueMessages() {
return new Queue(TopicRabbitConfig.MESSAGES);
}
@Bean
public Exchange exchange() {
return new TopicExchange("exchange");
}
@Bean
public Exchange exchange1() {
return new TopicExchange("exchange1");
}
@Bean
Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}
@Bean
Binding 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;
@RabbitHandler
public 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;
@RabbitHandler
public 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 {
@Autowired
private HelloSender helloSender;
@Test
public void hello() throws Exception{
Student student = new Student("student","name");
helloSender.send1();
helloSender.send2();
}
}
5)、输出结果
Sender : hi, i am message 1
Sender : hi, i am messages 2
com.example.exe.HelloReceiver1 helloOne接收到的消息 hi, i am messages 2
com.example.exe.HelloReceiver1 helloOne接收到了hi, i am messages 2条消息的消息
com.example.exe.HelloReceiver hello接收到的消息 hi, i am message 1
com.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;
@Configuration
public class FanoutRabbitMQConfig {
@Bean
public Queue AMessage(){
return new Queue("fanout.A");
}
@Bean
public Queue BMessage(){
return new Queue("fanout.B");
}
@Bean
public Queue CMessage(){
return new Queue("fanout.C");
}
@Bean
FanoutExchange fanoutExchange(){
return new FanoutExchange("fanoutExchange");
}
@Bean
Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange){
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(Queue BMessage,FanoutExchange fanoutExchange){
return BindingBuilder.bind(BMessage).to(fanoutExchange);
}
@Bean
Binding 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;
@RabbitHandler
public 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;
@RabbitHandler
public 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;
@RabbitHandler
public 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 msg
com.example.exe.HelloReceiver1 helloOne接收到了hi, fanout msg 条消息的消息
com.example.exe.HelloReceiver hello接收到的消息 hi, fanout msg
com.example.exe.HelloReceiver hello接收到了hi, fanout msg 条消息的消息
com.example.exe.HelloReceiver2 接收到的消息 hi, fanout msg
com.example.exe.HelloReceiver2 接收到了hi, fanout msg 条消息的消息