本篇文章将带你真正的搞定SpringMVC工作原理

环境:Spring5.3.23

1. 简介

在Spring中要定义一个接口是非常的简单,如下示例:

@RestController
@RequestMapping("/demos")
public class DemoController {
  @GetMapping("/index")
  public Object index() {
    return "index" ;
  }
}

通过上面的@RestController, @RequestMapping就完成了一个简单的接口定义。

实际Spring Web底层是做了很多的工作,其核心组件有HandlerMapping, HandlerAdapter, ViewResolver等组件。

  • HandlerMapping根据当前请求的URI,查找对应的Handler,如:HandlerExecutionChain,包装的HandlerMethod
  • HandlerAdapter根据上面的确定的HandlerMethod, 找到能够处理该Handler的Adapter,进行调用
  • ViewResolver如果返回的ModelAndView对象那么会通过相应的ViewResolver进行渲染输出

了解了上面的几个核心组件之后,接下来就是自定义实现上面的核心类,来完成接口的请求处理。

2. 实战案例

2.1 自定义Endpoint

自定义@PackEndpoint注解,该注解的功能就类似@Controller标记这个类是一个处理器类。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PackEndpoint {}

参数注解,该注解的作用就类似@RequestParam

@Target(ElementType.PARAMETER)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 public @interface PackParam {
 }

2.2 参数封装对象

该类的作用用来保存方法的参数相关的信息进行封装,如:参数名称,参数的类型及对应的方法Method。

public class PackMethodParameter {
// 用来解析接口参数的名称
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer() ;
private String name ;
private Executable executable ;
private int parameterIndex ;
private Class type ;

public PackMethodParameter(String name, int parameterIndex, Executable executable) {
this.name = name;
this.parameterIndex = parameterIndex ;
this.executable = executable ;
}

public PackMethodParameter(int parameterIndex, Executable executable, Class type) {
this.parameterIndex = parameterIndex ;
this.executable = executable ;
this.type = type ;
}

public boolean hasParameterAnnotation(Class