spring boot项目从零开始-(6)统一处理异常

简述

前提

目录

在这里插入图片描述

步骤

关键:@ControllerAdvice + @ExceptionHandler

自定义异常类ControllerException\ServiceException

package com.ydfind.start.common.exception;

/**
 * controller异常
 * @author ydfind
 * @date 2019.1.22
 */
public class ControllerException extends RuntimeException {
    public ControllerException(String message) {
        super(message);
    }

    public ControllerException(String message, Throwable cause) {
        super(message, cause);
    }
}
package com.ydfind.start.common.exception;

/**
 * service异常
 * @author ydfind
 * @date 2019.1.22
 */
public class ServiceException extends RuntimeException {
    public ServiceException(String message) {
        super(message);
    }

    public ServiceException(String message, Throwable cause) {
        super(message, cause);
    }
}

结果类Result

package com.ydfind.start.common.response;

import lombok.Data;
import java.io.Serializable;

/**
 * 请求结果
 * @param <T> 参数data类
 * @author ydifnd
 * @date 2019.1.22
 */
@Data
public class Result<T> implements Serializable {
    public static String SUCCESS = "200";
    public static String ERROR = "500";

    private T data;
    private String code;
    private String msg;

    public Result(String code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static <T> Result<T> success(String msg, T data) {
        return new Result<>(SUCCESS, msg, data);
    }

    public static <T> Result<T> error(String msg, T data) {
        return new Result<>(ERROR, msg, data);
    }
}

拦截报错类

package com.ydfind.start.common.handler;

import com.ydfind.start.common.exception.ControllerException;
import com.ydfind.start.common.exception.ServiceException;
import com.ydfind.start.common.response.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 统一拦截报错
 * @author ydfind
 * @date 2020.1.22
 */
@Slf4j
@ControllerAdvice
public class ResultHandler {

    @ResponseBody
    @ExceptionHandler
    public Object handleException(Exception e) {
        if (!(e instanceof ServiceException) && !(e instanceof ControllerException)) {
            log.error(e.getMessage(), e);
        }
        return Result.error(e.getMessage(), null);
    }
}

测试

   @Autowired
    MyMockService myMockService;
    
    @GetMapping("/name")
    @ApiOperation("获取名称")
    @ApiImplicitParam(name = "id", value = "主键id", defaultValue = "0")
    public Result<String> getName(String id) {
        return Result.success(null, myMockService.getName(id));
    }

@GetMapping("/expression")
    public Result<String> expression() {
        if (true) {
            throw new ControllerException("expression");
        }
        return Result.success(null, "expression");
    }
    
package com.ydfind.start.controller.test;

import com.alibaba.fastjson.JSONObject;
import com.ydfind.start.BaseTest;
import com.ydfind.start.common.exception.ControllerException;
import com.ydfind.start.common.exception.ServiceException;
import com.ydfind.start.common.response.Result;
import com.ydfind.start.service.test.MyMockService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

public class ExceptionTest extends BaseTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @MockBean
    private MyMockService myMockService;

    @Before
    public void init() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void testGet() throws Exception {
        String returnString = "this is mockito name.";
        Mockito.doReturn(returnString).when(myMockService).getName(Mockito.anyString());
        String resultStr = mockMvc.perform(MockMvcRequestBuilders.get("/mock/name")
                .param("id", "user")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn().getResponse().getContentAsString();
        Result<String> result = JSONObject.parseObject(resultStr, Result.class);
        assertSuccess(result, returnString);

        String exceptionStr = "Service exception";
        Mockito.doThrow(new ServiceException(exceptionStr)).when(myMockService).getName(Mockito.anyString());
        resultStr = mockMvc.perform(MockMvcRequestBuilders.get("/mock/name")
                .param("id", "user")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn().getResponse().getContentAsString();
        result = JSONObject.parseObject(resultStr, Result.class);
        assertFail(result, exceptionStr);

        exceptionStr = "Controller exception";
        Mockito.doThrow(new ControllerException(exceptionStr)).when(myMockService).getName(Mockito.anyString());
        resultStr = mockMvc.perform(MockMvcRequestBuilders.get("/mock/name")
                .param("id", "user")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn().getResponse().getContentAsString();
        result = JSONObject.parseObject(resultStr, Result.class);
        assertFail(result, exceptionStr);

        exceptionStr = "RuntimeException";
        Mockito.doThrow(new RuntimeException(exceptionStr)).when(myMockService).getName(Mockito.anyString());
        resultStr = mockMvc.perform(MockMvcRequestBuilders.get("/mock/name")
                .param("id", "user")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn().getResponse().getContentAsString();
        result = JSONObject.parseObject(resultStr, Result.class);
        assertFail(result, exceptionStr);
    }

    @Test
    public void testExpression() throws Exception {
        String resultStr = mockMvc.perform(MockMvcRequestBuilders.get("/expression")
                .contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn().getResponse().getContentAsString();
        Result<String> result = JSONObject.parseObject(resultStr, Result.class);
        assertFail(result, "expression");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值