从零搭建自己的SpringBoot后台框架(五)

释放双眼,带上耳机,听听看~!

Hello大家好,本章我们添加全局异常处理。有问题可以联系我mr_beany@163.com。另求各路大神指点,感谢

一:为什么需要定义全局异常

在互联网时代,我们所开发的应用大多是直面用户的,程序中的任何一点小疏忽都可能导致用户的流失,而程序出现异常往往又是不可避免的,所以我们需要对异常进行捕获,然后给予相应的处理,来减少程序异常对用户体验的影响

二:添加业务类异常

在前面说过的ret文件夹下创建ServiceException


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1package com.example.demo.core.ret;
2
3import java.io.Serializable;
4
5/**
6 * @Description: 业务类异常
7 * @author 张瑶
8 * @date 2018/4/20 14:30
9 *
10 */
11public class ServiceException extends RuntimeException implements Serializable{
12
13   private static final long serialVersionUID = 1213855733833039552L;
14
15   public ServiceException() {
16   }
17
18   public ServiceException(String message) {
19      super(message);
20   }
21
22   public ServiceException(String message, Throwable cause) {
23      super(message, cause);
24   }
25}复制代码
26

三:添加异常处理配置

打开上篇文章创建的WebConfigurer,添加如下方法


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
1@Override
2public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
3    exceptionResolvers.add(getHandlerExceptionResolver());
4}
5
6/**
7 * 创建异常处理
8 * @return
9 */
10private HandlerExceptionResolver getHandlerExceptionResolver(){
11    HandlerExceptionResolver handlerExceptionResolver = new HandlerExceptionResolver(){
12        @Override
13        public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
14                                             Object handler, Exception e) {
15            RetResult<Object> result = getResuleByHeandleException(request, handler, e);
16            responseResult(response, result);
17            return new ModelAndView();
18        }
19    };
20    return handlerExceptionResolver;
21}
22
23/**
24 * 根据异常类型确定返回数据
25 * @param request
26 * @param handler
27 * @param e
28 * @return
29 */
30private RetResult<Object> getResuleByHeandleException(HttpServletRequest request, Object handler, Exception e){
31    RetResult<Object> result = new RetResult<>();
32    if (e instanceof ServiceException) {
33        result.setCode(RetCode.FAIL).setMsg(e.getMessage()).setData(null);
34        return result;
35    }
36    if (e instanceof NoHandlerFoundException) {
37        result.setCode(RetCode.NOT_FOUND).setMsg("接口 [" + request.getRequestURI() + "] 不存在");
38        return result;
39    }
40    result.setCode(RetCode.INTERNAL_SERVER_ERROR).setMsg("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
41    String message;
42    if (handler instanceof HandlerMethod) {
43        HandlerMethod handlerMethod = (HandlerMethod) handler;
44        message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s", request.getRequestURI(),
45                handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod() .getName(), e.getMessage());
46    } else {
47        message = e.getMessage();
48    }
49    LOGGER.error(message, e);
50    return result;
51}
52
53/**
54 * @Title: responseResult
55 * @Description: 响应结果
56 * @param response
57 * @param result
58 * @Reutrn void
59 */
60private void responseResult(HttpServletResponse response, RetResult<Object> result) {
61    response.setCharacterEncoding("UTF-8");
62    response.setHeader("Content-type", "application/json;charset=UTF-8");
63    response.setStatus(200);
64    try {
65        response.getWriter().write(JSON.toJSONString(result,SerializerFeature.WriteMapNullValue));
66    } catch (IOException ex) {
67        LOGGER.error(ex.getMessage());
68    }
69}复制代码
70

四:添加配置文件

**Spring Boot 中, 当用户访问了一个不存在的链接时, Spring 默认会将页面重定向到 **/error** 上, 而不会抛出异常. **

既然如此, 那我们就告诉 Spring Boot, 当出现 404 错误时, 抛出一个异常即可. 

在 application.properties 中添加两个配置: 

spring.mvc.throw-exception-if-no-handler-found=true 

spring.resources.add-mappings=false 

上面的配置中, 第一个 spring.mvc.throw-exception-if-no-handler-found 告诉 SpringBoot 当出现 404 错误时, 直接抛出异常. 第二个 spring.resources.add-mappings 告诉 SpringBoot 不要为我们工程中的资源文件建立映射.

五:创建测试接口


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1package com.example.demo.service.impl;
2
3import com.example.demo.core.ret.ServiceException;
4import com.example.demo.dao.UserInfoMapper;
5import com.example.demo.model.UserInfo;
6import com.example.demo.service.UserInfoService;
7import org.springframework.stereotype.Service;
8
9import javax.annotation.Resource;
10import java.util.List;
11
12/**
13 * @author 张瑶
14 * @Description:
15 * @time 2018/4/18 11:56
16 */
17@Service
18public class UserInfoServiceImpl implements UserInfoService{
19
20    @Resource
21    private UserInfoMapper userInfoMapper;
22
23    @Override
24    public UserInfo selectById(Integer id){
25        UserInfo userInfo = userInfoMapper.selectById(id);
26        if(userInfo == null){
27            throw new ServiceException("暂无该用户");
28        }
29        return userInfo;
30    }
31}复制代码
32

UserInfoController.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
1package com.example.demo.controller;
2
3import com.example.demo.core.ret.RetResponse;
4import com.example.demo.core.ret.RetResult;
5import com.example.demo.core.ret.ServiceException;
6import com.example.demo.model.UserInfo;
7import com.example.demo.service.UserInfoService;
8import org.springframework.web.bind.annotation.PostMapping;
9import org.springframework.web.bind.annotation.RequestMapping;
10import org.springframework.web.bind.annotation.RestController;
11
12import javax.annotation.Resource;
13import java.util.List;
14
15/**
16 * @author 张瑶
17 * @Description:
18 * @time 2018/4/18 11:39
19 */
20@RestController
21@RequestMapping("userInfo")
22public class UserInfoController {
23
24    @Resource
25    private UserInfoService userInfoService;
26
27    @PostMapping("/hello")
28    public String hello(){
29        return "hello SpringBoot";
30    }
31
32    @PostMapping("/selectById")
33    public RetResult<UserInfo> selectById(Integer id){
34        UserInfo userInfo = userInfoService.selectById(id);
35        return RetResponse.makeOKRsp(userInfo);
36    }
37
38    @PostMapping("/testException")
39    public RetResult<UserInfo> testException(Integer id){
40        List a = null;
41        a.size();
42        UserInfo userInfo = userInfoService.selectById(id);
43        return RetResponse.makeOKRsp(userInfo);
44    }
45
46
47}复制代码
48

六:接口测试

访问192.168.1.104:8080/userInfo/selectById参数 id:3


1
2
3
4
5
6
1{
2    "code": 400,
3    "data": null,
4    "msg": "暂无该用户"
5}复制代码
6

访问192.168.1.104:8080/userInfo/testException


1
2
3
4
5
6
1{
2    "code": 500,
3    "data": null,
4    "msg": "接口 [/userInfo/testException] 内部错误,请联系管理员"
5}复制代码
6

项目地址

码云地址: gitee.com/beany/mySpr…

GitHub地址: github.com/MyBeany/myS…

写文章不易,如对您有帮助,请帮忙点下star

结尾

springboot添加全局异常处理已完成,后续功能接下来陆续更新,有问题可以联系我mr_beany@163.com。另求各路大神指点,感谢大家。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ explicit关键字

2022-1-11 12:36:11

安全经验

开源组件有风险 Veracode 发布 2017 年软件安全报告

2017-10-25 11:12:22

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索