2021-10-14-SpringBoot-01

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标准

  1. @GetMapping("/test1")  //相当与
    @RequestMapping(value = "/test1",method = RequestMethod.GET)
    
  2. @PostMapping("/test1")
    @RequestMapping(value = "/test1",method = RequestMethod.POST)
    
  3. @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();
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值