web全局异常捕获

问题:为什么要在数据处理层controller层做全局异常捕获?

分析:如果一个异常,在service层没有被catch到,那么,这个异常就传递到了controller层,如果controller不做处理,页面看到的就是500了。全局异常处理,针对的是这种情况:当异常不能被catch的时候,避免给用户展示500界面,在controller层做的统一处理,跳转到我们自定义的错误页面,或者返回自定义的error信息。

方案:@ControllerAdvice+@ExceptionHandler

package com.powersi.handler;

import cn.hsa.hsaf.core.framework.web.exception.AppException;
import com.alibaba.fastjson.JSON;
import com.powersi.common.exception.BaseExcCodesEnum;
import com.powersi.common.exception.BizRtException;
import com.powersi.common.utils.ResultBuilder;
import com.powersi.common.utils.ResultDto;
import com.powersi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.RpcException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName HSAFExceptionHandler
 * @Description HSAF异常处理器
 * @Author **** 
 * @Date 2021/1/12 11:09
 * @Version 1.0
 **/

@ControllerAdvice
@Slf4j
public class WebExceptionHandler {

    /**
     * 处理自定义运行时的业务异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(BizRtException.class)
    public Object exceptionHandler(BizRtException ex, HttpServletRequest request, HttpServletResponse response) {
        log.error("BizRtException:" + ex.getLocalizedMessage(), ex);
        return getObject(response, ResultBuilder.genExpResult(ex));
    }

    /**
     * 处理空指针的异常
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(value =NullPointerException.class)
    public Object exceptionHandler(NullPointerException ex, HttpServletRequest request, HttpServletResponse response) {
        log.error("NullPointerException:" + ex.getLocalizedMessage(), ex);
        return getObject(response, ResultBuilder.genExpResult(ex));
    }

    /**
     * Handle exceptions thrown by handlers.
     */
    @ExceptionHandler(AppException.class)
    public Object exceptionHandler(Exception ex, HttpServletRequest request, HttpServletResponse response) {
        log.error("exception:" + ex.getLocalizedMessage(), ex);
        return getObject(response, ResultBuilder.genExpResult(ex));
    }

    @ExceptionHandler({RpcException.class})
    public Object RpcException(Exception ex,HttpServletRequest request, HttpServletResponse response) {
        log.error("rpc接口参数校验异常。{}", ex.getMessage());
        log.error("exception:" + ex.getLocalizedMessage(), ex);
        String errMsg = ((ConstraintViolationException) ex.getCause()).getConstraintViolations()
                .iterator().next().getMessage();
        //ResponseEntity 为自定义的返回类,非springframework.http.ResponseEntity,当然此处可以自己定义返回类,只需将 异常信息 errMsg 返回即可
        return getObject(response, ResultBuilder.buildResult(BaseExcCodesEnum.PARAM_EXCEPTION.getCode(), null,errMsg));
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validExceptionHandler(MethodArgumentNotValidException e, HttpServletResponse response) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        StringBuffer stringBuffer = new StringBuffer(16);
        if (!CollectionUtils.isEmpty(fieldErrors)) {
            List<String> fieldList = new ArrayList<>();
            // 遍历所有错误信息,如果一个字段有多个校验注解,只取第一个错误信息
            fieldErrors.forEach(fieldError -> {
                if(fieldList.contains(fieldError.getField())){
                    return;
                }
                fieldList.add(fieldError.getField());
                stringBuffer.append(fieldError.getDefaultMessage()).append(",");
            });
        }
        String message = "";
        if(StringUtils.isNotEmpty(stringBuffer.toString())){
            message = stringBuffer.toString().substring(0,stringBuffer.toString().length()-1);
        }
        return getObject(response, ResultBuilder.buildResult(BaseExcCodesEnum.PARAM_EXCEPTION.getCode(), null, message));
    }

    private Object getObject(HttpServletResponse response, ResultDto resultDto) {
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setHeader("Access-control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setStatus(HttpStatus.OK.value());
        try {
            response.getWriter().write(JSON.toJSONString((resultDto)));
        } catch (IOException e) {
            log.error("异常返回出错" + e.getMessage(),e);
        }
        return new ModelAndView();
    }
}

异常都可以自己定义,基本就是错误信息+错误码


public class AppException extends RuntimeException {
    private static final long serialVersionUID = -7611643172712984323L;
    int code = -1;

    public AppException() {
    }

    public AppException(int code) {
        this.code = code;
    }

    public AppException(String message) {
        super(message);
    }

    public AppException(int code, String message) {
        super(message);
        this.code = code;
    }

    public AppException(Throwable cause) {
        super(cause);
    }

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

    public AppException(int code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    public int getCode() {
        return this.code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

这样我们service层throw或者throws抛出到controller层的异常,在controller层都不需要另外自己写代码处理了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果`doGetAuthenticationInfo`方法抛出的是一个自定义异常,并且该异常没有被捕获,那么它会沿着调用栈一直抛出,直到被JVM捕获或导致应用程序崩溃。为了避免这种情况,可以使用全局异常处理器来捕获并处理`doGetAuthenticationInfo`方法抛出的自定义异常。 在Java中,可以通过实现`javax.servlet.Filter`接口并在`web.xml`文件中配置来实现全局异常处理器。例如: ```java public class GlobalExceptionHandler implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { try { filterChain.doFilter(servletRequest, servletResponse); } catch (MyException e) { // 处理自定义异常 e.printStackTrace(); } catch (Exception e) { // 处理其他异常 e.printStackTrace(); } } // 省略其他方法 } ``` 在`doFilter`方法中,可以使用try-catch块来捕获自定义异常(例如`MyException`),并进行相应的处理。如果该异常没有被捕获,将会继续抛出,直到被全局异常处理器捕获。 然后,在`web.xml`文件中配置全局异常处理器: ```xml <filter> <filter-name>GlobalExceptionHandler</filter-name> <filter-class>com.example.GlobalExceptionHandler</filter-class> </filter> <filter-mapping> <filter-name>GlobalExceptionHandler</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ``` 上述配置将会拦截所有的请求,并使用`GlobalExceptionHandler`来处理异常。这样,当`doGetAuthenticationInfo`方法抛出自定义异常时,就能够被全局异常处理器捕获并处理,而不会导致应用程序崩溃。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值