1.Demo
(1)pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mxj</groupId> <artifactId>08-spring-boot-view-jsp</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.21.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</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>tomact-embed-jasper</artifactId> <scope>provided</scope> </dependency> </dependencies> </project>
(2)配置Controller
@Controller public class Helloworld { @RequestMapping("/hello") @ResponseBody public Map<String,Object> showHelloWorld(){ Map<String,Object> map = new HashMap<>(); map.put("msg","HelloWorld"); return map; } }
(3)编写启动器
注意:启动器存放的位置可以和Controller位于同一个包下,或者位于Controller的上一级包中,但是不能放在Controller的平级以及子包下
/** * SpringBoot 启动类 */ @SpringBootApplication public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
2.SpringBoot整合Servlet
(1)通过注解扫描完成Servlet组件的注册
编写Servlet
@WebServlet(name="FirstServlet",urlPatterns="/first") public class FirstServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } }
编写启动类
@SpringBootApplication @ServletComponentScan //在springBoot启动时会扫描@WebServlet,并将该类实例化 public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
(2)通过方法完成Servlet组件的注册
编写Servlet
public class SecondServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("SecondServlet.............."); } }
编写启动类
@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; } }
3. SpringBoot整合Filter
(1)通过注解扫描完成Filter组件的注册
编写Filter
//@WebFilter(filterName = "FirstFilter",urlPatterns = {"*.do","*.jsp"}) @WebFilter(filterName="FirstFilter",urlPatterns={"/first"}) public class FirstFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("进入Filter"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("离开Filter"); } @Override public void destroy() { } }
编写启动类
@SpringBootApplication @ServletComponentScan public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
(2)通过方法完成Filter组件的注册
编写Filter
public class SecondFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("进入SecondFilter"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("离开SecondFilter"); } @Override public void destroy() { } }
编写启动类
@SpringBootApplication public class App2 { public static void main(String[] args){ SpringApplication.run(App2.class,args); } /** * 注册Servlet */ @Bean public ServletRegistrationBean getervletRegistrationBean(){ 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; } }
4.SpringBoot整合Listener
(1)通过注解扫描完成Listener组件注册
编写Listener
@WebListener public class FirstListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { } public void contextDestroyed(ServletContextEvent sce) { System.out.println("Listener......init......"); } }
编写启动类
@SpringBootApplication @ServletComponentScan public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
(2)通过方法完成Listener组件注册
编写Listener
public class SecondListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { } public void contextDestroyed(ServletContextEvent sce) { System.out.println("SecondListener......init......"); } }
编写启动类
@SpringBootApplication public class App2 { public static void main(String[] args){ SpringApplication.run(App2.class,args); } /** * 注册listener */ public ServletListenerRegistrationBean<SecondListener> getServletListenerRegistrationBean(){ ServletListenerRegistrationBean<SecondListener> bean= new ServletListenerRegistrationBean<SecondListener>(new SecondListener()); return bean; } }
5.SpringBoot访问静态资源
(1)classpath/static目录
(2)ServletContext根目录(src/main/webapp)
6.SpringBoot文件上传
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>文件上传</title> </head> <body> <from action="fileUploadController" method="post" enctype="multipart/form-data"> 上传文件:<input type="file" name="filename"/><br/> <input type="submit" value="提交"/> </from> </body> </html>
编写Controller
@RestController //表示该类下的方法的返回值会自动做json格式的转换 public class FileUploadcontroller { /** * 处理文件上传 */ @RequestMapping("/fileUploadController") public Map<String,Object> fileUpload(MultipartFile filename) throws IOException { System.out.println(filename.getOriginalFilename()); filename.transferTo(new File("d:/"+filename.getOriginalFilename())); Map<String,Object> map = new HashMap<>(); map.put("msg","ok"); return map; } }
编写启动类
@SpringBootApplication public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
设置上传文件的默认值,main/resources/application.properties
spring.http.multipart.max-file-size=200MB //设置单个上传文件的大小
spring.http.multipart.max-request-size=200MB //设置一次请求上传文件的总容量
7.SpringBoot整合jsp技术
(1)创建工程
(2)修改pom.xml坐标
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mxj</groupId> <artifactId>08-spring-boot-view-jsp</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.21.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--springBoot启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--jstl--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!--jasper--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomact-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
@Controller public class UserController { /** * 处理请求,产生数据 */ @RequestMapping("/showUser") public ModelAndView 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)); System.out.println("UserController启动"); //Model对象 model.addAttribute("list",list); ModelAndView mav = new ModelAndView("/WEB-INF/jsp/userList.jsp"); //跳转视图 return mav; } }
(5)创建jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <title>Title</title> </head> <body> <table border="1" align="center" width="50%"> <tr> <th>Id</th> <th>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)创建启动类
@SpringBootApplication public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
8.SpringBoot整合Freemarker
(1)创建项目
(2)修改pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mxj</groupId> <artifactId>08-spring-boot-view-freemarker</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--freemarker启动器坐标--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> </dependencies> </project>
(3)编写视图
注意:SpringBoot要求模板形式的视图层文件必须放到src/main/resources/templates文件夹下
<html> <head> <title>展示用户</title> <meta charset="utf-8"></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
@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)创建启动器
@SpringBootApplication public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
9.SpringBoot整合Thymeleaf
- 创建Thymeleaf入门项目
(1)创建项目
(2)修改pom文件添加坐标
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mxj</groupId> <artifactId>spring-boot-view-thymeleaf</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</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>
(3)创建存放视图的目录:Src/main/resources/templates
templates:该目录是安全的,意味着该目录下的内容是不允许外界直接访问的
(4)创建Controller
@Controller
public class DemoController { @RequestMapping("/show") public String showInfo(Model model){ model.addAttribute("msg","Thymeleaf第一个案例"); return "index"; } }
(5)创建视图
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>Title</title> </head> <body> <span th:text="Hello"></span> <hr/> <span th:text="${msg}"></span> </body> </html>
(6)编写启动器
@SpringBootApplication public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
- Thymeleaf特点
Thymeleaf是通过特定语法对html的标记做渲染
- Thymeleaf语法
(1)变量输出与字符串操作
th:text 在页面中输出值
th:value 可以将一个值放入到input标签的value中
${#strings.isEmpty(key)} 判断字符串是否为空
${#strings.contains(msg,'T')} 判断字符串是否包含指定的子串
${#strings.startsWith(msg,'a')} 判断当前字符串是否以子串开头
${#strings.endsWith(msg,'a')} 判断当前字符串是否以子串结尾
${#strings.length(msg)} 返回字符串的长度
${#strings.indexOf(msg,'h')} 查找子串的位置,并返回该子串的下标,没找到返回-1
$(#strings.substring(msg,start,end)) 截取子串,用法与jdk下String相同
${#strings.toUpperCase(msg)} 字符串转大写
${#strings.toLowerCase(msg)} 字符串转小写
(2)日期格式化处理
${#dates.format(key)} 格式化日期,默认以浏览器默认语言为格式化标准
${#dates.format(key,'yyyy/MM/dd')} 按照自定义格式做日期转换
${#dates.year(key)} 获取年
${#dates.month(key)} 获取月
${#dates.day(key)} 获取日
(3)条件判断
th:if if判断,th:if"${sex} == '男' "
th:switch th:case switch判断
(4)迭代遍历
th:each迭代list
<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> 当前迭代对象的索引,从0开始 <td th:text="${var.count}"></td> 当前迭代对象的计数器,从1开始 <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>
th:each迭代map
<tr th:each="maps : ${map}"> <td th:each="entry:${maps}" th:text="${entry.key}"></td> <td th:each="entry:${maps}" th:text="${entry.value}"></td> <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>
(5)域对象操作
@RequestMapping("/show")
public String showInfo(HttpServletRequest request,Model model){
request.setAttribute("req","HttpServletRequest");
request.getSession().setAttribute("sess","HttpSession);
request.getSession().getServletContext.setAttribute("app","Application");
return "index"'
}
<body> Request:<span th:text="${#httpServletRequest.getAttribute('req')}"></span> Session:<span th:text="session.sess"></span> Application:<span th:text="${application.app}"></span> </body>
(6)URL表达式
url基本语法:@{}
url类型:
<body> <a th:href="@{http://www.baidu.com}">绝对路径</a><br/> </body>
相对于项目的上下文的相对路径
<body> <a th:href="@{/show}">相对路径</a> </body>
相对于服务器路径的根
<body> <a th:href="@{~/project/resourcename}">相对路径</a> </body>
url实现参数传递
<body> <a th:href="@{/show(id=1,name=张三)}">相对路径-传参</a> </body>
在url中通过restful风格进行参数传递
<body> <a th:href="@{/path/{id}/show(id=1,name=张三)}">相对路径-传参-restful</a> </body>
10.SpringBoot整合SpringMVC+Mybatis
(1)创建项目
(2)修改pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mxj</groupId> <artifactId>spring-boot-springmvc-mybatis</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.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> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency> </dependencies> </project>
(3)添加application.properties全局配置文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
mybatis.type-aliases-package=com.mxj.pojo
(4)数据库表设计
CREATE TABLE `users` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `age` int(10) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
(5)创建实体类:Users
(6)创建mapper接口以及映射配置文件
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.mxj.mapper.UsersMapper"> <insert id="insertUser" parameterType="users"> insert into users(name,age) values(#{name},#{age}) </insert> </mapper>
(7)创建业务层
@Service @Transactional public class UsersServiceImpl implements UsersService { @Autowired private UsersMapper usersMapper; @Override public void addUser(Users users) { this.usersMapper.insertUser(users); } }
(8)创建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"; } }
(9)编写页面
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <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" name="提交"/><br/> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>操作提示页面</title> </head> <body> 操作成功!!! </body> </html>
(10)编写启动类
@SpringBootApplication @MapperScan("com.mxj.mapper") //用于扫描MyBatis的Mapper接口 public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
11.SpringBoot对表单做数据校验
- SpringBoot对表单数据校验的技术特点
SpringBoot中使用了Hiberbate-validate校验框架
- SpringBoot表单数据校验步骤
(1)在实体类中添加校验规则
public class Users { @NotBlank //非空校验 private Integer age; private String name; @NotBlank //密码非空校验 private String password; }
(2)在Controller中开启校验
/** * 完成用户添加 * @Valid 开启对Users对象的数据校验 * BindingResult:封装了校验的结果 */ @RequestMapping("/save") public String saveUser(@Valid Users users, BindingResult result){ if(result.hasErrors()){ return "add"; } return "ok"; }
(3)在页面中获取提示信息
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>添加用户</title> </head> <body> <from th:action="@{/save}" method="post"> 用户姓名:<input type="text" name="name" /><font color="red" th:errors="user.name">姓名不能为空</font><br/> 用户密码:<input type="password" name="password" /><font color="red" th:errors="user.password">密码不能为空</font><br/> 用户年龄:<input type="text" name="age" /><font color="red" th:errors="user.age">年龄不能为空</font><br/> <input type="submit" value="OK"/> </from> </body> </html>
- 其他校验规则
@NotBlank:判断字符串是否为null或者是空串
@NotEmpty:判断字符串是否为null或者是空串
@Length:判断字符串的长度(最大或最小)
@Min:判断数值最小值
@Max:判断数值最大值
@Email:判断邮箱是否合法
12.SprintBoot中异常处理
- SpringBoot中对于异常处理提供了五种处理方式
(1)自定义错误页面
(2)通过@ExceptionHandle注解处理异常
/** * 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; }
(3)通过@ControllerAdvice+@ExceptionHandle注解处理异常
需要创建一个能够处理异常的全局异常类,在该类上添加@ControllerAdvice注解,类中内容和(2)中相同
(4)配置SimpleMappingExceptionResolver处理异常
相比于(3)只能跳转页面,不能传递异常信息
/** * 全局异常处理类 */ @Configuration public class GlobalException { /** * 该方法必须要有返回值,返回值类型必须是:SimpleMappingExceptionResolver */ @Bean public SimpleMappingExceptionResolver getSimpleMappingExceptioinResolver(){ 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; } }
(5)自定义HandlerExceptionResolver类处理异常
/** * 实现HandlerExceptionResolver接口做异常处理 */ @Configuration public class GlobalException2 implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { ModelAndView mv = new ModelAndView(); //判断不同异常类型,做不同视图跳转 if(e instanceof ArithmeticException){ mv.setViewName("error1"); } if(e instanceof NullPointerException){ mv.setViewName("error2"); } mv.addObject("error",e.toString()); return mv; } }
13.SpringBoot整合Junit
/** * SpringBoot测试类 * @RunWith:启动器 * SpringJUnit4ClassRunner.class 让junit与spring环境进行整合 * @SpringBootTest(classes={SpringBootTestApplication}) * 当前类为SpringBoot测试类,加载启动类,启动SpringBoot */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes={SpringBootTestApplication.class}) public class UserServiceTest { @Autowired private UserServiceImpl userServiceImpl; @Test public void testAddUser(){ this.userServiceImpl.addUser(); } }
14.SpringBoot的热部署
- SpringLoader插件
方式一:maven插件方式使用SpringLoader
(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>
(2)使用maven命令启动:spring-boot:run
(3)SpringLoader缺陷
只能对java代码做部署处理,但是对页面不行
这种方式是在系统后台以进程方式运行,需要手动关闭java.exe
方式二:在项目中直接使用jar包
(1)添加SpringLoader的jar包到lib目录下
(2)启动命令:-javaagent:.\lib\springloaded-1.2.5.RELEASE.jar -noverify
- DevTools工具
SpringLoader与DevTools的区别
SpringLoader在部署项目时使用热部署
DevTools在部署项目时使用重新部署的方式
(1)修改pom文件添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
(2)可以对java代码和页面做部署处理
15.Spring Boot缓存技术
- Spring Boot整合Ehcache
(1)修改pom文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> </dependency>
(2)创建Ehcache配置文件
文件名:chcache.xml
位置:src/main/resources
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </defaultCache> </ehcache>
(3)修改application.properties文件
spring.cache.ehcache.config=ehcache.xml
(4)修改启动类
@SpringBootApplication @EnableCaching public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
(5)创建业务层
@Service public class UsersServiceImpl implements UsersService { @Autowired private UsersRepository usersRepository; @Override public List<Users> findUserAll() { return null; } @Override @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)修改实体类,实现 Serializable接口
- @Cacheable与@CacheEvict
(1)@Cacheable
作用:把方法的返回值添加到Ehcache中做缓存
value属性:指定一个Ehcach配饰文件中的缓存策略,如果没有指定使用默认
key属性:给存储的值添加唯一标记,查询时如果有key相同的直接从缓存中返回
(2)@CacheEvict
作用:清除缓存
ex:@CacheEvict(value="users",allEntries=true)清除缓存中以users缓存策略缓存的对象
- Spring Boot整合Spring Data Redis
16.Spring Boot整合Spring Data JPA
- Demo
(1)创建项目
(2)修改pom文件添加坐标
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency>
(3)在项目中添加application.properties文件
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=UTF-8&useUnicode=true&useSSL=true&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 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; }
(5)编写Dao接口
/** * 参数一 T:当前需要映射的实体 * 参数二 ID:当前映射的实体中的OID的类型 */ public interface UsersRepository extends JpaRepository<Users,Integer> { }
(6)创建启动类
@SpringBootApplication public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
(7)编写测试代码
/** * 测试类 */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = App.class) public class UsersRepositoryTest { @Autowired private UsersRepository usersRepository; @Test public void testSave(){ Users users = new Users(); users.setAddress("Beijing"); users.setAge(20); users.setName("zhangsan"); this.usersRepository.save(users); } }
- Spring Data JPA提供的核心接口
(1)Repository接口
提供了方法名称命名查询方式
提供了基于@Query注解查询与更新
编写接口
/** * Repository接口的方法名称命名查询 */ public interface UsersRepositoryByName extends Repository<Users,Integer> { //方法的名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写) public List<Users> findByName(String name); List<Users> findByNameAndAge(String name,Integer age); List<Users> findByNameLike(String name); }
测试代码
/** * 测试类 */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = App.class) public class UsersRepositoryTest { @Autowired private UsersRepositoryByName usersRepositoryByName; /** * Repository--方法名称命名测试 */ @Test public void testFindName(){ List<Users> list = this.usersRepositoryByName.findByName("zhangsan"); for(Users users : list){ System.out.println(users); } } /** * Repository--方法名称命名测试 */ @Test public void testFindNameAndAge(){ List<Users> list = this.usersRepositoryByName.findByNameAndAge("zhangsan",21); for(Users users : list){ System.out.println(users); } } /** * Repository--方法名称命名测试 */ @Test public void testFindNameLike(){ List<Users> list = this.usersRepositoryByName.findByNameLike("zhang"); for(Users users : list){ System.out.println(users); } } }
@Query注解方式编写接口
/** * 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); }
测试代码
/** * 测试类 */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = App.class) public class UsersRepositoryTest { @Autowired private UsersRepositoryQueryAnnotation usersRepositoryQueryAnnotation; /** * Repository--@Query测试 */ @Test public void testUsersRepositoryQueryAnnotation(){ List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseHQL("zhangsan"); for(Users users : list){ System.out.println(users); } } /** * Repository--@Query测试 */ @Test public void testQueryByNameUseSQL(){ List<Users> list = this.usersRepositoryQueryAnnotation.queryByNameUseSQL("zhangsan"); for(Users users : list){ System.out.println(users); } } /** * Repository--@Query测试 */ @Test @Transactional //这两个注解一起使用时事务自动回滚 @Rollback //取消自动回滚 public void testUpdateUsersNameById(){ this.usersRepositoryQueryAnnotation.updateUsersNameById("zhangsan",1); } }
(2)CrudRepository接口
CrudRepository接口,主要是完成增删改查的操作,继承了Repository接口
(3)PagingAndSortingRepository接口
排序&&分页
(4)JpaRepository接口*
继承PagingAndSortingRepository接口,对继承的父接口中的方法的返回值进行适配
(5)JPASpecificationExecutor接口
该接口主要是提供了多条件查询的支持,并且可以在查询中添加分页与排序
注意:单独存在,需配合其他接口使用
17.SpringBoot定时任务
- Scheduled定时任务器
Spring3.0以后自带的一个定时任务器
(1)在pom文件中添加Scheduled的坐标
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-context-support</artifactId> </dependency>
(2)编写定时任务类
/** * Scheduled定时任务器 */ @Component public class ScheduledDemo { /** * 定时任务方法 * @Scheduled:设置定时任务 * cron属性:cron表达式,定时任务触发时间的字符串表达形式 */ @Scheduled(cron = "0/2 * * * * ?") public void scheduledMethod(){ System.out.println("定时器被触发 "+new Date()); } }
(3)在启动类中开启定时任务的使用
/** * Scheduled */ @SpringBootConfiguration @EnableScheduling public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
- cron表达式
(1)语法格式
Seconds Minutes Hours Day Month Week Year
Seconds Minutes Hours Day Month Week
(2)各字符含义
位置 | 时间域名 | 允许值 | 允许的特殊字符 |
1 | 秒 | 0-59 | , - * / |
2 | 分钟 | 0-59 | , - * / |
3 | 小时 | 0-23 | , - * / |
4 | 日 | 1-31 | , - * / L W C |
5 | 月 | 1-12 | , - * / |
6 | 星期 | 1-7 | , - * ? / L W C |
7 | 年(可选) | 1970-2099 | , - * / |
*:可用在所有字符中,表示对应时间域的每一个时刻
?:该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于占位符
-:表式一个范围
,:表式一个列表值
/:x/y表示一个等步长序列,x为起始值,y为等量步长值
L:该字符只在日期和星期字段中使用,代表“Last”的意思
W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日
LW:在日期字段可以组合使用,意思是当月最后一个工作日
#:只能在日期字段中使用,表示当月某个工作日
C:该字符只能在日期和星期字段中使用,代表“Calendar”,表示计划所关联的日期;如果日期没有被关联,则相当于日历中所有日期。
- 整合Quartz定时任务框架
(1)Quartz的介绍以及Quartz的使用思路
Job - 任务
Trigger - 触发器
Scheduler - 任务调度
(2)Quartz基本使用
pom文件
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency>
创建任务类
/** * 定义任务类 */ public class QuartzDemo implements Job { /** * 任务被触发时所执行的方法 * @param jobExecutionContext * @throws JobExecutionException */ public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("Execute..."+new Date()); } }
编写测试代码
public class QuartzMain { public static void main(String[] args) throws SchedulerException { //创建job对象 做什么 JobDetail job = JobBuilder.newJob(QuartzDemo.class).build(); /** * 简单的trigger触发时间,通过Quartz提供一个方法来完成简单的重复调用 * cron Trigger:按照Cron的表达式来给定触发时间 */ //创建Trigger对象 什么时间做 //Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever()).build(); Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")).build(); //创建Scheduler对象 在什么时间做什么事 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(job,trigger); //启动 scheduler.start(); } }
(3)Spring Boot整合Quartz定时框架
修改pom文件
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> <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>
编写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; } /** * 2.创建Trigger对象 * Cron Trigger */ @Bean public CronTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){ CronTriggerFactoryBean factory = new CronTriggerFactoryBean(); //关联JobDetail对象 factory.setJobDetail(jobDetailFactoryBean.getObject()); //设置触发时间 factory.setCronExpression("0/2 * * * * ?"); return factory; } /** * 3.创建Scheduler对象 */ @Bean public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){ SchedulerFactoryBean factory = new SchedulerFactoryBean(); //关联trigger factory.setTriggers(simpleTriggerFactoryBean.getObject()); return factory; } }
启动类
/** * spring Boot整合Quartz */ @SpringBootApplication @EnableScheduling public class App { public static void main(String[] args){ SpringApplication.run(App.class,args); } }
(4)Job类中注入对象
注入时会产生异常,编写MyAdaptableJobFactory类解决该异常
/** * 该方法需要实例化任务对象手动的添加springIOC容器中并且完成对象的注入 */ @Component("MyAdaptableJobFactory") public class MyAdaptableJobFactory extends AdaptableJobFactory { /** * AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成对象注入 */ @Autowired private AutowireCapableBeanFactory autowireCapableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Object obj = super.createJobInstance(bundle); //将obj对象添加到Spring IOC容器中,并完成注入 this.autowireCapableBeanFactory.autowireBean(obj); return obj; } }
修改QuartzConfig类
/** * 3.创建Scheduler对象 */ @Bean public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean,MyAdaptableJobFactory myAdaptableJobFactory){ SchedulerFactoryBean factory = new SchedulerFactoryBean(); //关联trigger factory.setTriggers(cronTriggerFactoryBean.getObject()); factory.setJobFactory(myAdaptableJobFactory); return factory; }