栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringMvc 源码分析 (如何自定义视图 + 如何自定义异常) (十四)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringMvc 源码分析 (如何自定义视图 + 如何自定义异常) (十四)

文章目录
      • 0.前记
      • 1.自定义视图
      • 2.自定义异常
      • 3.自定义异常的原理

0.前记

在前面的文章中, 表示了视图解析的原理和异常解析器的解析原理。

这篇通过如何自定义视图和自定义异常处理和自定义异常处理的原理进行说明。

这里说明一下, 自定义的视图和自定义的异常都是会代替容器默认的组件的, 异常还好说, 就是不符合就抛, 视图的话需要注意一下优先级, 可以在自定义的视图解析器上加上@Order注解。

1.自定义视图

MeiNvView.java

public class MeiNvView implements View {
    @Override
    public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        StringBuilder sb = new StringBuilder();
        sb.append(model.get("info")).append(request.getParameter("name"));

        response.getWriter().write(sb.toString());

    }
}

MeiNvViewResolver.java

@Order
@Component
public class MeiNvViewResolver implements ViewResolver {
    @Override
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (viewName.startsWith("meinv:")){
            return new MeiNvView();
        }
        return null;
    }
}

HelloController.java

    @GetMapping("/meinv")
    public String meinv(String name, Model model){
        model.addAttribute("info", "001");
        return "meinv:" + name;
    }

这里原理就是添加一个视图和视图解析器, 然后放入容器中, 最后访问相应的路径就可以。
原理解释请看之前的文章

2.自定义异常

GgktException : 自定义异常类

@Data
@AllArgsConstructor
@NoArgsConstructor
// 自定义异常
public class GgktException extends RuntimeException {
    private Integer code;
    private String msg;
}

GlobalExceptionHandler : 全局异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {
    // 全局异常
    @ExceptionHandler(Exception.class)
//    @ResponseBody
    public Result error(Exception e){
        e.printStackTrace();
        return Result.fail().message("执行了全局异常处理");
    }

    // 特定异常
    @ExceptionHandler(ArithmeticException.class)
//    @ResponseBody
    public Result error(ArithmeticException e){
        e.printStackTrace();
        return Result.fail().message("执行了特定异常处理");
    }

    // 自定义异常
    @ExceptionHandler(GgktException.class)
//    @ResponseBody
    public Result error(GgktException e){
        e.printStackTrace();
        return Result.fail().message(e.getMsg()).code(e.getCode());
    }
}

Result: 对于上述的异常处理的返回处理

@Data
public class Result {

    private Integer code;

    private String message;

    private T data;

    public Result(){}

    public static  Result build(T body, Integer code, String message) {
        Result result = new Result();
        if (body != null) {
            result.setData(body);
        }
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    public static Result ok(){
        return Result.ok(null);
    }

    
    public static Result ok(T data){
        return build(data,20000,"成功");
    }

    public static Result fail(){
        return Result.fail(null);
    }

    
    public static Result fail(T data){
        return build(data, 20001,"失败");
    }

    public Result message(String msg){
        this.setMessage(msg);
        return this;
    }

    public Result code(Integer code){
        this.setCode(code);
        return this;
    }
}

这里通过一个自定义的异常加入到全局的异常处理中, 上面加了@ExceptionHandler的注解

3.自定义异常的原理

由上一篇可知, 异常解析器解析的过程中, 有3步, 第一步如果注解有@ExceptionHandler的话优先考虑这个方案。

在此做一个解释。

因为ExceptionHandlerExceptionResolver实现了 InitializingBean这个接口, 所以实现了afterPropertiesSet方法

  1. 首先会初始化ExceptionHandler的一些信息
  2. 加入参数解析器
  3. 加入返回值解析器

  1. 拿到所有含有@ControllerAdvice的 ControllerAdviceBean
  2. 拿到这个类上标注了@ExceptionHandler的注解的方法
  3. 挨个解析

.


找到所以含有@ControllerAdvice的类

	public ExceptionHandlerMethodResolver(Class handlerType) {
		for (Method method : MethodIntrospector.selectMethods(handlerType, EXCEPTION_HANDLER_METHODS)) {
			for (Class exceptionType : detectExceptionMappings(method)) {
				addExceptionMapping(exceptionType, method);
			}
		}
	}
	public static final MethodFilter EXCEPTION_HANDLER_METHODS = method ->
			AnnotatedElementUtils.hasAnnotation(method, ExceptionHandler.class);

这里是找到@ExceptionHandler的类, 并缓存起来

AbstractHandlerMethodExceptionResolver.doResolveException() -> ExceptionHandlerExceptionResolver.doResolveHandlerMethodException()


ExceptionHandlerExceptionResolver.doResolveHandlerMethodException()


这个方法遍历了所以的@ControllerAdvice, 看哪个类可以解析异常

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1025064.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号