SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回。
DispatcherServlet是继承自HttpServlet的,既然SpringMVC是基于DispatcherServlet的,那么我们先来配置一下DispatcherServlet,好让它能够管理我们希望它管理的内容。HttpServlet是在web.xml文件中声明的。
使用 Maven 引入相关 jar 包
配置方式主要有两种:通过web.xml文件配置,或者通过代码进行配置;
使用web.xml配置
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>/WEB-INF/applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
listener-class>
listener>
<servlet>
<servlet-name>SpringMVCservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>/WEB-INF/SpringMVC-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>SpringMVCservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
spring-servlet.xml配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">http://www.springframework.org/schema/context/spring-context-3.0.xsda>">
<context:annotation-config />
<context:component-scan base-package="controller">context:component-scan>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/jsp/" p:suffix=".jsp" />
beans>
使用代码配置
创建一个 MyMvcConfig 类继承 WebMvcConfigurerAdapter
@Configuration
@EnableWebMvc// 1
@EnableScheduling
@ComponentScan("com.wisely.highlight_springmvc4")
public class MyMvcConfig extends WebMvcConfigurerAdapter {// 2
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/classes/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations(
"classpath:/assets/");// 3
}
@Bean
// 1
public DemoInterceptor demoInterceptor() {
return new DemoInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {// 2
registry.addInterceptor(demoInterceptor());
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index").setViewName("/index");
registry.addViewController("/toUpload").setViewName("/upload");
registry.addViewController("/converter").setViewName("/converter");
registry.addViewController("/sse").setViewName("/sse");
registry.addViewController("/async").setViewName("/async");
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
@Override
public void extendMessageConverters(List> converters) {
converters.add(converter());
}
@Bean
public MyMessageConverter converter(){
return new MyMessageConverter();
}
}
2.创建初始化类,实现 WebApplicationInitializer 接口
public class WebInitializer implements WebApplicationInitializer {//1
@Override
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(MyMvcConfig.class);
ctx.setServletContext(servletContext); //2
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx)); //3
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
servlet.setAsyncSupported(true);//1
}
}
1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)
4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
7. ViewResolver 结合Model和View,来渲染视图
8. 将渲染结果返回给客户端。
1. 当DispatcherServlet接到请求时,他先回查找适当的处理程序来处理请求。DispatcherServlet通过一个或者多个处理程序映射,将每个请求映射到处理程序中。处理程序映射配置在web应用程序的上下文中,是实现了HandlerMapping接口的Bean。它负责为请求返回一个适当的处理程序(也就是Controller)。处理程序映射通常根据请求的URL将请求映射到处理程序(Controller)。
2. 一旦DispatcherServlet选择了适当的控制器,它就会调用这个控制器来处理请求。
3. 控制器处理完请求后,会将模型和视图名(有时候是视图对象)返回给DispatcherServlet。模型包含了控制器要传递给视图进行显示的属性。如果返回的是视图名称,它会被解析成视图对象再进行呈现。绑定模型和视图的基本类是ModelAndView
4. 当DispatcherServlet接收到模型和视图名称时,它会将逻辑视图名称解析成视图对象再进行呈现。DispatcherServlet从一个或者多个视图解析器中解析视图。视图解析器配置在Web应用程序上下文中,是实现了ViewResolver接口的Bean。它的任务是根据逻辑视图名称返回试图对象。
5. 一旦DispatcherServlet将视图名称解析称为试图对象,它就会呈现视图对象,并传递控制器返回的模型。视图的任务是将模型属性展示给用户。
DispatcherServlet接到请求后如何映射到Controller呢?
在Spring MVC中,Web请求被Web应用程序上下文中声明的一个或者多个处理程序映射Bean(是吸纳了HandlerMapping接口的Bean)映射到Controller。Spring MVC提供了几种HandlerMapping实现:
1. BeanNameUrlHandlerMapping(默认情况),他根据Controller Bean名称中指定的URL模式将请求映射到处理程序上。
eg. …
当你访问http://**/welcome.htm这个URL时,DispatcherServlet通过BeanNameUrlHandlerMapping映射就找到了WelcomeController。
2. ControllerClassNameHandlerMapping,它是按控制器类名称映射请求。
3. SimpleUrlHandlerMapping,用定制的映射定义来映射请求。
几种常见的ViewResolver的解析:
1. InternalResourceViewResolver: 根据URL解析视图。通过添加前缀和后缀的方法,将每个视图名称都映射到一个URL上。
2. XmlViewResolver: 从XML配置文件中解析视图。将视图声明成Spring的Bean,并按他们的Bean Name进行解析。
3. ResourceBundleViewResolver: 从ResourceBundle中解析视图。
4. 用多个视图解析器解析视图, 需要注意的是,您需要为你配置的视图解析器配置解析的优先级。 value越小,优先级越高。