慕课网《SpringBoot开发常用技术整合》学习总结
- 时间:2018年04月19日星期四
- 说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com
- 教学源码:https://github.com/zccodere/study-imooc
- 学习源码:https://github.com/zccodere/study-imooc
SpringBoot简介
- 微框架,与Spring4一起诞生,比如@RestController
- 可以快速上手,整合了一些子项目(开源框架或者第三方开源库)
- 可以依赖很少的配置就可以十分快速的搭建并且运行项目
SpringBoot特点
- Spring全家桶的一员:基于Spring,使开发者快速入门,门槛很低
- SpringBoot可以创建独立运行的应用而不依赖于容器
- 不需要打成war包,可以放入tomcat中直接运行
- 提供maven极简配置,缺点就是会引入很多不需要的包
- 根据项目来依赖,从而配置Spring,需要什么引用什么
- 提供可视化的相关功能,方便监控,比如性能、应用的健康程度等
- 简化配置,不用再看过多的xml,使用注解进行配置
- 为微服务SpringCloud铺路,SpringBoot可以整合很多框架来构建微服务,比如Dubbo、Thrift等
SpringBoot使用场景
- 有Spring的地方都可以使用SpringBoot
- JavaWeb项目:JavaEE项目等
- 微服务:SpringCloud微服务开发的基础
Spring官方提供的项目骨架生成地址
代码编写
1.创建名为boot-start的maven项目pom文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.myimooc</groupId>
<artifactId>boot-start</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>boot-start</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring boot 热启动模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<!--optional = true,表示依赖不会传递,即该项目依赖 devtools;如果有其它项目依赖该项目,则其它项目不会自动依赖 devtools-->
<optional>true</optional>
</dependency>
<!--spring boot 配置文件加载模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--引入 Freemarker 模版引擎依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!--引入 Thymeleaf 模版引擎依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba</groupId>-->
<!--<artifactId>druid</artifactId>-->
<!--<version>1.1.0</version>-->
<!--</dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<!--<dependency>-->
<!--<groupId>com.alibaba</groupId>-->
<!--<artifactId>druid-spring-boot-starter</artifactId>-->
<!--<version>1.1.0</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!--引入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>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.编写BootStartApplication类
package com.myimooc.boot.start;
import org.n3r.idworker.Sid;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import tk.mybatis.spring.annotation.MapperScan;
/**
* <br>
* 标题: 启动类<br>
* 描述: 首个SpringBoot项目<br>
* 使用 @EnableScheduling 开启支持定时任务
* 使用 @EnableAsync 开启异步执行程序
* @author zc
* @date 2018/04/19
*/
@SpringBootApplication
@MapperScan("com.myimooc.boot.start.dao.mapper")
@EnableScheduling
@EnableAsync
public class BootStartApplication {
public static void main(String[] args) {
SpringApplication.run(BootStartApplication.class, args);
}
@Bean
public Sid sid() {
return new Sid();
}
}
3.编写HelloController类
package com.myimooc.boot.start.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <br>
* 标题: 基于REST的Controller<br>
* 描述: 返直接返回方法的响应内容<br>
*
* @author zc
* @date 2018/04/19
*/
@RestController
public class HelloController {
@GetMapping("/hello")
public Object hello(){
return "Hello SpringBoot!";
}
}
然后启动BootStartApplication,访问http://localhost:8080/hello
第二章:常用开发 2-1 响应对象通常一个应用都会有一个统一的响应对象,用于封装响应状态、响应消息、响应数据等,并提供一些常用静态方法
代码编写
1.编写JsonResult类
package com.myimooc.boot.start.domain;
import java.io.Serializable;
/**
* <br>
* 标题: 自定义JSON响应数据结构<br>
* 描述: 统一请求响应返回的格式<br>
* 200 成功
* 500 错误,错误信息在msg字段中
* 501 Bean验证错误信息,以map返回
* 502 拦截器拦截到用户token出错
* 555:抛出异常信息
* @author zc
* @date 2018/04/19
*/
public class JsonResult implements Serializable{
private static final long serialVersionUID = 4997293587553904193L;
/**
* 响应状态
*/
private Integer status;
/**
* 响应消息
*/
private String msg;
/**
* 响应数据
*/
private Object data;
public static JsonResult build(Integer status,String msg,Object data){
return new JsonResult(status,msg,data);
}
public static JsonResult ok(Object data){
return new JsonResult(200,"ok",data);
}
public static JsonResult ok(){
return JsonResult.ok(null);
}
public static JsonResult errMsg(String msg){
return new JsonResult(500,msg,null);
}
public static JsonResult errMap(Object data){
return new JsonResult(501,"error",data);
}
public static JsonResult errTokenMsg(String msg){
return new JsonResult(502,msg,null);
}
public static JsonResult errException(String msg){
return new JsonResult(555,msg,null);
}
public JsonResult() {
}
public JsonResult(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
}
@Override
public String toString() {
return "JsonResult{" +
"status=" + status +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
2.编写User类
package com.myimooc.boot.start.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable;
import java.util.Date;
/**
* <br>
* 标题: POJO类<br>
* 描述: 用户信息<br>
*
* @author zc
* @date 2018/04/19
*/
public class User implements Serializable {
private static final long serialVersionUID = 7332961063564924222L;
/**
* 名称
*/
private String name;
/**
* 密码,使用 @JsonIgnore 注解,在序列化为 JSON 时,忽略该字段
*/
@JsonIgnore
private String password;
/**
* 年龄
*/
private Integer age;
/**
* 生日,使用 @JsonFormat 注解,在序列化为 JSON 时,使用 pattern 属性指定的值格式化日期时间
*/
@JsonFormat(pattern = "yyyy-MM-dd",locale = "zh",timezone = "GMT+8")
private Date birthday;
/**
* 描述,使用 @JsonInclude 注解,在序列化为 JSON 时,当字段为 null 时,则忽略该字段
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private String note;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
", birthday=" + birthday +
", note='" + note + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
3.编写UserController类
package com.myimooc.boot.start.controller;
import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.domain.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* <br>
* 标题: 使用Controller<br>
* 描述: 返回JSON数据<br>
*
* @author zc
* @date 2018/04/19
*/
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/getUser")
public User getUser(){
User user = new User();
user.setName("myImooc2");
user.setPassword("myImooc");
user.setAge(22);
user.setBirthday(new Date());
user.setNote("Hello");
return user;
}
@GetMapping("/getUserJson")
public JsonResult getUserJson(){
User user = new User();
user.setName("myImooc2");
user.setPassword("myImooc");
user.setAge(22);
user.setBirthday(new Date());
user.setNote("Hello");
return JsonResult.ok(user);
}
}
2-2 配置文件
资源文件中的属性配置与映射到实体类,即加载配置文件到实体类中
代码编写
1.编写resource.properties
com.imooc.opensource.name=imooc
com.imooc.opensource.website=www.imooc.com
com.imooc.opensource.language=java
2.编写Resource类
package com.myimooc.boot.start.domain;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* <br>
* 标题: 配置属性实体类<br>
* 描述: 从配置文件中获取属性值<br>
*
* @author zc
* @date 2018/04/25
*/
@Configuration
@ConfigurationProperties(prefix = "com.imooc.opensource")
@PropertySource(value = "classpath:resource.properties")
public class Resource {
private String name;
private String website;
private String language;
@Override
public String toString() {
return "Resource{" +
"name='" + name + '\'' +
", website='" + website + '\'' +
", language='" + language + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
3.修改HelloController类
package com.myimooc.boot.start.controller;
import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.domain.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <br>
* 标题: 基于REST的Controller<br>
* 描述: 返直接返回方法的响应内容<br>
*
* @author zc
* @date 2018/04/19
*/
@RestController
public class HelloController {
@Autowired
private Resource resource;
@GetMapping("/hello")
public Object hello(){
return "Hello SpringBoot!";
}
@GetMapping("/getResource")
public JsonResult getResource(){
Resource target = new Resource();
BeanUtils.copyProperties(resource,target);
return JsonResult.ok(target);
}
}
第三章:技术整合
3-1 模版引擎
Spring Boot 整合模版引擎
- Spring Boot 整合 Freemarker
- Spring Boot 整合 Thymeleaf
代码编写
1.修改pom引入依赖
<!--引入 Freemarker 模版引擎依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!--引入 Thymeleaf 模版引擎依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.修改application.properties
#------------ Server 服务端相关配置
# 配置 api 端口号
#server.port=8080
# 配置 context-path,一般在正式发布时不配置
#server.servlet.context-path=/start
# 错误页,指定发生错误时,跳转的URL -> BasicErrorController
#server.error.path=/error
# session 最大超时时间(单位:秒;默认值:30分钟)
server.servlet.session.timeout=3600
# 绑定ID地址,如果本机不是该ID地址则抛出异常,根据具体业务需求来设置
#server.address=192.168.1.8
# tomcat 最大线程数(默认值:200)
#server.tomcat.max-threads=250
# tomcat 的URI编码
server.tomcat.uri-encoding=UTF-8
# 配置 i18N 资源文件,供 thymeleaf 读取
spring.messages.basename=i18n/messages
spring.messages.cache-duration=3600
spring.messages.encoding=UTF-8
# 设置静态文件路径,js、css等
spring.mvc.static-path-pattern=/static/**
#------------ Freemarker 静态资源配置
# 设置 ftl 文件路径
spring.freemarker.template-loader-path=classpath:/templates/
# 关闭缓存,即时刷新,生产环境需改为true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl
#------------ Thymeleaf 静态资源配置
spring.thymeleaf.prefix=classpath:/templates/
# 关闭缓存,即时刷新,生产环境需改为true
spring.thymeleaf.cache=false
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html
3.编写FreemarkerController类
package com.myimooc.boot.start.controller;
import com.myimooc.boot.start.domain.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* <br>
* 标题: Freemarker<br>
* 描述: 整合 Freemarker<br>
*
* @author zc
* @date 2018/04/25
*/
@Controller
@RequestMapping("ftl")
public class FreemarkerController {
@Autowired
private Resource resource;
@GetMapping("/index")
public String index(ModelMap map){
map.addAttribute("resource",resource);
return "freemarker/index";
}
@GetMapping("/center")
public String center(){
return "freemarker/center/center";
}
}
4.编写ThymeleafController类
package com.myimooc.boot.start.controller;
import com.myimooc.boot.start.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* <br>
* 标题: Thymeleaf<br>
* 描述: 整合 Thymeleaf<br>
*
* @author zc
* @date 2018/04/25
*/
@Controller
@RequestMapping("th")
public class ThymeleafController {
@RequestMapping("/index")
public String index(ModelMap map) {
map.addAttribute("name", "thymeleaf-imooc");
return "thymeleaf/index";
}
@RequestMapping("center")
public String center() {
return "thymeleaf/center/center";
}
@RequestMapping("test")
public String test(ModelMap map) {
User u = new User();
u.setName("superadmin");
u.setAge(10);
u.setPassword("123465");
u.setBirthday(new Date());
u.setNote("<font color='green'><b>hello imooc</b></font>");
map.addAttribute("user", u);
User u1 = new User();
u1.setAge(19);
u1.setName("imooc");
u1.setPassword("123456");
u1.setBirthday(new Date());
User u2 = new User();
u2.setAge(17);
u2.setName("LeeCX");
u2.setPassword("123456");
u2.setBirthday(new Date());
List<User> userList = new ArrayList<>();
userList.add(u);
userList.add(u1);
userList.add(u2);
map.addAttribute("userList", userList);
return "thymeleaf/test";
}
@PostMapping("postform")
public String postform(User user) {
System.out.println("姓名:" + user.getName());
System.out.println("年龄:" + user.getAge());
return "redirect:/th/test";
}
@RequestMapping("showerror")
public String showerror(User user) {
int a = 1 / 0;
return "redirect:/th/test";
}
}
5.受篇幅限制,页面代码就不显示了,源码请到github查看。完成后的目录结构如下
代码编写
1.编写ErrorController类
package com.myimooc.boot.start.controller;
import com.myimooc.boot.start.domain.JsonResult;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* <br>
* 标题: 错误页演示<br>
* 描述: 跳转至错误页<br>
*
* @author zc
* @date 2018/04/25
*/
@Controller
@RequestMapping("err")
public class ErrorController {
@RequestMapping("/error")
public String error() {
int a = 1 / 0;
return "thymeleaf/error";
}
@RequestMapping("/ajaxerror")
public String ajaxerror() {
return "thymeleaf/ajaxerror";
}
@RequestMapping("/getAjaxerror")
@ResponseBody
public JsonResult getAjaxerror() {
int a = 1 / 0;
return JsonResult.ok();
}
}
2.编写GlobalExceptionHandler类
package com.myimooc.boot.start.exception;
import com.myimooc.boot.start.domain.JsonResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* <br>
* 标题: 全局异常捕获,兼容 web 和 ajax<br>
* 描述: 使用 @ControllerAdvice 声明当前是助手类<br>
*
* @author zc
* @date 2018/04/25
*/
@ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final String ERROR_VIEW = "error";
@ExceptionHandler(Exception.class)
public Object handler(HttpServletRequest request, HttpServletResponse response, Exception e) {
e.printStackTrace();
if (isAjax(request)) {
return this.responseByAjax(request, response, e);
}
return this.responseByWeb(request, response, e);
}
private boolean isAjax(HttpServletRequest request) {
return (request.getHeader("X-Requested-With") != null) && ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) ;
}
private JsonResult responseByAjax(HttpServletRequest request, HttpServletResponse response, Exception e) {
return JsonResult.errException(e.getMessage());
}
private ModelAndView responseByWeb(HttpServletRequest request, HttpServletResponse response, Exception e) {
ModelAndView mav = new ModelAndView();
mav.setViewName(ERROR_VIEW);
mav.addObject("exception", e);
mav.addObject("url", request.getRequestURL());
return mav;
}
}
3-3 持久框架
Spring Boot 整合 MyBatis
- 使用generatorConfig生成mapper以及pojo
- 实现基于MyBatis的CRUD功能
- 整合MyBatis-pagehelper实现分页
- 自定义mapper的实现
受篇幅限制,代码就不显示了,源码请到github查看。
3-4 缓存技术Spring Boot 整合 Redis
代码编写
1.引入redis依赖
<!--引入redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置application.properties
#------------ redis 配置
# redis 数据库索引(默认值:0)
spring.redis.database=0
# redis 服务器地址
spring.redis.host=127.0.0.1
# redis 服务器端口
spring.redis.port=6379
3.编写JsonUtils类
package com.myimooc.boot.start.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
/**
* <br>
* 标题: 定义响应结构, 转换类<br>
* 描述: Json工具<br>
*
* @author zc
* @date 2018/04/26
*/
public class JsonUtils {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
* <p>Title: pojoToJson</p>
* <p>Description: </p>
* @param data
* @return
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param beanType 对象中的object类型
* @return
*/
public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将json数据转换成pojo对象list
* @param jsonData
* @param beanType
* @return
*/
public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
4.编写RedisOperator类
package com.myimooc.boot.start.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* <br>
* 标题: Redis 常用方法封装<br>
* 描述: 使用redisTemplate的操作实现类<br>
*
* @author zc
* @date 2018/04/26
*/
@Component
public class RedisOperator {
@Autowired
private StringRedisTemplate redisTemplate;
// Key(键),简单的key-value操作
/**
* 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。
*
* @param key
* @return
*/
public long ttl(String key) {
return redisTemplate.getExpire(key);
}
/**
* 实现命令:expire 设置过期时间,单位秒
*
* @param key
* @return
*/
public void expire(String key, long timeout) {
redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 实现命令:INCR key,增加key一次
*
* @param key
* @return
*/
public long incr(String key, long delta) {
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key
*/
public Set<String> keys(String pattern) {
return redisTemplate.keys(pattern);
}
/**
* 实现命令:DEL key,删除一个key
*
* @param key
*/
public void del(String key) {
redisTemplate.delete(key);
}
// String(字符串)
/**
* 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key)
*
* @param key
* @param value
*/
public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 实现命令:SET key value EX seconds,设置key-value和超时时间(秒)
*
* @param key
* @param value
* @param timeout (以秒为单位)
*/
public void set(String key, String value, long timeout) {
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 实现命令:GET key,返回 key所关联的字符串值。
*
* @param key
* @return value
*/
public String get(String key) {
return (String) redisTemplate.opsForValue().get(key);
}
// Hash(哈希表)
/**
* 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value
*
* @param key
* @param field
* @param value
*/
public void hset(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
/**
* 实现命令:HGET key field,返回哈希表 key中给定域 field的值
*
* @param key
* @param field
* @return
*/
public String hget(String key, String field) {
return (String) redisTemplate.opsForHash().get(key, field);
}
/**
* 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
*
* @param key
* @param fields
*/
public void hdel(String key, Object... fields) {
redisTemplate.opsForHash().delete(key, fields);
}
/**
* 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。
*
* @param key
* @return
*/
public Map<Object, Object> hgetall(String key) {
return redisTemplate.opsForHash().entries(key);
}
// List(列表)
/**
* 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头
*
* @param key
* @param value
* @return 执行 LPUSH命令后,列表的长度。
*/
public long lpush(String key, String value) {
return redisTemplate.opsForList().leftPush(key, value);
}
/**
* 实现命令:LPOP key,移除并返回列表 key的头元素。
*
* @param key
* @return 列表key的头元素。
*/
public String lpop(String key) {
return (String) redisTemplate.opsForList().leftPop(key);
}
/**
* 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。
*
* @param key
* @param value
* @return 执行 LPUSH命令后,列表的长度。
*/
public long rpush(String key, String value) {
return redisTemplate.opsForList().rightPush(key, value);
}
}
5.编写RedisController类
package com.myimooc.boot.start.controller;
import com.myimooc.boot.start.dao.po.SysUser;
import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.domain.User;
import com.myimooc.boot.start.util.JsonUtils;
import com.myimooc.boot.start.util.RedisOperator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* <br>
* 标题: 整合redis<br>
* 描述: redis访问<br>
*
* @author zc
* @date 2018/04/26
*/
@RestController
@RequestMapping("redis")
public class RedisController {
@Autowired
private StringRedisTemplate strRedis;
@Autowired
private RedisOperator redis;
@RequestMapping("/test")
public JsonResult test() {
strRedis.opsForValue().set("imooc-cache", "hello 慕课网~~~~~~");
SysUser user = new SysUser();
user.setId("100111");
user.setUsername("imooc");
user.setPassword("abc123");
user.setIsDelete(0);
user.setRegistTime(new Date());
strRedis.opsForValue().set("json:user", JsonUtils.objectToJson(user));
SysUser jsonUser = JsonUtils.jsonToPojo(strRedis.opsForValue().get("json:user"), SysUser.class);
return JsonResult.ok(jsonUser);
}
@RequestMapping("/getJsonList")
public JsonResult getJsonList() {
User user = new User();
user.setAge(18);
user.setName("慕课网");
user.setPassword("123456");
user.setBirthday(new Date());
User u1 = new User();
u1.setAge(19);
u1.setName("imooc");
u1.setPassword("123456");
u1.setBirthday(new Date());
User u2 = new User();
u2.setAge(17);
u2.setName("hello imooc");
u2.setPassword("123456");
u2.setBirthday(new Date());
List<User> userList = new ArrayList<>();
userList.add(user);
userList.add(u1);
userList.add(u2);
redis.set("json:info:userlist", JsonUtils.objectToJson(userList), 2000);
String userListJson = redis.get("json:info:userlist");
List<User> userListBorn = JsonUtils.jsonToList(userListJson, User.class);
return JsonResult.ok(userListBorn);
}
}
3-5 定时任务
代码编写
1.修改BootStartApplication启动类,增加注解
@EnableScheduling
2.编写TestTask类
package com.myimooc.boot.start.tasks;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* <br>
* 标题: 测试定时任务<br>
* 描述: 自定义定时任务<br>
*
* @author zc
* @date 2018/04/26
*/
@Component
public class TestTask {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
/**
* 定义每过3秒执行任务
* 支持使用 @Scheduled(cron = "4-40 * * * * ?") cron表达式
*/
@Scheduled(fixedRate = 3000)
public void reportCurrentTime() {
System.out.println("现在时间:" + dateFormat.format(new Date()));
}
}
3-6 异步任务
异步任务使用场景
- 发送短信
- 发送邮件
- APP消息推送
- 提高效率
代码编写
1.修改BootStartApplication启动类,增加注解
@EnableAsync
2.编写AsyncTask类
package com.myimooc.boot.start.tasks;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
/**
* <br>
* 标题: 自定义异步执行任务<br>
* 描述: 异步方法需使用 @Async 注解<br>
* 判断任务是否完成,必须返回 Future 接口
* @author zc
* @date 2018/04/26
*/
@Component
public class AsyncTask {
@Async
public Future<Boolean> doTask11() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("任务1耗时:" + (end - start) + "毫秒");
return new AsyncResult<>(true);
}
@Async
public Future<Boolean> doTask22() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(700);
long end = System.currentTimeMillis();
System.out.println("任务2耗时:" + (end - start) + "毫秒");
return new AsyncResult<>(true);
}
@Async
public Future<Boolean> doTask33() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(600);
long end = System.currentTimeMillis();
System.out.println("任务3耗时:" + (end - start) + "毫秒");
return new AsyncResult<>(true);
}
}
3.编写DoTaskController类
package com.myimooc.boot.start.tasks;
import com.myimooc.boot.start.domain.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Future;
/**
* <br>
* 标题: 调用异步方法的controller<br>
* 描述: 异步任务<br>
*
* @author zc
* @date 2018/04/26
*/
@RestController
@RequestMapping("/tasks")
public class DoTaskController {
@Autowired
private AsyncTask asyncTask;
@RequestMapping("/asyncTask")
public JsonResult asyncTask() throws Exception {
long start = System.currentTimeMillis();
Future<Boolean> a = asyncTask.doTask11();
Future<Boolean> b = asyncTask.doTask22();
Future<Boolean> c = asyncTask.doTask33();
while (!a.isDone() || !b.isDone() || !c.isDone()) {
if (a.isDone() && b.isDone() && c.isDone()) {
break;
}
}
long end = System.currentTimeMillis();
String times = "任务全部完成,总耗时:" + (end - start) + "毫秒";
System.out.println(times);
return JsonResult.ok(times);
}
}
3-7 用拦截器
Spring Boot 拦截器的使用
- 使用注解@Configuration配置拦截器
- 继承WebMvcConfigurerAdapter
- 重新addInterceptors增加需要的拦截器地址
代码编写
1.编写OneInterceptor类
package com.myimooc.boot.start.interceptor;
import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.util.JsonUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* <br>
* 标题: 自定义拦截器一<br>
* 描述: 拦截器<br>
*
* @author zc
* @date 2018/04/26
*/
public class OneInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前进行调用(Controller方法调用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object object) throws Exception {
System.out.println("被one拦截,放行...");
return true;
// 当校验不通过时,返回 ajax 错误信息
// if (true) {
// this.returnErrorResponse(response, JsonResult.errMsg("被one拦截"));
// }
// return false;
}
/**
* 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object object, ModelAndView mv)
throws Exception {
// 可以修改返回的数据
}
/**
* 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行
* (主要是用于进行资源清理工作)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object object, Exception ex)
throws Exception {
}
private void returnErrorResponse(HttpServletResponse response, JsonResult result) throws Exception {
OutputStream out = null;
try {
response.setCharacterEncoding("utf-8");
response.setContentType("text/json");
out = response.getOutputStream();
out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
out.flush();
} finally {
if (out != null) {
out.close();
}
}
}
}
2.编写TwoInterceptor类
package com.myimooc.boot.start.interceptor;
import com.myimooc.boot.start.domain.JsonResult;
import com.myimooc.boot.start.util.JsonUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* <br>
* 标题: 自定义拦截器二<br>
* 描述: 拦截器<br>
*
* @author zc
* @date 2018/04/26
*/
public class TwoInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前进行调用(Controller方法调用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
if (true) {
returnErrorResponse(response, JsonResult.errMsg("被two拦截"));
}
System.out.println("被two拦截...");
return false;
}
/**
* 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mv)
throws Exception {
}
/**
* 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception ex)
throws Exception {
}
public void returnErrorResponse(HttpServletResponse response, JsonResult result) throws Exception{
OutputStream out=null;
try{
response.setCharacterEncoding("utf-8");
response.setContentType("text/json");
out = response.getOutputStream();
out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
out.flush();
} finally{
if(out!=null){
out.close();
}
}
}
}
3.编写WebMvcConfig类
package com.myimooc.boot.start.config;
import com.myimooc.boot.start.interceptor.OneInterceptor;
import com.myimooc.boot.start.interceptor.TwoInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* <br>
* 标题: 自定义配置类<br>
* 描述: 注册自定义的拦截器<br>
*
* @author zc
* @date 2018/04/26
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* 拦截器按照顺序执行
*/
registry.addInterceptor(new TwoInterceptor()).addPathPatterns("/two/**").addPathPatterns("/one/**");
registry.addInterceptor(new OneInterceptor()).addPathPatterns("/one/**");
super.addInterceptors(registry);
}
}
第四章:课程总结
4-1 课程总结
课程总结
- 搭建项目
- 模版引擎
- 全局异常
- 持久框架
- 缓存技术
- 定时任务
- 异步任务
- 使用拦截器