SpringBoot高级使用

Java
428
0
0
2022-12-20
标签   SpringBoot

SpringBoot高级

1.热部署

为了提高我们的开发效率,我们可以放开IDEA中的SpringBoot项目的热部署操作

1.1 放开配置

在IDEA中默认是没有放开热部署操作的,我们需要手动的放开设置

img

1.2 注册

Control+shift+Alt+/ 会出现一个弹出界面

img

然后选择Registry

img

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 请求,然后跳转到默认显示异常的页面来展示异常信息

img

如果我们需要将所有的异常统一跳转到我们自定义的错误页面,需要在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>

img

img

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>

效果

img

img

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";
    }
}

img

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的。

img

所以我们也可以自己来实现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 ...");
    }
​
}
​

img