一,Spring Boot 介绍
1,如果使用 Spring 开发一个"HelloWorld"的 web 应用:
• 创建一个 web 项目并且导入相关 jar 包。SpringMVC Servlet
• 创建一个 web.xml
• 编写一个控制类(Controller)
• 需要一个部署 web 应用的服务器 如 tomcat
2,Spring Boot 特点:
• Spring Boot 设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。
• 嵌入的 Tomcat,无需部署 WAR 文件
• Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方
式。
二,构建 Spring Boot 项目及启动器讲解
1.使用 maven 构建 SpringBoot 项目
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>01-spring-boot-hello</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 修改jdk版本 --> <properties> <java.version>1.7</java.version> </properties> <dependencies> <!-- springBoot的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
package com.bjsxt.controller; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * SpringBoot HelloWorld * @author Administrator * */ @Controller public class HelloWorld { @RequestMapping("/hello") @ResponseBody public Map<String, Object> showHelloWorld(){ Map<String, Object> map = new HashMap<>(); map.put("msg", "HelloWorld"); return map; } }
package com.bjsxt.controller; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * SpringBoot 启动类 * @author Administrator * */ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
2.修改 pom 文件 将 jdk 的版本更新为 1.7
3.注入 SpringBoot 启动坐标
<!-- springBoot的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
4.SpringBoot 启动器。
所谓的 springBoot 启动器其实就是一些 jar 包的集合。SprigBoot 一共提供 44 启动器。
4.1 spring-boot-starter-web
支持全栈式的 web 开发,包括了 romcat 和 springMVC 等 jar
4.2 spring-boot-starter-jdbc
支持 spring 以 jdbc 方式操作数据库的 jar 包的集合
4.3 spring-boot-starter-redis
支持 redis
5.关于编写启动器需要注意的问题
启动器存放的位置。启动器可以和 controller 位于同一个包下,或者位于 controller 的上一级
包中,但是不能放到 controller 的平级以及子包下。
一,整合 Servlet
1,通过注解扫描完成 Servlet 组件的注册
1.1 编写 servlet
/***SpringBoot 整合 Servlet 方式一 **<servlet> * <servlet-name>FirstServlet</servlet-name> * <servlet-class>com.bjsxt.servlet.FirstServlet</servlet-class> *</servlet> **<servlet-mapping> * <servlet-name>FirstServlet</servlet-name> * <url-pattern>/first</url-pattern> *</servlet-mapping> **/ package com.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * springboot整合servelt方式一 * @author Administrator * */ @WebServlet(name="FirstServlet",urlPatterns="/first") public class FirstServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("servlet执行了"); } }
1.2 编写启动类
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @SpringBootApplication @ServletComponentScan //在springboot启动时会扫描@WebServlet.并将该类实例化 public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
2,通过方法完成 Servlet 组件的注册
2.1 编写 servlet
package com.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SecondServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("SecondServlet..."); } }
2.2 编写启动类
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import com.servlet.SecondServlet; /** * springboot整合Servlet方式二 * @author Administrator * */ @SpringBootApplication public class App2 { public static void main(String[] args) { SpringApplication.run(App2.class, args); } @Bean public ServletRegistrationBean getServletRegistrationBean() { ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet()); bean.addUrlMappings("/second"); return bean; } }
二,整合 Filter
1,通过注解扫描完成 Filter 组件的注册
1.1 编写 Filter
package com.bjsxt.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; /** *SpringBoot整合Filter 方式一 *<filter> * <filter-name>FirstFilter</filter-name> * <filter-class>com.bjsxt.filter.FirstFilter</filter-class> *</filter> *<filter-mapping> * <filter-name>FirstFilter</filter-name> * <url-pattern>/first</url-pattern> *</filter-mapping> */ //@WebFilter(filterName="FirstFilter",urlPatterns={"*.do","*.jsp"}) @WebFilter(filterName="FirstFilter",urlPatterns="/first") public class FirstFilter implements Filter { @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("进入Filter"); arg2.doFilter(arg0, arg1); System.out.println("离开Filter"); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
1.2 编写启动类
package com.bjsxt; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; /** *SpringBoot整合Filter 方式一 * */ @SpringBootApplication @ServletComponentScan public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
2,通过方法完成 Filter 组件的注册
2.1 编写 Filter
package com.bjsxt.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * *SpringBoot整合Filter 方式二 * */ public class SecondFilter implements Filter { @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("进入SecondFilter"); arg2.doFilter(arg0, arg1); System.out.println("离开SecondFilter"); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
2.2 编写启动类
package com.bjsxt; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import com.bjsxt.filter.SecondFilter; import com.bjsxt.servlet.SecondServlet; /** * SpringBoot整合Filter方式二 * * */ @SpringBootApplication public class App2 { public static void main(String[] args) { SpringApplication.run(App2.class, args); } /** * 注册Servlet * @return */ @Bean public ServletRegistrationBean getServletRegistrationBean(){ ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet()); bean.addUrlMappings("/second"); return bean; } /** * 注册Filter */ @Bean public FilterRegistrationBean getFilterRegistrationBean(){ FilterRegistrationBean bean = new FilterRegistrationBean(new SecondFilter()); //bean.addUrlPatterns(new String[]{"*.do","*.jsp"}); bean.addUrlPatterns("/second"); return bean; } }
2.3编写servlet
package com.bjsxt.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** *SpringBoot整合Servlet方式一 * *<servlet> * <servlet-name>FirstServlet</servlet-name> * <servlet-class>com.bjsxt.servlet.FirstServlet</servlet-class> *</servlet> * *<servlet-mapping> * <servlet-name>FirstServlet</servlet-name> * <url-pattern>/first</url-pattern> *</servlet-mapping> * */ @WebServlet(name="FirstServlet",urlPatterns="/first") public class FirstServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("FirstServlet............"); } }
package com.bjsxt.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** *SpringBoot整合Servlet方式二 * */ public class SecondServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("SecondServlet.........."); } }
三,整合 Listener
1,通过注解扫描完成 Listener 组件的注册
1.1 编写 Listener
package com.listener; import javax.servlet.ServletContextEvent; /** * springboot 整合listener * <listener> * <listener-class>com.listener.FirstListener</listener-class> * </listener> * */ import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class FirstListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("listen....init....."); } }
1.2 编写启动类
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; /** * springboot 整合listener方式一 * @author Administrator * */ @SpringBootApplication @ServletComponentScan public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
2. 通过方法完成 Listener 组件注册
2.1 编写 Listener
package com.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * springBoot整合Listener方式二 * @author Administrator * */ public class SecondListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { } @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("secondlistener...init..."); } }
2.2 编写启动类
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import com.filter.SecondFilter; import com.listener.SecondListener; import com.servlet.SecondServlet; /** * SpringBoot整合listener方式二 * @author Administrator * */ @SpringBootApplication public class App2 { public static void main(String[] args) { SpringApplication.run(App2.class, args); } /** * 注册servlet * @return *//* @Bean public ServletRegistrationBean getServletRegistrationBean() { ServletRegistrationBean bean=new ServletRegistrationBean(new SecondServlet()); bean.addUrlMappings("/second"); return bean; }*/ /** * 注册filter */ /*@Bean public FilterRegistrationBean getFistrationBean() { FilterRegistrationBean bean=new FilterRegistrationBean(new SecondFilter()); //bean.addUrlPatterns(new String[] {"*.do","*.jsp"}); bean.addUrlPatterns("/second"); return bean; }*/ /** * 注册listener */ @Bean public ServletListenerRegistrationBean<SecondListener> getServletListenerRegistrationBean(){ ServletListenerRegistrationBean<SecondListener> bean=new ServletListenerRegistrationBean<>(new SecondListener()); return bean; } }
四,访问静态资源
1. SpringBoot 从 classpath/static 的目录
注意目录名称必须是 static
2. ServletContext 根目录下
package com.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * SpringBoot 启动类 * @author Administrator * */ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
五,文件上传
1. 编写 Controller
package com.controller; import java.io.File; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; /** * SpringBoot文件上传 * * */ //@Controller @RestController //表示该类下的方法的返回值会自动做json格式的转换 public class FileUploadController { /* * 处理文件上传 */ @RequestMapping("/fileUploadController") public Map<String, Object> fileUpload(MultipartFile filename)throws Exception{ System.out.println(filename.getOriginalFilename()); filename.transferTo(new File("e:/"+filename.getOriginalFilename())); Map<String, Object> map = new HashMap<>(); map.put("msg", "ok"); return map; } }
2. 编写启动类
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * SpringBoot 启动类 * Springboot 文件上传 * @author Administrator * */ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
3. 设置上传文件大小的默认值
设置单个上传文件的大小
spring.http.multipart.maxFileSize=200MB
设置一次请求上传文件的总容量
spring.http.multipart.maxRequestSize=200MB
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html > <head> <title>upload.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3"> <meta name="description" content="this is my page"> <!-- <meta name="content-type" content="text/html; charset=UTF-8"> --> <meta charset="UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <form action="fileUploadController" method="post" enctype="multipart/form-data"> 上传文件:<input type="file" name="filename"/><br> <input type="submit"> </form> </body> </html>
Spring Boot 第三章(视图层技术)
课程介绍:
整合 jsp
整合 freemarker
整合 Thymeleaf
一,SpringBoot 整合 jsp 技术
1,创建项目
2,修改 pom 文件,添加坐标
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com</groupId> <artifactId>08-spring-boot-view-jsp</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- jdk1.7 --> <properties> <java.version>1.7</java.version> </properties> <dependencies> <!-- springBoot的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- jasper --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> </dependencies> </project>
3,创建 springBoot 的全局配置文件,application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
4,创建 Controller
package com.controller; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.pojo.Users; /** * springBoot整合jsp * @author Administrator * */ @Controller public class UserController { /** * 处理请求,产生数据 */ @RequestMapping("/showUser") public String showUser(Model model) { List<Users> list=new ArrayList<>(); list.add(new Users(1,"张三",20)); list.add(new Users(2,"李四",22)); list.add(new Users(3,"王五",25)); //需要一个Model对象 model.addAttribute("list", list); //跳转视图 return "userList"; } }
5,创建 jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <table border="1" align="center" width="50%"> <tr> <th>ID</th> <tr>Name</th> <th>Age</th> </tr> <c:forEach items="${list}" var="user"> <tr> <td>${user.userid}</td> <td>${user.username}</td> <td>${user.userage}</td> </tr> </c:forEach> </table> </body> </html>
6,创建启动类
package com.bjsxt; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * SpringBoot启动类 * * */ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
二,SpringBoot 整合 Freemarker
1,创建项目
2,修改 pom 添加坐标
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com</groupId> <artifactId>09-spring-boot-view-freemarker</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> </properties> <dependencies> <!-- springBoot的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> </dependencies> </project>
3,编写视图
注意:springBoot 要求模板形式的视图层技术的文件必须要放到 src/main/resources 目录下必
须要一个名称为 templates
userList.ftl
<html> <head> <title>展示用户数据</title> <meta charset="utf-9"></meta> </head> <body> <table border="1" align="center" width="50%"> <tr> <th>ID</th> <th>Name</th> <th>Age</th> </tr> <#list list as user > <tr> <td>${user.userid}</td> <td>${user.username}</td> <td>${user.userage}</td> </tr> </#list> </table> </body> </html>
4,创建 Controller
package com.bjsxt.controller; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.bjsxt.pojo.Users; /** * SpringBoot整合jsp * * */ @Controller public class UserController { /* * 处理请求,产生数据 */ @RequestMapping("/showUser") public String showUser(Model model){ List<Users> list = new ArrayList<>(); list.add(new Users(1,"张三",20)); list.add(new Users(2,"李四",22)); list.add(new Users(3,"王五",24)); //需要一个Model对象 model.addAttribute("list", list); //跳转视图 return "userList"; } }
5,创建启动器
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
三,SpringBoot 整合 Thymeleaf (重点讲解)
1. 创建 Thymeleaf 的入门项目
1.1 创建项目
1.2 修改 pom 文件添加坐标
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com</groupId> <artifactId>10-spring-boot-view-thymeleaf</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> </project>
1.3 创建存放视图的目录
目录位置:src/main/resources/templates
templates:该目录是安全的。意味着该目录下的内容是不允许外界直接访问的。
2. Thymeleaf 的基本使用
2.1Thymeleaf 特点:
Thymelaef 是通过他特定语法对 html 的标记做渲染。
/*** Thymeleaf 入门案例 ***/ @Controller public class DemoController { @RequestMapping("/show") public String showInfo(Model model){ model.addAttribute("msg", "Thymeleaf 第一个案例"); return "index"; } }
2.3 创建视图 .html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Thymeleaf 入门</title> </head> <body> <span th:text="Hello"></span> <hr/> <span th:text="${msg}"></span> </body> </html>
2.4 编写启动类
/****Thymeleaf 入门案例 **/ @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
2.5 解决异常
2.5.1 解决异常方式 1
让 html 的标记按照严禁的语法去编写。
2.5.2 解决异常方式 2
Thymeleaf.jar:更新为 3.0 以上的版本
thymeleaf-layout-dialect.jar:更新为 2.0 以上的版本
更换 thymeleaf 的 jar 包的版本
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>10-spring-boot-view-thymeleaf</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.versi on></properties> <dependencies> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> </project>
3. Thymeleaf 语法详解
3.1 变量输出与字符串操作
3.1.1th:text
th:text
在页面中输出值
<span th:text="Hello"></span><br/>
<span th:text="${msg}"></span>
3.1.2th:value
th:value
可以将一个值放入到 input 标签的 value 中
<input type="text" th:value="${msg}"/>
<input type="text" th:value="ss"/>
3.1.3 判断字符串是否为空
Thymeleaf 内置对象
注意语法:
1,调用内置对象一定要用#
2,大部分的内置对象都以 s 结尾 strings、numbers、dates
${#strings.isEmpty(key)}
判断字符串是否为空,如果为空返回 true,否则返回 false
${#strings.contains(msg,'T')}
判断字符串是否包含指定的子串,如果包含返回 true,否则返回 false
${#strings.startsWith(msg,'a')}
判断当前字符串是否以子串开头,如果是返回 true,否则返回 false
${#strings.endsWith(msg,'a')}
判断当前字符串是否以子串结尾,如果是返回 true,否则返回 false
${#strings.length(msg)}
返回字符串的长度
${#strings.indexOf(msg,'h')}
查找子串的位置,并返回该子串的下标,如果没找到则返回-1
${#strings.substring(msg,13)}
${#strings.substring(msg,13,15)}
截取子串,用户与 jdk String 类下 SubString 方法相同
${#strings.toUpperCase(msg)}
${#strings.toLowerCase(msg)}
字符串转大小写。
3.2 日期格式化处理
${#dates.format(key)}
格式化日期,默认的以浏览器默认语言为格式化标准
${#dates.format(key,'yyy/MM/dd')}
按照自定义的格式做日期转换
${#dates.year(key)}
${#dates.month(key)}
${#dates.day(key)}
year:取年
Month:取月
Day:取日
3.3 条件判断
3.3.1th:if
<span th:if="${sex} == '男'">
性别:男
</span>
<span th:if="${sex} == '女'">
性别:女
</span>
3.3.2th:switch
<div th:switch="${id}">
<span th:case="1">ID 为 1</span>
<span th:case="2">ID 为 2</span><span th:case="3">ID 为 3</span>
</div>
3.4 迭代遍历
3.4.1th:each
@RequestMapping("/show3") public String showInfo3(Model model){ List<Users> list = new ArrayList<>(); list.add(new Users(1,"张三",20)); list.add(new Users(2,"李四",22)); list.add(new Users(3,"王五",24)); model.addAttribute("list", list); return "index3"; }
<table border="1"> <tr> <th>ID</th> <th>Name</th> <th>Age</th> </tr> <tr th:each="u : ${list}"> <td th:text="${u.userid}"></td> <td th:text="${u.username}"></td> <td th:text="${u.userage}"></td> </tr> </table>
3.4.2ht:each 状态变量
@RequestMapping("/show3") public String showInfo3(Model model){ List<Users> list = new ArrayList<>(); list.add(new Users(1,"张三",20)); list.add(new Users(2,"李四",22)); list.add(new Users(3,"王五",24)); model.addAttribute("list", list); return "index3"; }
<table border="1"> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th>Index</th> <th>Count</th> <th>Size</th> <th>Even</th> <th>Odd</th> <th>First</th> <th>lase</th> </tr> <tr th:each="u,var : ${list}"> <td th:text="${u.userid}"></td> <td th:text="${u.username}"></td> <td th:text="${u.userage}"></td> <td th:text="${var.index}"></td> <td th:text="${var.count}"></td> <td th:text="${var.size}"></td> <td th:text="${var.even}"></td> <td th:text="${var.odd}"></td> <td th:text="${var.first}"></td> <td th:text="${var.last}"></td> </tr> </table>
状态变量属性
1,index:当前迭代器的索引 从 0 开始
2,count:当前迭代对象的计数 从 1 开始
3,size:被迭代对象的长度
4,even/odd:布尔值,当前循环是否是偶数/奇数 从 0 开始
5,first:布尔值,当前循环的是否是第一条,如果是返回 true 否则返回 false
6,last:布尔值,当前循环的是否是最后一条,如果是则返回 true 否则返回 false
3.4.3th:each 迭代 Map
@RequestMapping("/show4") public String showInfo4(Model model){ Map<String, Users> map = new HashMap<>(); map.put("u1", new Users(1,"张三",20)); map.put("u2", new Users(2,"李四",22)); map.put("u3", new Users(3,"王五",24)); model.addAttribute("map", map); return "index4"; }
<table border="1"> <tr> <th>ID</th> <th>Name</th> <th>Age</th> </tr> <tr th:each="maps : ${map}"> <td th:text="${maps}"></td> </tr> </table> <th/> <table border="1"> <tr><th>ID</th> <th>Name</th> <th>Age</th> </tr> <tr th:each="maps : ${map}"> <td th:each="entry:${maps}" th:text="${entry.value.userid}" ></td> <td th:each="entry:${maps}" th:text="${entry.value.username}"> </td> <td th:each="entry:${maps}" th:text="${entry.value.userage}"></td> </tr> </table>
3.5 域对象操作
3.5.1HttpServletRequest
request.setAttribute("req", "HttpServletRequest");
Request:<span
th:text="${#httpServletRequest.getAttribute('req')}"></span><br/>
3.5.2HttpSession
request.getSession().setAttribute("sess", "HttpSession");
Session:<span th:text="${session.sess}"></span><br/>
3.5.3ServletContext
request.getSession().getServletContext().setAttribute("app",
"Application");
Application:<span th:text="${application.app}"></span>
3.6 URL 表达式
th:href
th:src
3.6.1url 表达式语法
基本语法:@{}
3.6.2URL 类型
3.6.2.1 绝对路径
<a th:href="@{http://www.baidu.com}">绝对路径</a><br/>
3.6.2.2 相对路径
1)相对于当前项目的根
相对于项目的上下文的相对路径
<a th:href="@{/show}">相对路径</a>
2) 相对于服务器路径的根
<a th:href="@{~/project2/resourcename}">相对于服务器的根</a>3.6.3 在 url 中实现参数传递
<a th:href="@{/show(id=1,name=zhagnsan)}">相对路径-传参</a>
3.6.4 在 url 中通过 restful 风格进行参数传递
<a th:href="@{/path/{id}/show(id=1,name=zhagnsan)}"> 相 对 路 径 - 传 参-restful</a>
SpringBoot 第四章
(SpringBoot 整合 SpringMVC+MyBatis)需求分析:通过使用 SpringBoot+SpringMVC+MyBatis 整合实现一
个对数据库中的 users 表的 CRUD 的操作
一、 创建项目
1 修改 pom 文件
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>12-spring-boot-springmvc-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.7</java.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.ve
rsion>
</properties>
<dependencies>
<!-- springBoot 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- web 启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Mybatis 启动器 --><dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
</dependencies>
</project>
2 添加 application.properties 全局配置文件
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.type-aliases-package=com.bjsxt.pojo
3 数据库表设计
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
二、 添加用户
1 创建实体类
public class Users {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2 创建 mapper 接口以及映射配置文件
import com.bjsxt.pojo.Users;
public interface UsersMapper {
void insertUser(Users users);
}
<?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.bjsxt.mapper.UsersMapper">
<insert id="insertUser" parameterType="users">
insert into users(name,age) values(#{name},#{age})
</insert>
</mapper>
3 创建业务层
@Service
@Transactional
public class UsersServiceImpl implements UsersService {
@Autowired
private UsersMapper usersMapper;
@Override
public void addUser(Users users) {
this.usersMapper.insertUser(users);
}
}
4 创建 Controller
@Controller
@RequestMapping("/users")
public class UsersController {
@Autowired
private UsersService usersService;
/**
* 页面跳转
*/
@RequestMapping("/{page}")
public String showPage(@PathVariable String page){
return page;
}
/*** 添加用户
*/
@RequestMapping("/addUser")
public String addUser(Users users){
this.usersService.addUser(users);
return "ok";
}
}
5 编写页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>添加用户</title>
</head>
<body>
<form th:action="@{/users/addUser}" method="post">
用户姓名:<input type="text" name="name"/><br/>
用户年龄:<input type="text" name="age"/><br/>
<input type="submit" value="确定"/><br/>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>操作提示页面</title>
</head>
<body>
操作成功!!!
</body>
</html>
6 启动类
@SpringBootApplication
@MapperScan("com.bjsxt.mapper") //@MapperScan 用户扫描MyBatis的Mapper接口
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
三、 查询用户
1 在 mapper 接口中以及映射配置文件中添加相关代码
List<Users> selectUsersAll();
<select id="selectUsersAll" resultType="users">
select id,name,age from users
</select>
2 在业务层中添加查询方法
@Override
public List<Users> findUserAll() {
return this.usersMapper.selectUsersAll();
}
3 在 Controller 中添加方法
/**
* 查询全部用户
*/
@RequestMapping("/findUserAll")
public String findUserAll(Model model){
List<Users> list = this.usersService.findUserAll();
model.addAttribute("list", list);
return "showUsers";
}
4 添加页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>展示用户数据</title>
</head>
<body>
<table border="1" style="300px;">
<tr>
<th>用户 ID</th>
<th>用户姓名</th>
<th>用户年龄</th>
</tr>
<tr th:each="user : ${list}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
</tr>
</table>
</body>
</html>
四、 用户更新
1 更新用户之前的查询,并将数据在页面中回显
1.1修改 mapper 接口以及映射配置文件
Users selectUsersById(Integer id);
<select id="selectUsersById" resultType="users">
select id,name,age from users where id = #{value}
</select>
1.2修改业务层代码
@Override
public Users findUserById(Integer id) {
return this.usersMapper.selectUsersById(id);
}1.3修改 Controller
/**
* 根据用户 id 查询用户
*/
@RequestMapping("/findUserById")
public String findUserById(Integer id,Model model){
Users user = this.usersService.findUserById(id);
model.addAttribute("user", user);
return "updateUser";
}
1.4添加页面 updateUsers.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form th:action="@{/users/editUser}" method="post">
<input type="hidden" name="id" th:field="${user.id}"/>
用户姓名:<input type="text" name="name"
th:field="${user.name}"/><br/>
用户年龄:<input type="text" name="age"
th:field="${user.age}"/><br/>
<input type="submit" value="确定"/><br/>
</form>
</body>
</html>
1.5修改 showUsers.html 页面添加操作功能
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>展示用户数据</title>
</head>
<body>
<table border="1" style="300px;"><tr>
<th>用户 ID</th>
<th>用户姓名</th>
<th>用户年龄</th>
<th>操作</th>
</tr>
<tr th:each="user : ${list}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
<td>
<a th:href="@{/users/findUserById(id=${user.id})}">更
新用户</a>
</td>
</tr>
</table>
</body>
</html>
2 用户更新
2.1修改 mapper 接口以及映射配置文件
void updateUser(Users users);
<update id="updateUser" parameterType="users">
update users set name=#{name} ,age=#{age} where id=#{id}
</update>
2.2修改业务层代码
@Override
public void updateUser(Users users) {
this.usersMapper.updateUser(users);
}
2.3修改 Controller
/**
* 更新用户
*/@RequestMapping("/editUser")
public String editUser(Users users){
this.usersService.updateUser(users);
return "ok";
}
五、 删除用户
1 修改 mapper 接口以及映射配置文件
void deleteUserById(Integer id);
<delete id="deleteUserById">
delete from users where id = #{value}
</delete>
2 修改业务层代码
@Override
public void deleteUserById(Integer id) {
this.usersMapper.deleteUserById(id);
}
3 修改 Controller
/**
* 删除用户
*/
@RequestMapping("/delUser")
public String delUser(Integer id){
this.usersService.deleteUserById(id);
return "redirect:/users/findUserAll";
}
4 修改 showUsers.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>展示用户数据</title></head>
<body>
<table border="1" style="300px;">
<tr>
<th>用户 ID</th>
<th>用户姓名</th>
<th>用户年龄</th>
<th>操作</th>
</tr>
<tr th:each="user : ${list}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
<td>
<a th:href="@{/users/findUserById(id=${user.id})}">更
新用户</a>
<a th:href="@{/users/delUser(id=${user.id})}">删除用户
</a>
</td>
</tr>
</table>
</body>
</html>
SpringBoot 第一章服务端表单数据校验
(SpringBoot 高级)
一、 实现添加用户功能
1 创建项目
2 修改 POM 文件
<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> <parent><groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>13-spring-boot-validate</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.ve rsion> </properties> <dependencies> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- thymeleaf 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> </project>
3 编写添加用户功能创建实体类
public class Users { private String name; private String password; private Integer age; 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; } @Override public String toString() { return "Users [name=" + name + ", password=" + password + ", age=" + age + "]"; } }
3.1编写 Controller
/** * SpringBoot 表单数据校验 * * */ @Controller public class UsersController { @RequestMapping("/addUser") public String showPage(){ return "add"; } /** * 完成用户添加 */ @RequestMapping("/save") public String saveUser(Users users){ System.out.println(users); return "ok"; }}
3.2编写页面 add.html ok.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>添加用户</title> </head> <body> <form th:action="@{/save}" method="post"> 用户姓名:<input type="text" name="name"/><br/> 用户密码:<input type="password" name="password" /><br/> 用户年龄:<input type="text" name="age" /><br/> <input type="submit" value="OK"/> </form> </body> </html> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>操作成功</title> </head> <body> OK。。。。 </body> </html>
二、 SpringBoot 对表单做数据校验
1 SpringBoot 对表单数据校验的技术特点
1.1SpringBoot 中使用了 Hibernate-validate 校验框架
2 SpringBoot 表单数据校验步骤
2.1在实体类中添加校验规则
public class Users { @NotBlank //非空校验 private String name; @NotBlank //密码非空校验 private String password; private Integer age; 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; } @Override public String toString() { return "Users [name=" + name + ", password=" + password + ", age=" + age + "]"; } }
2.2在 Controller 中开启校验
/** * 完成用户添加 *@Valid 开启对 Users 对象的数据校验 *BindingResult:封装了校验的结果 */ @RequestMapping("/save") public String saveUser(@Valid Users users,BindingResult result){ if(result.hasErrors()){ return "add"; } System.out.println(users); return "ok"; }
2.3在页面中获取提示信息
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>添加用户</title> </head> <body> <form th:action="@{/save}" method="post"> 用户姓名:<input type="text" name="name"/><font color="red" th:errors="${users.name}"></font><br/> 用户密码:<input type="password" name="password" /><font color="red" th:errors="${users.password}"></font><br/> 用户年龄:<input type="text" name="age" /><font color="red" th:errors="${users.age}"></font><br/> <input type="submit" value="OK"/> </form> </body> </html>
2.4遇到异常
三、 解决数据校验时的异常问题
解决异常的方法,在跳转页面的方法中注入一个对象,来解决问题。要求参数对象的
变量名必须是对象的类名的全称首字母小写。
代码
/** * 解决异常的方式。可以在跳转页面的方法中注入一个 Uesrs 对象。 * 注意:由于 springmvc 会将该对象放入到 Model 中传递。key 的名称会使用 该对象的驼峰式的命名规则来作为 key。 * 参数的变量名需要与对象的名称相同。将首字母小写。 ** @param users * @return */ @RequestMapping("/addUser") public String showPage( Users users){ return "add"; } /** * 完成用户添加 *@Valid 开启对 Users 对象的数据校验 *BindingResult:封装了校验的结果 */ @RequestMapping("/save") public String saveUser( @Valid Users users,BindingResult result){ if(result.hasErrors()){ return "add"; }System.out.println(users); return "ok"; }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>添加用户</title> </head> <body> <form th:action="@{/save}" method="post"> 用户姓名:<input type="text" name="name"/><font color="red" th:errors="${users.name}"></font><br/> 用户密码:<input type="password" name="password" /><font color="red" th:errors="${users.password}"></font><br/> 用户年龄:<input type="text" name="age" /><font color="red" th:errors="${users.age}"></font><br/> <input type="submit" value="OK"/> </form> </body> </html>
如果参数的名称需要做改变
/**** 如果想为传递的对象更改名称,可以使用@ModelAttribute("aa")这表示当 前传递的对象的 key 为 aa。 * 那么我们在页面中获取该对象的 key 也需要修改为 aa * @param users * @return */ @RequestMapping("/addUser") public String showPage(@ModelAttribute("aa") Users users){ return "add"; } /** * 完成用户添加 *@Valid 开启对 Users 对象的数据校验 *BindingResult:封装了校验的结果 */ @RequestMapping("/save") public String saveUser(@ModelAttribute("aa") @Valid Users users,BindingResult result){ if(result.hasErrors()){ return "add"; }System.out.println(users); return "ok"; }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>添加用户</title> </head> <body> <form th:action="@{/save}" method="post"> 用户姓名:<input type="text" name="name"/><font color="red" th:errors="${aa.name}"></font><br/> 用户密码:<input type="password" name="password" /><font color="red" th:errors="${aa.password}"></font><br/> 用户年龄:<input type="text" name="age" /><font color="red" th:errors="${aa.age}"></font><br/> <input type="submit" value="OK"/> </form> </body> </html>
四、 其他校验规则
@NotBlank: 判断字符串是否为 null 或者是空串(去掉首尾空格)。
@NotEmpty: 判断字符串是否 null 或者是空串。
@Length: 判断字符的长度(最大或者最小)
@Min: 判断数值最小值
@Max: 判断数值最大值
@Email: 判断邮箱是否合法
Spring Boot 第二章异常处理与单元测试
(SpringBoot 高级)
@RestControllerAdvice @Slf4j public class CustomExceptionHandler { @ExceptionHandler(value = Exception.class) public DataResult exception(Exception e){ log.error("Exception,{},{}",e.getLocalizedMessage(),e); return DataResult.getResult(BaseResponseCode.SYSTEM_ERROR); } @ExceptionHandler(value = BusinessException.class) public DataResult businessException(BusinessException e){ log.error("businessException,{},{}",e.getLocalizedMessage(),e); return DataResult.getResult(e.getCode(), e.getDefaultMessage()); } /** * 处理validation 框架异常 * @Author: 小霍 * @UpdateUser: * @Version: 0.0.1 * @param e * @return com.yingxue.lesson.utils.DataResult<T> * @throws */ @ExceptionHandler(MethodArgumentNotValidException.class) <T> DataResult<T> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { log.error("methodArgumentNotValidExceptionHandler bindingResult.allErrors():{},exception:{}", e.getBindingResult().getAllErrors(), e); List<ObjectError> errors = e.getBindingResult().getAllErrors(); return createValidExceptionResp(errors); } private <T> DataResult<T> createValidExceptionResp(List<ObjectError> errors) { String[] msgs = new String[errors.size()]; int i = 0; for (ObjectError error : errors) { msgs[i] = error.getDefaultMessage(); log.info("msg={}",msgs[i]); i++; } return DataResult.getResult(BaseResponseCode.METHOD_IDENTITY_ERROR.getCode(), msgs[0]); } @ExceptionHandler(UnauthorizedException.class) public DataResult unauthorizedException(UnauthorizedException e){ log.error("UnauthorizedException,{},{}",e.getLocalizedMessage(),e); return DataResult.getResult(BaseResponseCode.NOT_PERMISSION); } }
一、 SpringBoot 中异常处理方式
1 SpringBoot 中对于异常处理提供了五种处理方式
1.1自定义错误页面
SpringBoot 默认的处理异常的机制:SpringBoot 默认的已经提供了一套处理异常的机制。
一旦程序中出现了异常 SpringBoot 会像/error 的 url 发送请求。在 springBoot 中提供了一个
叫 BasicExceptionController 来处理/error 请求,然后跳转到默认显示异常的页面来展示异常
信息。
如 果 我 们 需 要 将 所 有 的 异 常 同 一 跳 转 到 自 定 义 的 错 误 页 面 , 需 要 再
src/main/resources/templates 目录下创建 error.html 页面。注意:名称必须叫 error
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>错误提示页面</title> </head> <body> 出错了,请与管理员联系。。。 <span th:text="${exception}"></span> </body> </html>
1.2@ExceptionHandle 注解处理异常
1.2.1 Controller
/** * SpringBoot 处理异常方式一:自定义错误页面 * * */ @Controller public class DemoController { @RequestMapping("/show") public String showInfo(){ String str = null; str.length(); return "index"; } @RequestMapping("/show2") public String showInfo2(){ int a = 10/0; return "index"; } /** * java.lang.ArithmeticException * 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视 图的指定 * 参数 Exception e:会将产生异常对象注入到方法中 */ @ExceptionHandler(value={java.lang.ArithmeticException.class}) public ModelAndView arithmeticExceptionHandler(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("error", e.toString()); mv.setViewName("error1"); return mv; } /** * java.lang.NullPointerException * 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视 图的指定* 参数 Exception e:会将产生异常对象注入到方法中 */ @ExceptionHandler(value={java.lang.NullPointerException.class}) public ModelAndView nullPointerExceptionHandler(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("error", e.toString()); mv.setViewName("error2"); return mv; } }
1.2.2 页面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>错误提示页面-ArithmeticException</title> </head> <body> 出错了,请与管理员联系。。。 <span th:text="${error}"></span> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>错误提示页面-NullPointerException</title> </head> <body> 出错了,请与管理员联系。。。 <span th:text="${error}"></span> </body> </html>
1.3@ControllerAdvice+@ExceptionHandler 注解处理异常
1.3.1 需要创建一个能够处理异常的全局异常类。在该类上需要添加@ControllerAdvice 注解
/** * 全局异常处理类 * * */ @ControllerAdvice public class GlobalException { /** * java.lang.ArithmeticException * 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视 图的指定 * 参数 Exception e:会将产生异常对象注入到方法中 */ @ExceptionHandler(value={java.lang.ArithmeticException.class}) public ModelAndView arithmeticExceptionHandler(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("error", e.toString()); mv.setViewName("error1"); return mv; } /** * java.lang.NullPointerException * 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视 图的指定 * 参数 Exception e:会将产生异常对象注入到方法中 */ @ExceptionHandler(value={java.lang.NullPointerException.class}) public ModelAndView nullPointerExceptionHandler(Exception e){ ModelAndView mv = new ModelAndView(); mv.addObject("error", e.toString()); mv.setViewName("error2"); return mv; } }
1.4配置 SimpleMappingExceptionResolver 处理异常
1.4.1 在全局异常类中添加一个方法完成异常的同一处理
/** * 通过 SimpleMappingExceptionResolver 做全局异常处理 * * */ @Configuration public class GlobalException { /** * 该方法必须要有返回值。返回值类型必须是: SimpleMappingExceptionResolver */ @Bean public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){ SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); /** * 参数一:异常的类型,注意必须是异常类型的全名 * 参数二:视图名称 */ mappings.put("java.lang.ArithmeticException", "error1"); mappings.put("java.lang.NullPointerException","error2"); //设置异常与视图映射信息的 resolver.setExceptionMappings(mappings); return resolver; } }
1.5自定义 HandlerExceptionResolver 类处理异常
1.5.1 需 要 再 全 局 异 常 处 理 类 中 实 现
HandlerExceptionResolver 接口
/** * 通过实现 HandlerExceptionResolver 接口做全局异常处理 * * */ @Configuration public class GlobalException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView mv = new ModelAndView(); //判断不同异常类型,做不同视图跳转 if(ex instanceof ArithmeticException){ mv.setViewName("error1"); } if(ex instanceof NullPointerException){ mv.setViewName("error2"); } mv.addObject("error", ex.toString()); return mv; } }
二、 Spring Boot 整合 Junit 单元测试
1 创建项目
2 修改 pom 文件
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>19-spring-boot-test</artifactId> <version>0.0.1-SNAPSHOT</version> <properties><java.version>1.7</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 添加 junit 环境的 jar 包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> </project>
3 编写业务代码
3.1Dao
@Repository public class UserDaoImpl { public void saveUser(){ System.out.println("insert into users....."); } }
3.2业务层
@Service public class UserServiceImpl { @Autowired private UserDaoImpl userDaoImpl; public void addUser(){ this.userDaoImpl.saveUser(); } }
3.3编写启动类
@SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
4 使用 SpringBoot 整合 Junit 做单元测试
4.1编写测试类
/** * SpringBoot 测试类 *@RunWith:启动器 *SpringJUnit4ClassRunner.class:让 junit 与 spring 环境进行整合 * *@SpringBootTest(classes={App.class}) 1,当前类为 springBoot 的测试类 *@SpringBootTest(classes={App.class}) 2,加载 SpringBoot 启动类。启动 springBoot * *junit 与 spring 整合 @Contextconfiguartion("classpath:applicationContext.xml") */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes={App.class}) public class UserServiceTest { @Autowired private UserServiceImpl userServiceImpl; @Test public void testAddUser(){ this.userServiceImpl.addUser(); } }
(SpringBoot 高级)
一、 SpringBoot 中异常处理方式
1 SpringBoot 中对于异常处理提供了五种处理方式
1.1自定义错误页面
SpringBoot 默认的处理异常的机制:SpringBoot 默认的已经提供了一套处理异常的机制。
一旦程序中出现了异常 SpringBoot 会像/error 的 url 发送请求。在 springBoot 中提供了一个
叫 BasicExceptionController 来处理/error 请求,然后跳转到默认显示异常的页面来展示异常
信息。
如 果 我 们 需 要 将 所 有 的 异 常 同 一 跳 转 到 自 定 义 的 错 误 页 面 , 需 要 再
src/main/resources/templates 目录下创建 error.html 页面。注意:名称必须叫 error
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>错误提示页面</title>
</head>
<body>
出错了,请与管理员联系。。。
<span th:text="${exception}"></span>
</body>
</html>1.2@ExceptionHandle 注解处理异常
1.2.1 Controller
/**
* SpringBoot 处理异常方式一:自定义错误页面
*
*
*/
@Controller
public class DemoController {
@RequestMapping("/show")
public String showInfo(){
String str = null;
str.length();
return "index";
}
@RequestMapping("/show2")
public String showInfo2(){
int a = 10/0;
return "index";
}
/**
* java.lang.ArithmeticException
* 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视
图的指定
* 参数 Exception e:会将产生异常对象注入到方法中
*/
@ExceptionHandler(value={java.lang.ArithmeticException.class})
public ModelAndView arithmeticExceptionHandler(Exception e){
ModelAndView mv = new ModelAndView();
mv.addObject("error", e.toString());
mv.setViewName("error1");
return mv;
}
/**
* java.lang.NullPointerException
* 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视
图的指定* 参数 Exception e:会将产生异常对象注入到方法中
*/
@ExceptionHandler(value={java.lang.NullPointerException.class})
public ModelAndView nullPointerExceptionHandler(Exception e){
ModelAndView mv = new ModelAndView();
mv.addObject("error", e.toString());
mv.setViewName("error2");
return mv;
}
}
1.2.2 页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>错误提示页面-ArithmeticException</title>
</head>
<body>
出错了,请与管理员联系。。。
<span th:text="${error}"></span>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>错误提示页面-NullPointerException</title>
</head>
<body>
出错了,请与管理员联系。。。
<span th:text="${error}"></span>
</body>
</html>1.3@ControllerAdvice+@ExceptionHandler 注解处理异常
1.3.1 需要创建一个能够处理异常的全局异常类。在该类上需
要添加@ControllerAdvice 注解/**
* 全局异常处理类
*
*
*/
@ControllerAdvice
public class GlobalException {
/**
* java.lang.ArithmeticException
* 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视
图的指定
* 参数 Exception e:会将产生异常对象注入到方法中
*/
@ExceptionHandler(value={java.lang.ArithmeticException.class})
public ModelAndView arithmeticExceptionHandler(Exception e){
ModelAndView mv = new ModelAndView();
mv.addObject("error", e.toString());
mv.setViewName("error1");
return mv;
}
/**
* java.lang.NullPointerException
* 该方法需要返回一个 ModelAndView:目的是可以让我们封装异常信息以及视
图的指定
* 参数 Exception e:会将产生异常对象注入到方法中
*/
@ExceptionHandler(value={java.lang.NullPointerException.class})
public ModelAndView nullPointerExceptionHandler(Exception e){
ModelAndView mv = new ModelAndView();
mv.addObject("error", e.toString());
mv.setViewName("error2");
return mv;
}
}1.4配置 SimpleMappingExceptionResolver 处理异常
1.4.1 在全局异常类中添加一个方法完成异常的同一处理
/**
* 通过 SimpleMappingExceptionResolver 做全局异常处理
*
*
*/
@Configuration
public class GlobalException {
/**
* 该方法必须要有返回值。返回值类型必须是:
SimpleMappingExceptionResolver
*/
@Bean
public SimpleMappingExceptionResolver
getSimpleMappingExceptionResolver(){
SimpleMappingExceptionResolver resolver = new
SimpleMappingExceptionResolver();
Properties mappings = new Properties();
/**
* 参数一:异常的类型,注意必须是异常类型的全名
* 参数二:视图名称
*/
mappings.put("java.lang.ArithmeticException", "error1");
mappings.put("java.lang.NullPointerException","error2");
//设置异常与视图映射信息的
resolver.setExceptionMappings(mappings);
return resolver;
}
}1.5自定义 HandlerExceptionResolver 类处理异常
1.5.1 需 要 再 全 局 异 常 处 理 类 中 实 现
HandlerExceptionResolver 接口
/**
* 通过实现 HandlerExceptionResolver 接口做全局异常处理
*
*
*/
@Configuration
public class GlobalException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler,
Exception ex) {
ModelAndView mv = new ModelAndView();
//判断不同异常类型,做不同视图跳转
if(ex instanceof ArithmeticException){
mv.setViewName("error1");
}
if(ex instanceof NullPointerException){
mv.setViewName("error2");
}
mv.addObject("error", ex.toString());
return mv;
}
}
二、 Spring Boot 整合 Junit 单元测试
1 创建项目
2 修改 pom 文件
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>19-spring-boot-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties><java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加 junit 环境的 jar 包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>
3 编写业务代码
3.1Dao
@Repository
public class UserDaoImpl {
public void saveUser(){
System.out.println("insert into users.....");
}
}
3.2业务层
@Service
public class UserServiceImpl {
@Autowired
private UserDaoImpl userDaoImpl;
public void addUser(){
this.userDaoImpl.saveUser();
}
}3.3编写启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
4 使用 SpringBoot 整合 Junit 做单元测试
4.1编写测试类
/**
* SpringBoot 测试类
*@RunWith:启动器
*SpringJUnit4ClassRunner.class:让 junit 与 spring 环境进行整合
*
*@SpringBootTest(classes={App.class}) 1,当前类为 springBoot 的测试类
*@SpringBootTest(classes={App.class}) 2,加载 SpringBoot 启动类。启动
springBoot
*
*junit 与 spring 整合
@Contextconfiguartion("classpath:applicationContext.xml")
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={App.class})
public class UserServiceTest {
@Autowired
private UserServiceImpl userServiceImpl;
@Test
public void testAddUser(){
this.userServiceImpl.addUser();
}
}
Spring Boot 第三章 SpringBoot 热部署
(SpringBoot 高级)
SprigBoot 的热部署方式分为两种
SpringLoader 插件
DevTools 工具
一、 SpringLoader 插件的使用
1 创建项目
2 修改 pom 文件
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>20-spring-boot-springloader</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.7</java.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.versi
on>
</properties>
<dependencies>
<!-- springBoot 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- thymeleaf 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
3 创建 Controller
/**
* SpringBoot----SpringLoader
*
**/
@Controller
public class UsersController {
@RequestMapping("/show")
public String showPage(){
return "index";
}
}
4 编写页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span th:text="Hello...."></span>
</body>
</html>
5 创建启动类
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
6 使用 SpringLoader 进行项目的热部署
6.1方式一:以 maven 插件方式使用 SpringLoader
6.1.1 在 pom 文件中添加插件配置
<!-- springloader 插件 -->
<build>
<plugins><plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
6.1.2 使用 maven 的命令起来启动
spring-boot:run
SpringLoader 缺陷:就是 Java 代码做部署处理。但是对页面无能为力。6.1.3 注意:这种方式的缺点是 Springloader 热部署程序是在
系统后台以进程的形式来运行。需要手动关闭该进程
7 方式二:在项目中直接使用 jar 包的方式
7.1添加 springloader 的 jar 包
7.2启动方式
启动命令:
-javaagent:.libspringloaded-1.2.5.RELEASE.jar -noverify
二、 DevTools 工具
1 SpringLoader 与 DevTools 的区别:
SpringLoader:SpringLoader 在部署项目时使用的是热部署的方式。
DevTools:DevTools 在部署项目时使用的是重新部署的方式
2 修改项目的 pom 文件添加 devtools 的依赖
<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> <parent> <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>21-spring-boot-devtools</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.versi on> </properties> <dependencies> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- thymeleaf 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- DevTools 的坐标 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> </project>
第四章节 Spring Boot 整合 Spring Data JPA
(SpringBoot 高级)
一、 Spring Data JPA 介绍
Spring Data:其实 Spring Data 就是 spring 提供了一个操作数据的框架。而 Spring Data JPA
只是 Spring Data 框架下的一个基于 JPA 标准操作数据的模块。
Spring Data JPA:基于 JPA 的标准对数据进行操作。简化操作持久层的代码。只需要编
写接口就可以。
二、 Spring Boot 整合 Spring Data JPA
1 搭建整合环境
2 修改 POM 文件添加坐标
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>22-spring-boot-jpa</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.ve rsion> </properties> <dependencies> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- mysql --> <dependency><groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- druid 连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency> </dependencies> </project>
3 在项目中添加 application.properties 文件
spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/ssm spring.datasource.username=root spring.datasource.password=root spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true
4 添加实体类
@Entity @Table(name="t_users") public class Users { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id") private Integer id; @Column(name="name") private String name;@Column(name="age") private Integer age; @Column(name="address") private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Users [id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + "]"; } }
5 编写 Dao 接口
/** * 参数一 T :当前需要映射的实体 * 参数二 ID :当前映射的实体中的 OID 的类型 * */ public interface UsersRepository extends JpaRepository<Users,Integer> { }
6 在 pom 文件中添加测试启动器的坐标
<!-- 测试工具的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> 7 创建启动类 @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
8 编写测试代码
/** * 测试类 * * */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes=App.class) public class UsersRepositoryTest { @Autowiredprivate UsersRepository usersRepository; @Test public void testSave(){ Users users = new Users(); users.setAddress("北京市海淀"); users.setAge(20); users.setName("张三"); this.usersRepository.save(users); } }
三、 Spring Data JPA 提供的核心接口
1 Repository 接口
2 CrudRepository 接口
3 PagingAndSortingRepository 接口
4 JpaRepository 接口
5 JPASpecificationExecutor 接口
四、 Repository 接口的使用
提供了方法名称命名查询方式
提供了基于@Query 注解查询与更新
1 方法名称命名查询方式
1.1编写接口
/**
* Repository 接口的方法名称命名查询*
*
*/
public interface UsersRepositoryByName extends Repository<Users,
Integer> {
//方法的名称必须要遵循驼峰式命名规则。findBy(关键字)+属性名称(首字母要
大写)+查询条件(首字母大写)
List<Users> findByName(String name);
List<Users> findByNameAndAge(String name,Integer age);
List<Users> findByNameLike(String name);
}
1.2测试代码
/** * Repository--方法名称命名测试 */ @Test public void testFindByName(){ List<Users> list = this.usersRepositoryByName.findByName("张三 "); for (Users users : list) { System.out.println(users); } } /** * Repository--方法名称命名测试 */ @Test public void testFindByNameAndAge(){ List<Users> list = this.usersRepositoryByName.findByNameAndAge("张三", 20); for (Users users : list) { System.out.println(users); } } /** * Repository--方法名称命名测试*/ @Test public void testFindByNameLike(){ List<Users> list = this.usersRepositoryByName.findByNameLike(" 张%"); for (Users users : list) { System.out.println(users); } }
2 基于@Query 注解查询与更新
2.1编写接口
/** * Repository @Query * * */ public interface UsersRepositoryQueryAnnotation extends Repository<Users, Integer> { @Query("from Users where name = ?") List<Users> queryByNameUseHQL(String name); @Query(value="select * from t_users where name = ?",nativeQuery=true) List<Users> queryByNameUseSQL(String name); @Query("update Users set name = ? where id = ?") @Modifying //需要执行一个更新操作 void updateUsersNameById(String name,Integer id); }
2.2测试代码
/** * Repository--@Query 测试 */@Test public void testQueryByNameUseHQL() { List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseHQL("张三"); for (Users users : list) { System.out.println(users); } } /** * Repository--@Query 测试 */ @Test public void testQueryByNameUseSQL() { List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseSQL("张三"); for (Users users : list) { System.out.println(users); } } /** * Repository--@Query 测试 */ @Test @Transactional //@Transactional 与@Test 一起使用时 事务是自动回滚的。 @Rollback(false) //取消自动回滚 public void testUpdateUsersNameById() { this.usersRepositoryQueryAnnotation.updateUsersNameById("张三 三", 1); }
五、 CrudRepository 接口
1 CrudRepository 接口,主要是完成一些增删改查的操作。
注意:
CredRepository 接口继承 Repository 接口
2 编写接口
2 编写接口
/** * CrudRepository 接口 * * */ public interface UsersRepositoryCrudRepository extends CrudRepository<Users, Integer> { }
3 测试代码
/** * CrudRepository 测试 */ @Test public void testCrudRepositorySave() { Users user = new Users(); user.setAddress("天津"); user.setAge(32); user.setName("张三丰"); this.usersRepositoryCrudRepository.save(user); } /** * CrudRepository 测试*/ @Test public void testCrudRepositoryUpdate() { Users user = new Users(); user.setId(4); user.setAddress("南京"); user.setAge(40); user.setName("张三丰"); this.usersRepositoryCrudRepository.save(user); } /** * CrudRepository 测试 */ @Test public void testCrudRepositoryFindOne() { Users users = this.usersRepositoryCrudRepository.findOne(4); System.out.println(users); } /** * CrudRepository 测试 */ @Test public void testCrudRepositoryFindAll() { List<Users> list = (List<Users>)this.usersRepositoryCrudRepository.findAll(); for (Users users : list) { System.out.println(users); } } /** * CrudRepository 测试 */ @Test public void testCrudRepositoryDeleteById() { this.usersRepositoryCrudRepository.delete(4); }
六、 PagingAndSortingRepository 接口
1 该 接 口 提 供 了 分 页 与 排 序 的 炒 作 。 注 意 : 该 接 口 集 成 了
CrudRepository 接口
2 编写接口
/** * *PagingAndSortingRepository 接口 * */ public interface UsersRepositoryPagingAndSorting extends PagingAndSortingRepository<Users,Integer> { }
3 测试代码
/**
* PagingAndSortingRepository 排序测试
*/
@Test
public void testPagingAndSortingRepositorySort() {
//Order 定义排序规则
Order order = new Order(Direction.DESC,"id");
//Sort 对象封装了排序规则
Sort sort = new Sort(order);List<Users> list =
(List<Users>)this.usersRepositoryPagingAndSorting.findAll(sort);
for (Users users : list) {
System.out.println(users);
}
}
/**
* PagingAndSortingRepository 分页测试
*/
@Test
public void testPagingAndSortingRepositoryPaging() {
//Pageable:封装了分页的参数,当前页,每页显示的条数。注意:他的当前
页是从 0 开始。
//PageRequest(page,size) page:当前页。size:每页显示的条数
Pageable pageable = new PageRequest(1, 2);
Page<Users> page =
this.usersRepositoryPagingAndSorting.findAll(pageable);
System.out.println("总条数:"+page.getTotalElements());
System.out.println("总页数"+page.getTotalPages());
List<Users> list = page.getContent();
for (Users users : list) {
System.out.println(users);
}
}
/**
* PagingAndSortingRepository 排序+分页
*/
@Test
public void testPagingAndSortingRepositorySortAndPaging() {
Sort sort = new Sort(new Order(Direction.DESC, "id"));
Pageable pageable = new PageRequest(1, 2, sort);
Page<Users> page =
this.usersRepositoryPagingAndSorting.findAll(pageable);
System.out.println("总条数:"+page.getTotalElements());
System.out.println("总页数"+page.getTotalPages());
List<Users> list = page.getContent();
for (Users users : list) {
System.out.println(users);
}}
七、 JpaRepository 接口
1 该接口继承了 PagingAndSortingRepository 接口。对继承的父接口
中的方法的返回值进行适配。
2 编写接口
/**
* 参数一 T :当前需要映射的实体
* 参数二 ID :当前映射的实体中的 OID 的类型
*
*/
public interface UsersRepository extends JpaRepository<Users,Integer>{
}
3 测试代码
/**
* JapRepository 排序测试
*/
@Test
public void testJpaRepositorySort() {
//Order 定义排序规则
Order order = new Order(Direction.DESC,"id");
//Sort 对象封装了排序规则
Sort sort = new Sort(order);
List<Users> list = this.usersRepository.findAll(sort);
for (Users users : list) {
System.out.println(users);
}
}
八、 JPASpecificationExecutor 接口
1 该接口主要是提供了多条件查询的支持,并且可以在查询中添加
分页与排序。注意:JPASpecificationExecutor 是单独存在。完全独
立。
2 编写接口
/**
*
*JpaSpecificationExecutor
*
*/
public interface UsersRepositorySpecification extends
JpaRepository<Users, Integer>, JpaSpecificationExecutor<Users> {
}
3 测试代码
/**
* JpaSpecificationExecutor 单条件测试
*/
@Testpublic void testJpaSpecificationExecutor1() {
/**
* Specification<Users>:用于封装查询条件
*/
Specification<Users> spec = new Specification<Users>() {
//Predicate:封装了 单个的查询条件
/**
* Root<Users> root:查询对象的属性的封装。
* CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分
的信息,select from order by
* CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
// where name = '张三三'
/**
* 参数一:查询的条件属性
* 参数二:条件的值
*/
Predicate pre = cb.equal(root.get("name"), "张三三");
return pre;
}
};
List<Users> list =
this.usersRepositorySpecification.findAll(spec);
for (Users users : list) {
System.out.println(users);
}
}
/**
* JpaSpecificationExecutor 多条件测试
*/
@Test
public void testJpaSpecificationExecutor2() {
/**
* Specification<Users>:用于封装查询条件
*/
Specification<Users> spec = new Specification<Users>() {//Predicate:封装了 单个的查询条件
/**
* Root<Users> root:查询对象的属性的封装。
* CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分
的信息,select from order by
* CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
// where name = '张三三' and age = 20
List<Predicate> list = new ArrayList<>();
list.add(cb.equal(root.get("name"),"张三三"));
list.add(cb.equal(root.get("age"),20));
Predicate[] arr = new Predicate[list.size()];
return cb.and(list.toArray(arr));
}
};
List<Users> list =
this.usersRepositorySpecification.findAll(spec);
for (Users users : list) {
System.out.println(users);
}
}
4 多条件查询的第二种写法
/**
* JpaSpecificationExecutor 多条件测试第二种写法
*/
@Test
public void testJpaSpecificationExecutor3() {
/**
* Specification<Users>:用于封装查询条件
*/
Specification<Users> spec = new Specification<Users>() {
//Predicate:封装了 单个的查询条件
/**
* Root<Users> root:查询对象的属性的封装。
* CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分的信息,select from order by
* CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
*/
@Override
public Predicate toPredicate(Root<Users> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
// where name = '张三三' and age = 20
/*List<Predicate> list = new ArrayList<>();
list.add(cb.equal(root.get("name"),"张三三"));
list.add(cb.equal(root.get("age"),20));
Predicate[] arr = new Predicate[list.size()];*/
//(name = '张三' and age = 20) or id = 2
return cb.or(cb.and(cb.equal(root.get("name"),"张三三
"),cb.equal(root.get("age"),20)),cb.equal(root.get("id"), 2));
}
};
Sort sort = new Sort(new Order(Direction.DESC,"id"));
List<Users> list =
this.usersRepositorySpecification.findAll(spec,sort);
for (Users users : list) {
System.out.println(users);
}
}
九、 关联映射操作
1 一对多的关联关系
需求:角色与用户的一对多的关联关系。
角色:一方
用户:多方
1.1Users
@Entity
@Table(name="t_users")
public class Users {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)@Column(name="id")
private Integer id;
@Column(name="name")
private String name;
@Column(name="age")
private Integer age;
@Column(name="address")
private String address;
@ManyToOne
//@JoinColumn:维护外键
@JoinColumn(name="roles_id")
private Roles roles;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Users [id=" + id + ", name=" + name + ", age=" + age +
", address=" + address + "]";
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
}
1.2Roles
@Entity
@Table(name="t_roles")
public class Roles {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="roleid")
private Integer roleid;
@Column(name="rolename")
private String rolename;
@OneToMany(mappedBy="roles")
private Set<Users> users = new HashSet<>();
public Integer getRoleid() {
return roleid;
}public void setRoleid(Integer roleid) {
this.roleid = roleid;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public Set<Users> getUsers() {
return users;
}
public void setUsers(Set<Users> users) {
this.users = users;
}
}
1.3测试一对多的关联关系
/**
* 一对多关联关系测试
*
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=App.class)
public class OneToManyTest {
@Autowired
private UsersRepository usersRepository;
/**
* 一对多关联关系的添加
*/
@Test
public void testSave(){//创建一个用户
Users users = new Users();
users.setAddress("天津");
users.setAge(32);
users.setName("小刚");
//创建一个角色
Roles roles = new Roles();
roles.setRolename("管理员");
//关联
roles.getUsers().add(users);
users.setRoles(roles);
//保存
this.usersRepository.save(users);
}
/**
* 一对多关联关系的查询
*/
@Test
public void testFind(){
Users findOne = this.usersRepository.findOne(4);
System.out.println(findOne);
Roles roles = findOne.getRoles();
System.out.println(roles.getRolename());
}
}
2 多对多的关联关系
需求:角色与菜单多对多关联关系
角色:多方
菜单:多方
2.1Roles
@Entity
@Table(name="t_roles")
public class Roles {@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="roleid")
private Integer roleid;
@Column(name="rolename")
private String rolename;
@OneToMany(mappedBy="roles")
private Set<Users> users = new HashSet<>();
@ManyToMany(cascade=CascadeType.PERSIST,fetch=FetchType.EAGER)
//@JoinTable:映射中间表
//joinColumns:当前表中的主键所关联的中间表中的外键字段
@JoinTable(name="t_roles_menus",joinColumns=@JoinColumn(name="ro
le_id"),inverseJoinColumns=@JoinColumn(name="menu_id"))
private Set<Menus> menus = new HashSet<>();
public Integer getRoleid() {
return roleid;
}
public void setRoleid(Integer roleid) {
this.roleid = roleid;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public Set<Users> getUsers() {
return users;
}
public void setUsers(Set<Users> users) {
this.users = users;
}
public Set<Menus> getMenus() {return menus;
}
public void setMenus(Set<Menus> menus) {
this.menus = menus;
}
}
2.2Menus
@Entity
@Table(name="t_menus")
public class Menus {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="menusid")
private Integer menusid;
@Column(name="menusname")
private String menusname;
@Column(name="menusurl")
private String menusurl;
@Column(name="fatherid")
private Integer fatherid;
@ManyToMany(mappedBy="menus")
private Set<Roles> roles = new HashSet<>();
public Integer getMenusid() {
return menusid;
}
public void setMenusid(Integer menusid) {
this.menusid = menusid;
}
public String getMenusname() {
return menusname;}
public void setMenusname(String menusname) {
this.menusname = menusname;
}
public String getMenusurl() {
return menusurl;
}
public void setMenusurl(String menusurl) {
this.menusurl = menusurl;
}
public Integer getFatherid() {
return fatherid;
}
public void setFatherid(Integer fatherid) {
this.fatherid = fatherid;
}
public Set<Roles> getRoles() {
return roles;
}
public void setRoles(Set<Roles> roles) {
this.roles = roles;
}
@Override
public String toString() {
return "Menus [menusid=" + menusid + ", menusname=" + menusname
+ ", menusurl=" + menusurl + ", fatherid="
+ fatherid + "]";
}
}2.3测试多对多的关联关系
/**
* 多对多的关联关系的测试
*
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=App.class)
public class ManyToManyTest {
@Autowired
private RolesRepository rolesRepository;
/**
* 添加测试
*/
@Test
public void testSave(){
//创建角色对象
Roles r = new Roles();
r.setRolename("项目经理");
//创建菜单对象
Menus menus = new Menus();
menus.setMenusname("xxxx 管理系统");
menus.setFatherid(0);
Menus menus2 = new Menus();
menus2.setFatherid(1);
menus2.setMenusname("项目管理");
//关联
r.getMenus().add(menus);
r.getMenus().add(menus2);
menus.getRoles().add(r);
menus2.getRoles().add(r);
//保存
this.rolesRepository.save(r);
}
/**
* 查询操作
*/
@Testpublic void testFind(){
Roles roles = this.rolesRepository.findOne(2);
System.out.println(roles.getRolename());
Set<Menus> menus = roles.getMenus();
for (Menus menus2 : menus) {
System.out.println(menus2);
}
}
}
第五章节 Spring Boot 缓存技术
(SpringBoot 高级)
课程内容
Spring Boot 整合 Ehcache
Spring Boot 整合 Spring Data Redis
一、 Spring Boot 整合 Ehcache
1 修改 pom 文件
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>23-spring-boot-ehcache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.7</java.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.ve
rsion>
</properties>
<dependencies>
<!-- springBoot 的启动器 -->
<dependency><groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springBoot 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- springBoot 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 测试工具的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<!-- Spring Boot 缓存支持启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache 坐标 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId></dependency>
</dependencies>
</project>
2 创建 Ehcache 的配置文件
文件名:ehcache.xml
位置:src/main/resources/ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<!--defaultCache:echcache 的默认缓存策略 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<!-- 自定义缓存策略 -->
<cache name="users"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</cache>
</ehcache>
3 修改 application.properties 文件
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=rootspring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.cache.ehcache.cofnig=ehcache.xml
4 修改启动类
@SpringBootApplication
@EnableCaching
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
5 创建业务层
/**
* UsersService 接口实现类
*
*
*/
@Service
public class UsersServiceImpl implements UsersService {
@Autowired
private UsersRepository usersRepository;
@Override
public List<Users> findUserAll() {
return this.usersRepository.findAll();
}
@Override
//@Cacheable:对当前查询的对象做缓存处理
@Cacheable(value="users")public Users findUserById(Integer id) {
return this.usersRepository.findOne(id);
}
@Override
public Page<Users> findUserByPage(Pageable pageable) {
return this.usersRepository.findAll(pageable);
}
@Override
public void saveUsers(Users users) {
this.usersRepository.save(users);
}
}
6 修改实体类 Users
@Entity
@Table(name="t_users")
public class Users implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private Integer id;
@Column(name="name")
private String name;
@Column(name="age")
private Integer age;
@Column(name="address")
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Users [id=" + id + ", name=" + name + ", age=" + age +
", address=" + address + "]";
}
}
7 测试
/**
* UsersService 测试
*
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=App.class)
public class UsersServiceTest {
@Autowiredprivate UsersService usersService;
@Test
public void testFindUserById(){
//第一次查询
System.out.println(this.usersService.findUserById(1));
//第二次查询
System.out.println(this.usersService.findUserById(1));
}
}
二、 @Cacheable 与@CacheEvict
1 @Cacheable
@Cacheable 作用:把方法的返回值添加到 Ehcache 中做缓存
Value 属性:指定一个 Ehcache 配置文件中的缓存策略,如果么有给定 value,name 则
表示使用默认的缓存策略。
Key 属性:给存储的值起个名称。在查询时如果有名称相同的,那么则知己从缓存中将
数据返回
1.1业务层
@Override
@Cacheable(value="users",key="#pageable.pageSize")
public Page<Users> findUserByPage(Pageable pageable) {
return this.usersRepository.findAll(pageable);
}1.2测试代码
@Test
public void testFindUserByPage(){
Pageable pageable = new PageRequest(0, 2);
//第一次查询
System.out.println(this.usersService.findUserByPage(pageable).getTot
alElements());
//第二次查询
System.out.println(this.usersService.findUserByPage(pageable).getTot
alElements());
//第三次查询
pageable = new PageRequest(1, 2);
System.out.println(this.usersService.findUserByPage(pageable).getTot
alElements());
}
}
2 @CacheEvict
@CacheEvict 作用:清除缓存
2.1业务层
/**
* UsersService 接口实现类
*
*
*/
@Service
public class UsersServiceImpl implements UsersService {
@Autowired
private UsersRepository usersRepository;
@Override
@Cacheable(value="users")public List<Users> findUserAll() {
return this.usersRepository.findAll();
}
@Override
//@Cacheable:对当前查询的对象做缓存处理
@Cacheable(value="users")
public Users findUserById(Integer id) {
return this.usersRepository.findOne(id);
}
@Override
@Cacheable(value="users",key="#pageable.pageSize")
public Page<Users> findUserByPage(Pageable pageable) {
return this.usersRepository.findAll(pageable);
}
@Override
//@CacheEvict(value="users",allEntries=true) 清除缓存中以 users 缓
存策略缓存的对象
@CacheEvict(value="users",allEntries=true)
public void saveUsers(Users users) {
this.usersRepository.save(users);
}
}
2.2测试代码
@Test
public void testFindAll(){
//第一次查询
System.out.println(this.usersService.findUserAll().size());
Users users = new Users();
users.setAddress("南京");
users.setAge(43);
users.setName("朱七");
this.usersService.saveUsers(users);
//第二次查询
System.out.println(this.usersService.findUserAll().size());
}
三、 Spring Boot 整合 Spring Data Redis
Redis 版本:3.0.0
运行环境:Linux
1 安装 Redis
1.1安装 gcc
Yum install gcc-c++
1.2解压 redis.3.0.0.tar.gz 压缩包
tar -zxvf redis-3.0.0.tar.gz
1.3进入解压后的目录进行编译
cd redis-3.0.0
a e
1.4将 Redis 安装到指定目录
make PREFIX=/usr/local/redis install
1.5启动 Redis
./redis-server
2 Spring Boot 整合 Spring Data Redis
Spring Data Redis 是属于 Spring Data 下的一个模块。作用就是简化对于 redis 的操做
2.1修改 pom 文件添加 Spring Data Redis 的坐标
<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>24-spring-boot-redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.7</java.version>
<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.versi
on>
</properties>
<dependencies>
<!-- springBoot 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- thymeleaf 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Data Redis 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
</project>
2.2编写 Spring Data Redis 的配置类(重点)
/**
* 完成对 Redis 的整合的一些配置*
*
*/
@Configuration
public class RedisConfig {
/**
* 1.创建 JedisPoolConfig 对象。在该对象中完成一些链接池配置
*
*/
@Bean
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig config = new JedisPoolConfig();
//最大空闲数
config.setMaxIdle(10);
//最小空闲数
config.setMinIdle(5);
//最大链接数
config.setMaxTotal(20);
return config;
}
/**
* 2.创建 JedisConnectionFactory:配置 redis 链接信息
*/
@Bean
public JedisConnectionFactory
jedisConnectionFactory(JedisPoolConfig config){
JedisConnectionFactory factory = new JedisConnectionFactory();
//关联链接池的配置对象
factory.setPoolConfig(config);
//配置链接 Redis 的信息
//主机地址
factory.setHostName("192.168.70.128");
//端口
factory.setPort(6379);
return factory;
}
/**
* 3.创建 RedisTemplate:用于执行 Redis 操作的方法
*/@Bean
public RedisTemplate<String,Object>
redisTemplate(JedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
//关联
template.setConnectionFactory(factory);
//为 key 设置序列化器
template.setKeySerializer(new StringRedisSerializer());
//为 value 设置序列化器
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}
2.3编写测试代码,测试整合环境
2.3.1 修改 pom 文件添加测试启动器坐标
<!-- Test 的启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
2.3.2 编写测试类
/**
* Spring Data Redis 测试
*
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=App.class)
public class RedisTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 添加一个字符串
*/@Test
public void testSet(){
this.redisTemplate.opsForValue().set("key", "北京尚学堂");
}
/**
* 获取一个字符串
*/
@Test
public void testGet(){
String value =
(String)this.redisTemplate.opsForValue().get("key");
System.out.println(value);
}
}
3 提取 redis 的配置信息
3.1在 src/main/resource/ 目 录 下 新 建 一 个 配 置 文
件:application.properties
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=5
spring.redis.pool.max-total=20
spring.redis.hostName=192.168.70.128
spring.redis.port=6379
3.2修改配置类
/**
* 完成对 Redis 的整合的一些配置
*
*
*/
@Configuration
public class RedisConfig {
/**
* 1.创建 JedisPoolConfig 对象。在该对象中完成一些链接池配置
* @ConfigurationProperties:会将前缀相同的内容创建一个实体。*/
@Bean
@ConfigurationProperties(prefix="spring.redis.pool")
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig config = new JedisPoolConfig();
/*//最大空闲数
config.setMaxIdle(10);
//最小空闲数
config.setMinIdle(5);
//最大链接数
config.setMaxTotal(20);*/
System.out.println("默认值:"+config.getMaxIdle());
System.out.println("默认值:"+config.getMinIdle());
System.out.println("默认值:"+config.getMaxTotal());
return config;
}
/**
* 2.创建 JedisConnectionFactory:配置 redis 链接信息
*/
@Bean
@ConfigurationProperties(prefix="spring.redis")
public JedisConnectionFactory
jedisConnectionFactory(JedisPoolConfig config){
System.out.println("配置完毕:"+config.getMaxIdle());
System.out.println("配置完毕:"+config.getMinIdle());
System.out.println("配置完毕:"+config.getMaxTotal());
JedisConnectionFactory factory = new JedisConnectionFactory();
//关联链接池的配置对象
factory.setPoolConfig(config);
//配置链接 Redis 的信息
//主机地址
/*factory.setHostName("192.168.70.128");
//端口
factory.setPort(6379);*/
return factory;
}
/**
* 3.创建 RedisTemplate:用于执行 Redis 操作的方法
*/
@Bean
public RedisTemplate<String,Object>redisTemplate(JedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
//关联
template.setConnectionFactory(factory);
//为 key 设置序列化器
template.setKeySerializer(new StringRedisSerializer());
//为 value 设置序列化器
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}
4 Spring Data Redis 操作实体对象
4.1.1 创建实体类
public class Users implements Serializable {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}@Override
public String toString() {
return "Users [id=" + id + ", name=" + name + ", age=" + age +
"]";
}
}
4.1.2 测试代码
/**
* 添加 Users 对象
*/
@Test
public void testSetUesrs(){
Users users = new Users();
users.setAge(20);
users.setName("张三丰");
users.setId(1);
//重新设置序列化器
this.redisTemplate.setValueSerializer(new
JdkSerializationRedisSerializer());
this.redisTemplate.opsForValue().set("users", users);
}
/**
* 取 Users 对象
*/
@Test
public void testGetUsers(){
//重新设置序列化器
this.redisTemplate.setValueSerializer(new
JdkSerializationRedisSerializer());
Users users =
(Users)this.redisTemplate.opsForValue().get("users");
System.out.println(users);
}5 Spring Data Redis 以 JSON 格式存储实体对象
5.1测试代码
/**
* 基于 JSON 格式存 Users 对象
*/
@Test
public void testSetUsersUseJSON(){
Users users = new Users();
users.setAge(20);
users.setName("李四丰");
users.setId(1);
this.redisTemplate.setValueSerializer(new
Jackson2JsonRedisSerializer<>(Users.class));
this.redisTemplate.opsForValue().set("users_json", users);
}
/**
* 基于 JSON 格式取 Users 对象
*/
@Test
public void testGetUseJSON(){
this.redisTemplate.setValueSerializer(new
Jackson2JsonRedisSerializer<>(Users.class));
Users users =
(Users)this.redisTemplate.opsForValue().get("users_json");
System.out.println(users);
}
第六章节 Spring Boot 定时任务
(SpringBoot 高级)
课程内容
Scheduled 定时任务器
整合 Quartz 定时任务框架
一、 Scheduled 定时任务器
Scheduled 定时任务器:是 Spring3.0 以后自带的一个定时任务器。
1 在 pom 文件中添加 Scheduled 的坐标
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>25-spring-boot-scheduled</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>1.7</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.versi on> </properties> <dependencies> <!-- springBoot 的启动器 --> <dependency><groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- 添加 Scheduled 坐标 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> </dependencies> </project>
2 编写定时任务类
/** * Scheduled 定时任务 * * */ @Component public class ScheduledDemo { /** * 定时任务方法 * @Scheduled:设置定时任务 * cron 属性:cron 表达式。定时任务触发是时间的一个字符串表达形式 */ @Scheduled(cron="0/2 * * * * ?") public void scheduledMethod(){ System.out.println("定时器被触发"+new Date()); } }
3 在启动类中开启定时任务的使用
/** * *Scheduled* */ @SpringBootApplication @EnableScheduling public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
4 cron 表达式讲解
Cron 表达式是一个字符串,分为 6 或 7 个域,每一个域代表一个含义
Cron 有如下两种语法格式:
(1) Seconds Minutes Hours Day Month Week Year
(2)Seconds Minutes Hours Day Month Week
一、结构
corn 从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份
二、各字段的含义
位置 时间域名 允许值 允许的特殊字符
1 秒 0-59 , - * /
2 分钟 0-59 , - * /
3 小时 0-23 , - * /
4 日 1-31 , - * / L W C
5 月 1-12 , - * /
6 星期 1-7 , - * ? / L C #
7 年(可选) 1970-2099 , - * /
Cron 表达式的时间字段除允许设置数值外,还可使用一些特殊的字符,提供列表、范围、通配符等功
能,细说如下:●星号(*):可用在所有字段中,表示对应时间域的每一个时刻,例如,*在分钟字段时,表示“每分钟”;
●问号(?):该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于占位符;
●减号(-):表达一个范围,如在小时字段中使用“10-12”,则表示从 10 到 12 点,即 10,11,12;
●逗号(,):表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五;
●斜杠(/):x/y 表达一个等步长序列,x 为起始值,y 为增量步长值。如在分钟字段中使用 0/15,则
表示为 0,15,30 和 45 秒,而 5/15 在分钟字段中表示 5,20,35,50,你也可以使用*/y,它等同于 0/y;
●L:该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L 在日期
字段中,表示这个月份的最后一天,如一月的 31 号,非闰年二月的 28 号;如果 L 用在星期中,则表示星
期六,等同于 7。但是,如果 L 出现在星期字段里,而且在前面有一个数值 X,则表示“这个月的最后 X 天”,
例如,6L 表示该月的最后星期五;
●W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如 15W
表示离该月 15 号最近的工作日,如果该月 15 号是星期六,则匹配 14 号星期五;如果 15 日是星期日,
则匹配 16 号星期一;如果 15 号是星期二,那结果就是 15 号星期二。但必须注意关联的匹配日期不能够
跨月,如你指定 1W,如果 1 号是星期六,结果匹配的是 3 号星期一,而非上个月最后的那天。W 字符串
只能指定单一日期,而不能指定日期范围;
●LW 组合:在日期字段可以组合使用 LW,它的意思是当月的最后一个工作日;
●井号(#):该字符只能在星期字段中使用,表示当月某个工作日。如 6#3 表示当月的第三个星期五(6
表示星期五,#3 表示当前的第三个),而 4#5 表示当月的第五个星期三,假设当月没有第五个星期三,
忽略不触发;
● C:该字符只在日期和星期字段中使用,代表“Calendar”的意思。它的意思是计划所关联的日期,
如果日期没有被关联,则相当于日历中所有日期。例如 5C 在日期字段中就相当于日历 5 日以后的第一天。
1C 在星期字段中相当于星期日后的第一天。
Cron 表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。
例子:
@Scheduled(cron = "0 0 1 1 1 ?")//每年一月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 1,6 ?") //一月和六月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 1,4,7,10 ?") //每个季度的第一个月的一号的 1:00:00 执行一次
@Scheduled(cron = "0 0 1 1 * ?")//每月一号 1:00:00 执行一次
@Scheduled(cron="0 0 1 * * *") //每天凌晨 1 点执行一次二、
Spring Boot 整合 Quartz 定时任务框架
1 Quartz 的介绍以及 Quartz 的使用思路
1.1Quartz 的介绍
1.2Quartz 的使用思路
1)job - 任务 - 你要做什么事?
2)Trigger - 触发器 - 你什么时候去做?
3)Scheduler - 任务调度 - 你什么时候需要去做什么事?
2 Quartz 的基本使用方式
2.1创建项目
2.2修改 pom 文件添加 Quartz 的坐标
<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.bjsxt</groupId> <artifactId>26-quartz-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- Quartz 坐标 --><dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> </dependencies> </project>
2.3创建 Job 类
/** * 定义任务类 * * */ public class QuartzDemo implements Job { /** * 任务被触发时所执行的方法 */ public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("Execute...."+new Date()); } }
2.4编写测试代码
public class QuartzMain { public static void main(String[] args) throws Exception { // 1.创建 Job 对象:你要做什么事? JobDetail job = JobBuilder.newJob(QuartzDemo.class).build(); /** * 简单的 trigger 触发时间:通过 Quartz 提供一个方法来完成简单的重复 调用 cron * Trigger:按照 Cron 的表达式来给定触发的时间 */ // 2.创建 Trigger 对象:在什么时间做? /*Trigger trigger =TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSe condlyForever()) .build();*/ Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedu le("0/2 * * * * ?")) .build(); // 3.创建 Scheduler 对象:在什么时间做什么事? Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(job, trigger); //启动 scheduler.start(); } }
3 .Spring Boot 整合 Quartz 定时框架
3.1修改 pom 文件添加坐标
<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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.10.RELEASE</version> </parent> <groupId>com.bjsxt</groupId> <artifactId>27-spring-boot-quartz</artifactId> <version>0.0.1-SNAPSHOT</version> <properties><java.version>1.7</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.ve rsion> </properties> <dependencies> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springBoot 的启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- Quartz 坐标 --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <!-- 添加 Scheduled 坐标 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- Sprng tx 坐标 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> </dependencies></project>
3.2编写 Quartz 的启动类
/** * Quartz 配置类 * * */ @Configuration public class QuartzConfig { /** * 1.创建 Job 对象 */ @Bean public JobDetailFactoryBean jobDetailFactoryBean(){ JobDetailFactoryBean factory = new JobDetailFactoryBean(); //关联我们自己的 Job 类 factory.setJobClass(QuartzDemo.class); return factory; } /** * 2.创建 Trigger 对象 * 简单的 Trigger */ @Bean public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){ SimpleTriggerFactoryBean factory = new SimpleTriggerFactoryBean(); //关联 JobDetail 对象 factory.setJobDetail(jobDetailFactoryBean.getObject()); //该参数表示一个执行的毫秒数 factory.setRepeatInterval(2000); //重复次数 factory.setRepeatCount(5); return factory; }/** * 3.创建 Scheduler 对象 */ @Bean public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){ SchedulerFactoryBean factory = new SchedulerFactoryBean(); //关联 trigger factory.setTriggers(simpleTriggerFactoryBean.getObject()); return factory; } }
3.3修改启动类
/** * *spring Boot 整合 Quartz 案例 * */ @SpringBootApplication @EnableScheduling public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
4 Job 类中注入对象
4.1注入时会产生异常4.2编写一个 MyAdaptableJobFactory
4.2编写一个 MyAdaptableJobFactory 解决该问题
@Component("myAdaptableJobFactory") public class MyAdaptableJobFactory extends AdaptableJobFactory { //AutowireCapableBeanFactory 可以将一个对象添加到 SpringIOC 容器中, 并且完成该对象注入 @Autowired private AutowireCapableBeanFactory autowireCapableBeanFactory; /** * 该方法需要将实例化的任务对象手动的添加到 springIOC 容器中并且完成对 象的注入 */ @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object obj = super.createJobInstance(bundle); //将 obj 对象添加 Spring IOC 容器中,并完成注入 this.autowireCapableBeanFactory.autowireBean(obj); return obj; } }
4.3修改 QuartzConfig 类
/** * Quartz 配置类 * * */ @Configuration public class QuartzConfig { /** * 1.创建 Job 对象 */ @Bean public JobDetailFactoryBean jobDetailFactoryBean(){ JobDetailFactoryBean factory = new JobDetailFactoryBean();//关联我们自己的 Job 类 factory.setJobClass(QuartzDemo.class); return factory; } /** * 2.创建 Trigger 对象 * 简单的 Trigger */ /*@Bean public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){ SimpleTriggerFactoryBean factory = new SimpleTriggerFactoryBean(); //关联 JobDetail 对象 factory.setJobDetail(jobDetailFactoryBean.getObject()); //该参数表示一个执行的毫秒数 factory.setRepeatInterval(2000); //重复次数 factory.setRepeatCount(5); return factory; }*/ /** * Cron Trigger */ @Bean public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){ CronTriggerFactoryBean factory = new CronTriggerFactoryBean(); factory.setJobDetail(jobDetailFactoryBean.getObject()); //设置触发时间 factory.setCronExpression("0/2 * * * * ?"); return factory; } /** * 3.创建 Scheduler 对象 */ @Bean public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean,MyAdaptableJobFactory myAdaptableJobFactory){ SchedulerFactoryBean factory = new SchedulerFactoryBean();//关联 trigger factory.setTriggers(cronTriggerFactoryBean.getObject()); factory.setJobFactory(myAdaptableJobFactory); return factory; } }