Spring原理 MVC
1 WEB
1.1 RequestMappingHandlerMapping 与 RequestMappingHandlerAdapter
RequestMappingHandlerMapping 与 RequestMappingHandlerAdapter 俩是一对,分别用来
- 处理 @RequestMapping 映射
- 调用控制器方法、并处理方法参数与方法返回值
演示1 - DispatcherServlet 初始化
public class A20 {
private static final Logger log = LoggerFactory.getLogger(A20.class);
public static void main(String[] args) {
AnnotationConfigServletWebServerApplicationContext context =
new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
}
}
@Configuration
@ComponentScan //没有加包范围,默认扫描当前类所在的包,以及子包
public class WebConfig {
//内嵌web容器工厂
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(){
return new TomcatServletWebServerFactory();
}
//创建 DispatcherServlet 通过Spring容器创建,通过tomcat初始化
@Bean
public DispatcherServlet dispatcherServlet(){
return new DispatcherServlet();
}
//注册DispatcherServlet ,Spring MVC 的入口
@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet){
DispatcherServletRegistrationBean registrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/");// "/"表示所有请求
registrationBean.setLoadOnStartup(1); //大于1,Tomcat 启动后就初始化
return registrationBean;
}
}
把值写在配置文件中
@Configuration
@ComponentScan //没有加包范围,默认扫描当前类所在的包,以及子包
@PropertySource("classpath:application.properties")
//注入WebMvcProperties,ServerProperties,这两个类.这两个类都是配置文件中的属性值绑定
//WebMvcProperties: web.servlet
//ServerProperties: server
@EnableConfigurationProperties({WebMvcProperties.class, ServerProperties.class})
public class WebConfig {
//内嵌web容器工厂
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(ServerProperties serverProperties){
return new TomcatServletWebServerFactory(serverProperties.getPort());
}
//创建 DispatcherServlet 通过Spring容器创建,通过tomcat初始化
@Bean
public DispatcherServlet dispatcherServlet(){
return new DispatcherServlet();
}
//注册DispatcherServlet ,Spring MVC 的入口
@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet
,WebMvcProperties webMvcProperties){
DispatcherServletRegistrationBean registrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/");// "/"表示所有请求
//获取配置文件的值
int loadOnStartup = webMvcProperties.getServlet().getLoadOnStartup();
registrationBean.setLoadOnStartup(loadOnStartup); //大于1,Tomcat 启动后就初始化
return registrationBean;
}
}
DispatcherServlet 初始化做了什么
RequestMappingHandlerMapping 作用
如果使用默认DispatcherServlet.properties中的RequestMappingHandlerMapping,只会作为成员变量,并不会注入容器中,所以需要自己写
@Controller
public class Controller1 {
private static final Logger log = LoggerFactory.getLogger(Controller1.class);
@GetMapping("/test1")
public ModelAndView test1() throws Exception {
log.debug("test1()");
return null;
}
@PostMapping("/test2")
public ModelAndView test2(@RequestParam("name") String name) {
log.debug("test2({})", name);
return null;
}
@PutMapping("/test3")
public ModelAndView test3(@Token String token) {
log.debug("test3({})", token);
return null;
}
@RequestMapping("/test4")
// @ResponseBody
@Yml
public User test4() {
log.debug("test4");
return new User("张三", 18);
}
public static class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
public static void main(String[] args) {
String str = new Yaml().dump(new User("张三", 18));
System.out.println(str);
}
}
public class A20 {
private static final Logger log = LoggerFactory.getLogger(A20.class);
public static void main(String[] args) throws Exception {
AnnotationConfigServletWebServerApplicationContext context =
new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
//作用 解析 @RequestMappering 以及派生注解, 生成路径与控制器方法的映射关系,在初始化时就生成
RequestMappingHandlerMapping handlerMapping = context.getBean(RequestMappingHandlerMapping.class);
//获取映射信息
Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
handlerMethods.forEach((k,v)->{
System.out.println(k + "=" + v);
});
/** 打印结果: 请求方式 + 请求路径 = 哪个类控制器以及类中对应的方法信息
* {GET [/test1]}=com.feng.a20webdispatcherservlet.Controller1#test1()
* {PUT [/test3]}=com.feng.a20webdispatcherservlet.Controller1#test3(String)
* {POST [/test2]}=com.feng.a20webdispatcherservlet.Controller1#test2(String)
* { [/test4]}=com.feng.a20webdispatcherservlet.Controller1#test4()
*/
//请求来了,获取控制器的方法 Mock: 模拟请求
//返回处理器执行链对象
HandlerExecutionChain chain = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/test1"));
System.out.println(chain);
/**
* 结果:HandlerExecutionChain with [com.feng.a20webdispatcherservlet.Controller1#test1()] and 0 interceptors
* */
}
}
RequestMappingHandlerAdapter 作用
调用了Controller中的方法
查看参数解析器和返回值解析器
public class A20 {
private static final Logger log = LoggerFactory.getLogger(A20.class);
public static void main(String[] args) throws Exception {
AnnotationConfigServletWebServerApplicationContext context =
new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
//作用 解析 @RequestMappering 以及派生注解, 生成路径与控制器方法的映射关系,在初始化时就生成
RequestMappingHandlerMapping handlerMapping = context.getBean(RequestMappingHandlerMapping.class);
//获取映射信息
Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
handlerMethods.forEach((k,v)->{
System.out.println(k + "=" + v);
});
/** 打印结果: 请求方式 + 请求路径 = 哪个类控制器以及类中对应的方法信息
* {GET [/test1]}=com.feng.a20webdispatcherservlet.Controller1#test1()
* {PUT [/test3]}=com.feng.a20webdispatcherservlet.Controller1#test3(String)
* {POST [/test2]}=com.feng.a20webdispatcherservlet.Controller1#test2(String)
* { [/test4]}=com.feng.a20webdispatcherservlet.Controller1#test4()
*/
//请求来了,获取控制器的方法 Mock: 模拟请求
//返回处理器执行链对象
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test2");
request.setParameter("name", "张三");
MockHttpServletResponse response = new MockHttpServletResponse();
HandlerExecutionChain chain = handlerMapping.getHandler(request);
System.out.println(chain);
/**
* 结果:HandlerExecutionChain with [com.feng.a20webdispatcherservlet.Controller1#test1()] and 0 interceptors
* */
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>");
// HandlerAdapter作用:调用控制器的方法
MyRequestMappingHandlerAdapter handlerAdapter = context.getBean(MyRequestMappingHandlerAdapter.class);
handlerAdapter.invokeHandlerMethod(request, response, (HandlerMethod) chain.getHandler());
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>> 所有参数解析器");
for (HandlerMethodArgumentResolver resolver : handlerAdapter.getArgumentResolvers()) {
System.out.println(resolver);
}
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>> 所有返回值解析器");
for (HandlerMethodReturnValueHandler handler : handlerAdapter.getReturnValueHandlers()) {
System.out.println(handler);
}
}
}