Spring-MVC
SpringMVC
springmvc和spring framework一起发布,并且springmvc是基于servlet的原始web框架,最早springmvc是叫做springwebmvc源自于代码模块spring-webmvc。
核心
DispatcherServlet(前端控制器):为Request请求提供共享算法,但是实际的工作被可配置委托组件完成。前端控制器像任意一个servlet一样。需要被声明,和映射通过java配置的方式或者web.xml传统方式。前端控制器使用 Spring 配置来发现请求映射、视图解析、异常处理所需的委托组件。
Context的层次
配置方式
这是基于java配置的方式之一:
这个可以使得springmvc的开发完全基于java代码不用去编写配置文件,但是这个配置有局限性,就是很多事情Spring帮我们做了,但是我们并不知道做了那些事情,如果要扩展功能,就会有限制。
所以最好还是使用XML文件的配置方式去配置DispatchServlet。
/*通过继承AbstractAnnotationConfigDispatcherServletInitializer类来简化配置,这个是WebApplicationInitializer接口的实现类,WebApplicationInitializer是springmvc提供的一个接口,确定检测到你的实现,和自动用于初始化任何Servlet3容器.
*/
package cn.wangmyi.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class DispatchServletConig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ServletBean.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
这个xml配置的方式:
<web-app>
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--这个的默认地址是/WEB-INF/app-context.xml配置文件-->
<param-value>这里是前端控制器的配置元数据的配置路径</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
</web-app>
DispatcherServlet处理一个请求的流程
DispatcherServlet处理一个请求
- 在request请求中WebApplication被搜索并绑定为一个属性,在过程中controller或者其他元素可以使用
- locale resolver绑定到request中,让在解析locale的过程中的元素去使用,当处理请求时,如果不需要locacle解析,就不需要这个。
- 绑定主题解析器到lrequest中,让试图取使用。不用这个可以忽略。
- 如果有指定一个multipart file resolver,由于multiparts,request将被检查。如果发现request中包含multipart,它就会被包装到成MultipartHttpServletRequest进入更进一步被其他在过程中的元素处理。
- 合适的handler查找(HandlerMapping的工作),如果找到与handler有关的执行链就会执行取准备一个模型(modle)用于渲染,或者如果handler有被注解@ResponseBody那么响应将直接被渲染取代视图的渲染。
- 如果model被返回了,试图就被渲染,如果没有就没有试图被渲染,因为了请求已经被完成了。
- 所有的请求都要先经过前端控制器,然后前端控制器把单个实例的请求委托给其他的组件来执行。
- Dispatcher查询映射处理器确定应该去哪个控制器
- 选择好控制器之后,讲请求发送给控制器,控制器处理请求。
- 请求通过讲数据绑定到模型上,再指定视图名,发送回DispatcherServlet。
- DispatcherServlet调用视图解析器将控制器传回的试图名字进行匹配,找到一个特定的视图。
- DispatcherServlet渲染视图,就是把模型数据绑定到视图上
- 向客户端相应请求。就是把视图传送回去。
Web MVC Config的配置
Application 可以声明处理请求所需要的基础Bean。DispatcherServlet回去WebApplicationContext里面找特殊的Bean——就是处理请求所需要的基础Bean——如果我们没有·给DispatcherServlet提供,那么它就会使用默认的类型。在DispatcherServlet.proerpties文件里的属性。
基本的Bean
Bean type | Explanation |
---|---|
HandlerMapping |
将一个请求映射到一个连同用作前置和后置处理的拦截器一起的handler。映射基于特定一些标准,具体的根据HandlerMapping的实现而定。 |
HandlerAdapter |
在HandlerMapping找到handler之后,HandlerAdapter将帮助DispatcherServlet调用被映射的handler处理请求,不管它是如何被调用的。HandlerMapping主要是为了在一些细节上隐藏DispatcherServlet。这个就是处理例如@ResponseBody的,如果被这个注解了那么就不调用试图解析器了。 |
HandlerExceptionResolver |
解析异常的策略,可能将他们映射到处理器或者映射到一个错误的页的HTML,或者其他目标。 |
ViewResolver |
将一个从handler返回的基于String的视图名到一个真正的视图并渲染他们响应回去。 |
ThemeResolver |
解析你的web应用使用的主题。 |
MultipartResolver |
spring提供的多文件上传的帮助库。 |
基于Java配置DispatchServlet的方法:
实现WebApplicationInitializer接口。
这个接口是确保你实现是可以被探测到并且可以自动使用去初始化Servlet3容器的。
import org.springframework.web.WebApplicationInitializer;
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
使用Spring提供的WebApplicationInitializer实现类AbstractDispatcherServletInitializer可以更简单的的去注册DispatcherServlet,(这个是基于java配置Mvc推荐的方法) 可以通过继承已经继承了AbstractDispatcherServletInitializer的
AbstractAnnotationConfigDispatcherServletInitializer 去初始化DispatcherServlet,这个只要提供两个上下文的实现类——ServletApplicationContext和RootApplicationContext的类的类对象就可以。
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { MyWebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
基于XML-based Spring configuration
需要直接继承AbstractDispatcherServletInitializer。这个方式提供添加Filter实例,并且自动映射到DIspatcherServlet中。
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
XmlWebApplicationContext cxt = new XmlWebApplicationContext();
cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
return cxt;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
return new Filter[] {
new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
}
}
使用web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/web/RootApplicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>dispactcherServelet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/web/WebApplicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispactcherServelet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>