SpringBoot高级
1.热部署
为了提高我们的开发效率,我们可以放开IDEA中的SpringBoot项目的热部署操作
1.1 放开配置
在IDEA中默认是没有放开热部署操作的,我们需要手动的放开设置
1.2 注册
Control+shift+Alt+/ 会出现一个弹出界面
然后选择Registry
1.3 添加devtools
<!--devtools 热部署的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
2. 异常处理
2.1 自定义错误页面
SpringBoot默认的处理异常的机制:一旦程序出现了异常SpringBoot会想 /error 的url发送请求,在SpringBoot中提供了一个 BasicExceptionController来处理 /error 请求,然后跳转到默认显示异常的页面来展示异常信息
如果我们需要将所有的异常统一跳转到我们自定义的错误页面,需要在src/main/resources/template 目录下创建一个 error.html页面,注意名称必须是 error.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>系统出错,请联系管理员....</h1>
<span th:text="${exception}"></span>
</body>
</html>
2.2 @ExceptionHandle注解
package com.bobo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class UserController {
@RequestMapping("/show1")
public String showInfo1(){
String name = null;
// 模拟 空指针异常
name.length();
return "index";
}
@RequestMapping("/show2")
public String showInfo2(){
int a = 1/0; // 默认算术异常
return "index";
}
@ExceptionHandler(value = {NullPointerException.class})
public ModelAndView nullPointerExceptionHandler(Exception e){
ModelAndView mm = new ModelAndView();
mm.addObject("error",e.toString());
mm.setViewName("error1");
return mm;
}
@ExceptionHandler(value = {ArithmeticException.class})
public ModelAndView arithmeticException(Exception e){
ModelAndView mm = new ModelAndView();
mm.addObject("error",e.toString());
mm.setViewName("error2");
return mm;
}
}
error1.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>系统出错,请联系管理员....nullPointerExceptionHandler</h1>
<span th:text="${error}"></span>
</body>
</html>
error2.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>系统出错,请联系管理员....arithmeticException</h1>
<span th:text="${error}"></span>
</body>
</html>
效果
2.3 @ControllerAdvice注解
上面的实现将控制器和异常处理的方法写在了一块,显然不太合理,这时我们可以通过@ControllerAdvice注解来实现解耦
专门的异常处理类
package com.bobo.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class GlobalException {
@ExceptionHandler(value = {NullPointerException.class})
public ModelAndView nullPointerExceptionHandler(Exception e){
ModelAndView mm = new ModelAndView();
mm.addObject("error",e.toString());
mm.setViewName("error1");
return mm;
}
@ExceptionHandler(value = {ArithmeticException.class})
public ModelAndView arithmeticException(Exception e){
ModelAndView mm = new ModelAndView();
mm.addObject("error",e.toString());
mm.setViewName("error2");
return mm;
}
}
控制器代码
package com.bobo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class UserController {
@RequestMapping("/show1")
public String showInfo1(){
String name = null;
// 模拟 空指针异常
name.length();
return "index";
}
@RequestMapping("/show2")
public String showInfo2(){
int a = 1/0; // 默认算术异常
return "index";
}
}
2.4 SimpleMappingExceptionResolver
我们还可以通过SimpleMappingExceptionResolver来简化我们的异常处理
package com.bobo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import java.util.Properties;
@SpringBootApplication
public class SpringbootDemo11Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemo11Application.class, args);
}
/**
* 通过SimpleMappingExceptionResolver 设置 特定异常和 处理器的映射关系
* @return
*/
@Bean
public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
properties.put("java.lang.NullPointerException","error1");
properties.put("java.lang.ArithmeticException","error2");
resolver.setExceptionMappings(properties);
return resolver;
}
}
2.5 HandleExceptionResolver处理
我们上面讲的SimpleMappingExceptionResolver本质上就是实现HandleExceptionResolver的。
所以我们也可以自己来实现HandleExceptionResolver接口
package com.bobo.exception;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyHandleExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView mm = new ModelAndView();
if(e instanceof NullPointerException){
mm.setViewName("error1");
}else if(e instanceof ArithmeticException){
mm.setViewName("error2");
}else{
mm.setViewName("error");
}
return mm;
}
}
3. 单元测试
为了提高在开发过程中的效率,我们可以通过SpringBoot中提供的单元测试来快速测试service和dao的业务逻辑
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
业务逻辑
package com.bobo.service.impl;
import com.bobo.service.IUserService;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
@Service
public class UserServiceImpl implements IUserService {
@Override
public List<String> query() {
return Arrays.asList("张三","李四","王五");
}
}
单元测试
package com.bobo;
import com.bobo.service.IUserService;
import net.bytebuddy.asm.Advice;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringbootDemo12ApplicationTests {
@Autowired
private IUserService service;
@Test
void contextLoads() {
System.out.println("---->" + service.query());
}
@BeforeEach
void before(){
System.out.println("before ...");
}
@AfterEach
void after(){
System.out.println("after ...");
}
}