SpringBoot
1.Spring boot的优点
轻松创建独立的Spring应用程序。
内嵌Tomcat、jetty等web容器,不需要部署WAR文件。
提供一系列的“starter” 来简化的Maven配置,集成主流开源产品往往只需要简单的配置即可。
开箱即用,尽可能自动配置Spring。
使用sping boot非常适合构建微服务
2.构建SpringBoot的三种方式
1.在线创建
http://start.spring.io/
2.手动创建
3.Maven创建
3.SpringBoot项目的目录结构
1.自定义项目启动图标:
banner.txt
图标文件与主配置文件在同一目录下*(resources目录下)
2.配置项目端口 application.properties
#端口
server.port=8081
4.热部署
1.增加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
2.打开自动编译(Build project automatically)
3.快捷键ctrl+alt+shift+/ 选择registry 选择compiler.automake.allow.when.app.running
4.打开自动刷新
5.SpringBoot资源属性文件配置
1.创建对象
package com.ccc.demoboot.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "my1")
public class MyProperties1 {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.application.properties属性文件增加
my1.age=25
my1.name=Luis
3.测试
@Autowired
MyProperties1 my;
/**
* 加载默认属性文件
* @return
*/
@ResponseBody
@RequestMapping("/test2")
public String test2() {
return "aa:bb,vvvfffdfdffd" + my.getName();
}
6.多环境属性配置:不同环境加载不同的属性文件
开发环境:application-dev.properties
测试环境:application-test.properties
发布环境:application-prod.properties
加载不同环境配置
#加载其他属性文件
spring.profiles.active=dev
#spring.profiles.active=prof
#spring.profiles.active=test
6.SpringBoot配置JSP页面的跳转
1.添加依赖
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
2.创建webapp文件夹,创建view文件夹
3.增加配置 application.properties
#jsp访问配置
spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp
4.测试
@Controller
public class Hello {
@RequestMapping("/jsp/{jsp}")
public ModelAndView jsp(@PathVariable("jsp") String jsp) {
System.out.println(jsp);
ModelAndView mv = new ModelAndView();
mv.setViewName(jsp);
mv.addObject("a", "测试");
return mv;
}
}
测试地址:http://localhost:8080/jsp/ina
SpingBoot配置文件
springmvc的依赖文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
application.properties
application.yaml
两种文件的区别:
语法:
properties: key=value
#端口
server.port=8081
yaml: key: value (key:空格value)
#yaml配置文件的格式
server:
port: 8080
SpringBoot配置Thymeleaf模板
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置文件
spring.thymeleaf.cache=false
#针对的是resources下面的templates,默认就是的
#spring.thymeleaf.prefix=classpath:/templates/
#针对的是webapp下面,也可以不行,默认templates下面的
spring.thymeleaf.prefix=/view/
spring.thymeleaf.suffix=.html
不能添加@@ResponseBody注解,添加注解后只能返回字符串
SpringBoot静态资源:直接使用
SpringBoot整合Mybaties
依赖文件
<!-- Mybatis的依赖包mybatis-spring-boot-starter,该包拥有自动装配的特点 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- MYSQL依赖包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
配置 application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=1234
#Mybatis接口xml映射文件路径 idea是放在resources下面的
mybatis.mapper-locations=classpath:com/ccc/springbootwebtest/mapper/*.xml
#Mybatis实体pojo类路径,可以不用
mybatis.type-aliases-package=com.ccc.springbootwebtest.domain
# 驼峰命名规范 如:数据库字段是 order_id 那么 实体字段就要写成 orderId
mybatis.configuration.map-underscore-to-camel-case=true
SpringBoot***整合Mybatis***通用接口及分页插件事务
依赖
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
<version>1.2.10</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
<!-- 通用Mapper插件 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>RELEASE</version>
</dependency>
2 相关配置文件 application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=1234
# 如果想看到mybatis日志需要做如下配置 com.ccc.springbootwebtest.dao是Mapper接口的路径
# logging.level.*=debug
logging.level.com.ccc.springbootwebtest.dao=DEBUG
#Mybatis接口xml映射文件路径
mybatis.mapper-locations=classpath:com/ccc/springbootwebtest/mapper/*.xml
#Mybatis实体pojo类路径
mybatis.type-aliases-package=com.ccc.springbootwebtest.domain
# 驼峰命名规范 如:数据库字段是 order_id 那么 实体字段就要写成 orderId
mybatis.configuration.map-underscore-to-camel-case=true
########## 通用Mapper ##########
# 主键自增回写方法,默认值MYSQL,详细说明请看文档
mapper.identity=MYSQL
mapper.mappers=tk.mybatis.mapper.common.BaseMapper
# 设置 insert 和 update 中,是否判断字符串类型!=''
mapper.not-empty=true
# 枚举按简单类型处理(枚举按简单类型处理,如果有枚举字段则需要加上该配置才会做映射)
mapper.enum-as-simple-type=true
########## 分页插件 ##########
pagehelper.helperDialect=mysql
pagehelper.params=count=countSql
#pagehelper.reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
pagehelper.reasonable=false
#pagehelper.support-methods-arguments:支持通过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。
pagehelper.supportMethodsArguments=true
事务
spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。
第一步、增加@EnableTransactionManagement放在启动类上
第二步、service层实现类方法增加@Transactional()注解
文件上传.下载
<!-- 文件上传 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
配置文件上传的属性 application.properties
这些属性并非必须属性,自带默认值,没必要设置
# 禁用 thymeleaf 缓存
spring.thymeleaf.cache=false
# 是否支持批量上传 (默认值 true)
spring.servlet.multipart.enabled=true
# 上传文件的临时目录 (一般情况下不用特意修改)
spring.servlet.multipart.location=
# 上传文件最大为 1M (默认值 1M 根据自身业务自行控制即可)
spring.servlet.multipart.max-file-size=1048576
# 上传请求最大为 10M(默认值10M 根据自身业务自行控制即可)
spring.servlet.multipart.max-request-size=10485760
# 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改)
spring.servlet.multipart.file-size-threshold=0
# 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改)
spring.servlet.multipart.resolve-lazily=false
@RestController
public class fileupload {
@RequestMapping("/upload")
//multipartFile 应与前端界面中的name相同
public String upload(@RequestParam("multipartFile") MultipartFile multipartFile) throws IOException {
multipartFile.transferTo(new File("/Users/mengkeliu/Desktop/图片/临时文件/" + multipartFile.getOriginalFilename()));
return "ok";
}
}
前端界面:文件上传需放入p标签内,否则报错
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<form action="/fileupload" enctype="multipart/form-data" method="post">
<p>
<!--文件名称name需与后端名称相同-->
文件1:
<input type="file" name="multipartFile"/>
<input type="submit" value="上传"/>
</p>
</form>
</body>
</html>
SpringBoot整合FASTDFS文件存储服务
9.SpringBoot整合POI
POI API结构包名称说明
HSSF提供读写Microsoft Excel XLS格式档案的功能。
XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能。
HWPF提供读写Microsoft Word DOC格式档案的功能。
HSLF提供读写Microsoft PowerPoint格式档案的功能。
HDGF提供读Microsoft Visio格式档案的功能。
HPBF提供读Microsoft Publisher格式档案的功能。
HSMF提供读Microsoft Outlook格式档案的功能。
1.依赖
<!-- poi依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.14</version>
</dependency>
2.Excel的读取
/**
* 读取Excel内容
*
* @param filename
* @return
*/
public static List<Map<String, String>> readExcel1(String filename) throws IOException {
List<Map<String, String>> SheetList = new ArrayList<>();
FileInputStream fileInputStream = new FileInputStream(filename);
Workbook workbook = null;
if (filename.toLowerCase().endsWith("xlsx")) {
workbook = new XSSFWorkbook(fileInputStream);
} else if (filename.toLowerCase().endsWith("xls")) {
workbook = new HSSFWorkbook(fileInputStream);
}
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterable = sheet.iterator();
rowIterable.next();
//读取行
while (rowIterable.hasNext()) {
Row row = rowIterable.next();
Iterator<Cell> cellIterable = row.cellIterator();
Map<String, String> map = new HashMap<String, String>();
//读取单元格
while (cellIterable.hasNext()) {
Cell cell = cellIterable.next();
int a = cell.getCellType();
if (a == 0) {
int d = (int) cell.getNumericCellValue();
map.put(cell.getColumnIndex() + "", d + "");
} else if (a == 1) {
String value = cell.getStringCellValue();
map.put(cell.getColumnIndex() + "", value);
}
}
SheetList.add(map);
}
return SheetList;
}
10.全局异常处理
1.简单处理
/**
* 异常处理类
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public String exceptionHandler(Exception e){
return "发生错误"+e.getMessage();
}
}
2.进一步优化
/**
* 所有接口返回的对象类型,以json形式返回
*/
public class CommenReturnObject {
public static final int CODE200 = 200; //正确
public static final int CODE300 = 300;
public static final int CODE400 = 400;
public static final int CODE500 = 500;
private int code;
private String message;
private Object data;
public int getCode() {
return code;
}
public CommenReturnObject setCode(int code) {
this.code = code;
return this;
}
public String getMessage() {
return message;
}
public CommenReturnObject setMessage(String message) {
this.message = message;
return this;
}
public Object getData() {
return data;
}
public CommenReturnObject setData(Object data) {
this.data = data;
return this;
}
}
优化后的使用
11.SpringBoot RESTFUL标准
-
@GetMapping("/test1") //相当与 @RequestMapping(value = "/test1",method = RequestMethod.GET)
-
@PostMapping("/test1") @RequestMapping(value = "/test1",method = RequestMethod.POST)
-
@DeleteMapping("/test1") @RequestMapping(value = "/test1",method = RequestMethod.DELETE) @PutMapping("/test1") @RequestMapping(value = "/test1",method = RequestMethod.PUT)
put⽅法主要是⽤来更新整个资源的,⽽ patch ⽅法主要表示更新部分字段。
CORS跨域问题
三种解决方式
1.json
2.websocket
3.cors @CrossOrigin注解解决跨域问题
启动任务
在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( Servlet、Filter、Listener )之一 Listener ,这种情况下,一般定义一个 ServletContextListener,然后就可以监听到项目启动和销毁,进而做出相应的数据初始化和销毁操作
public class myListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//初始化数据操作
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//数据备份数据操作*/
}
}
多个启动任务设置优先级
@Component
@Order(100) //设置任务的优先级,1-100 数字越小优先级越高 不设置默认问MAX_VALUE
public class MyCommandLineRunner1 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("系统启动任务");
}
}
SpringBoor整合swagger
依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
创建 SwaggerConfig 配置类
SpringBoot-WebSocket
依赖
<!-- websocket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
增加WebSocketConfig配置类
/**
* Socket启动配置类
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
创建messsage对象:
package com.demo.websocket.websocket;
public class messageObject {
private String message;
private String touserid;
private String fromuserid;
public String getFromuserid() {
return fromuserid;
}
public void setFromuserid(String fromuserid) {
this.fromuserid = fromuserid;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTouserid() {
return touserid;
}
public void setTouserid(String touserid) {
this.touserid = touserid;
}
}
服务器应用:
/**
*
*/
@Component
@ServerEndpoint("/mywebsocket/{userid}")
public class Mywebsocket {
//
// public MyWebSocket() {
// System.out.println("实例化");
// }
//
// /**
// * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
// */
// private static ConcurrentHashMap<String, MyWebSocket> webSocketMap = new ConcurrentHashMap<>();
//
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 当前链接登录用户userId
*/
private String userid;
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userid") String userid) throws Exception {
this.userid = userid;//连接成功就把用户的id保存起来,为后续的关闭及发送消息使用
this.session = session;
System.out.println(userid + "用户连接服务器成功" + session.getId());
//保存的登陆的用户id及session对象
try {
Session put = SocketLoginSession.getLoginSessionMap().put(userid, session);
System.out.println(put);
} catch (Exception e) {
System.out.println(e.getMessage());
}
// try {
// sendMessage("连接成功");//发送给客户端
// this.session.getBasicRemote().sendText("连接成功");
// } catch (IOException e) {
// }
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() throws IOException {
this.session.close();
System.out.println(this.userid + "关闭了");
}
/**
* 客户端主动发送消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
messageObject messageObject = objectMapper.readValue(message, messageObject.class);
messageObject.setFromuserid(this.userid);
try {
//获取接受者登陆的session
Session session1 = SocketLoginSession.getLoginSessionMap().get(messageObject.getTouserid());
//发送消息
session1.getBasicRemote().sendText(objectMapper.writeValueAsString(messageObject));
} catch (Exception e) {
}
//发送消息
// System.out.println(this.userid + "发送的信息:" + messageObject.getMessage() + messageObject.getTouserid());
}
/**
* 出错时调用方法
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println(this.userid + "错误");
error.printStackTrace();
}
/**
* 自己封装的方法 服务器发送信息给客户端
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
}
前端应用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
var websocket = null;
/**
* 模拟登陆成功
*/
function login() {
var userid = document.getElementById("loginuser").value;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8081/mywebsocket/" + userid);
alert("客户端创建websocket与服务器连接成功");
} else {
alert('Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
setMessageInnerHTML("error");
}
//连接成功建立的回调方法
websocket.onopen = function (event) {
setMessageInnerHTML("open");
document.getElementById("div").innerHTML = document.getElementById("loginuser").value + "用户登陆成功。"
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
}
//连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("close");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
websocket.close();
}
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
// window.onbeforeunload = function () {
// websocket.close();
// }
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('messagebox').innerHTML += innerHTML + '<br/>';
}
//关闭连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function send() {
var message = document.getElementById('message').value;
var touserid = document.getElementById('touserid').value; //接受人id
// alert("message=" + message);
var object = {"message": message, "touserid": touserid};
websocket.send(JSON.stringify(object));
}
</script>
</head>
<body>
<DIV id="div" style="border: aqua 1px solid"></DIV>
登录用户ID:<input type="text" id="loginuser">
<input type="button" id="login" value="模拟登录" onclick="login()"><br>
信息:<input type="text" id="message">
接受人id:<input type="text" id="touserid">
<input type="button" id="sendmessage" value="发送消息" onclick="send()">
<div id="messagebox" style="border: 1px solid red;">
</div>
</body>
</html>
SpringBoot整合Quartz
Job 任务
JobDetail 任务信息
Trigger 触发器
Scheduler 调度器
*什么是Quartz*
在项⽬开发中,经常需要定时任务来帮助我们来做⼀些内容,⽐如定时派息、跑批对账、业务监控等。Spring Boot 体系中现在有两种⽅案可以选择,第⼀种是 Spring Boot 内置的⽅式简单注解就可以使⽤,当然如果需要更复杂的应⽤场景还是得 Quartz 上场,Quartz ⽬前是 Java 体系中最完善的定时⽅案,是 OpenSymphony 开源组织在 Job Scheduling 领域⼜⼀个开源项⽬,是完全由 Java 开发的⼀个开源任务⽇程管理系统,“任务进度管理器”就是⼀个在预先确定(被纳⼊⽇程)的时间到达时,负责执⾏(或者通知)其他软件组件的系统。 Quartz 是⼀个开源的作业调度框架,它完全由 Java 写成,并设计⽤于J2SE 和 J2EE 应⽤中,它提供了巨⼤的灵活性⽽不牺牲简单性。
当定时任务愈加复杂时,使⽤ Spring 注解 @Schedule 已经不能满⾜业务需要
*Quartz 的优点:*
丰富的 Job 操作 API;
⽀持多种配置;
Spring Boot ⽆缝集成;
⽀持持久化;
⽀持集群;
Quartz 还⽀持开源,是⼀个功能丰富的开源作业调度库,可以集成到⼏乎任何 Java 应⽤程序中。
1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2.先定义⼀个 SampleJob 需要继承 QuartzJobBean
package com.demo.websocket.QuartzJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class Job extends QuartzJobBean {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
System.out.println(String.format("Hello %s!", this.name));
}
}
3.构建 JobDetail,并且构建时传⼊属性的值
package com.demo.websocket.QuartzJob;
import org.quartz.*;
import org.quartz.JobDetail;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SampleScheduler {
@Bean
public JobDetail sampleJobDetail() {
//withIdentity定义 TriggerKey,也可以不设置,会⾃动⽣成⼀个独⼀⽆⼆的 TriggerKey ⽤来区分不同的 Trigger
//usingJobData("name", "World定时器") 设置SampleJob属性对应的值
return JobBuilder.newJob(SampleJob.class).withIdentity("sampleJob")
.usingJobData("name", "World定时器").storeDurably().build();
}
@Bean
public Trigger sampleJobTrigger() {
//withIntervalInSeconds(10)每隔10秒钟执行一次
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever();
return TriggerBuilder.newTrigger().forJob(sampleJobDetail())
.withIdentity("sampleTrigger").withSchedule(scheduleBuilder).build
();
}
// Cron表达式设置复杂的启动方式
// 把上面的那个sampleJobTrigger方法换成下面这个
// @Bean
// public Trigger printTimeJobTrigger() {
// CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
// return TriggerBuilder.newTrigger()
// .forJob(sampleJobDetail())//关联上述的JobDetail
// .withIdentity("quartzTaskService")//给Trigger起个名字
// .withSchedule(cronScheduleBuilder)
// .build();
//
// }
}
4.启动项⽬后每隔两秒输出:Hello World!
SpringBoot整合Redis
1。依赖
<!-- redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.application配置
# Redis 数据库索引(默认为 0)
spring.redis.database=0
# Redis 服务器地址
spring.redis.host=127.0.0.1
# Redis 服务器连接端⼝
spring.redis.port=6379
# Redis 服务器连接密码(默认为空)
spring.redis.password=
# 连接池最⼤连接数(使⽤负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最⼤阻塞等待时间(使⽤负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最⼤空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最⼩空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
3.Redis模板类的配置,设置序列化的方式等
**
* 为 Redis 设置⼀些全局配置
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
//@EnableCaching开启缓存
@Bean(name = "redisTemplate")
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
template.setConnectionFactory(factory);
//key序列化方式,如果不设置,会有乱码
template.setKeySerializer(redisSerializer);
//value序列化
template.setValueSerializer(redisSerializer);
//value hashmap序列化
template.setHashValueSerializer(redisSerializer);
//key haspmap序列化
template.setHashKeySerializer(redisSerializer);
return template;
}
@Bean(name = "redisTemplate2")
public RedisTemplate<String, Object> redisTemplate2(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
4.Redis工具类
@Repository
public class TestRedisTemplate {
@Resource(name = "redisTemplate2")
private RedisTemplate redisTemplate;
public void testString() {
System.out.println("redis");
redisTemplate.opsForValue().set("b", "ityouknow你好");//字符
// redisTemplate.opsForValue().set("bb", "ityouknow你好",10,TimeUnit.SECONDS);
User2 u2=new User2();
u2.setAddress("as");
u2.setImgpath("dfd/dfd.jpg");
redisTemplate.opsForValue().set("objuser",u2);//对象
Object v = redisTemplate.opsForValue().get("b");
User2 u=(User2)redisTemplate.opsForValue().get("objuser");
System.out.println(v + "===--"+u.getImgpath());
}
}
/**
* redis 字符模版工具类 String 类型
*/
@Repository
public class RedisStringTemplate {
@Resource(name = "redisTemplate")
RedisTemplate redisTemplate;
public void set(String key,Object value) {
this.redisTemplate.opsForValue().set(key,value);
}
public <T>T get(String key){
return (T) this.redisTemplate.opsForValue().get(key);
}
}
5.测试
@RestController
public class RedisController {
@Resource(name = "testRedisTemplate")
TestRedisTemplate testRedisTemplate;
@RequestMapping("/testRedisTemplate")
public void testRedisTemplate() {
testRedisTemplate.testString();
}
}