Springmvc自出道以来便以其简单易用,功能强大而闻名于java界,借着其亲爹spring的名头迅速流行起来,可怜昔日的老大structs2频频被曝漏洞,加上使用的复杂性,逐渐日暮西山 ,被springmvc所超越。今天我就来带大家探讨一下springmvc的执行过程。先上图:
下面结合源代码和上图来说明:
一:发送请求到DispatchServlet(*控制器)
Web.xml配置文件:
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
是不是很熟悉的感觉,没错这里就是servlet的配置,只不过这个servlet是系统已经实现好的*控制器:DispatcherServlet.
二:DispatcherServlet(*控制器)调用HandlerMapping(处理器映射器)根据请求url找到需要执行的处理器(此处做了简化实际返回的是执行链)
HandlerMapping是一个接口:
public interface HandlerMapping { 。。。 @Nullable HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception; }
这个接口里面只有一个方法:getHandler,该方法可以通过传入的参数请求对象:HttpServletRequest,得到 :HandlerExecutionChain,这里的HandlerExecutionChain里面包括了处理器对象和拦截器。可以简单的理解为该方法通过request请求对象获得要执行的处理器(每种HandlerMapping实现类返回的处理器不一定相同,有可能是处理器中的方法,也有可能是处理器本身)。
默认的HandlerMapping实现类是BeanNameUrlHandlerMapping,他的getHandler方法返回的是处理器类, 常用的HandlerMapping实现类有:RequestMappingHandlerMapping:采用注解方式进行映射,使用最广泛,也最简单,只需要在类或方法上加上@RequestMapping()的注解就可以了,它的getHandler方法返回的是处理器类中的方法。
@Controller public class HelloController { @RequestMapping("/sayHello") public String sayHello(){ System.out.println("hello"); return "success"; } }
SimpleUrlHandlerMapping:采用配置文件的方式进行映射,适用性最强,需要在配置文件里面配置,它的getHandler方法返回的是处理器类。
三:DispatcherServlet(*控制器)通过HandlerAdapter(处理器适配器)调用处理器
因为不同的HandlerMapping实现类返回的处理器格式不是固定的,所以处理请求时需要HandlerAdapter(处理器适配器)做适配。
public interface HandlerAdapter { //判断该适配器是否支持传入的handler(处理器) boolean supports(Object handler); //使用给定的handler处理请求,也就是执行handler @Nullable ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object handler) throws Exception; long getLastModified(HttpServletRequest var1, Object var2); }
HandlerAdapter也是一个接口,它里面有两个重要的方法:
boolean supports(Object handler) 这个方法可以判断该适配器是否支持传入的handler(处理器)
ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object handler)throws Exception; 这个方法使用给定的handler处理请求,也就是执行handler.
常用的HandlerAdapter实现类是RequestMappingHandlerAdapter,它是和RequestMappingHandlerMapping配合使用的。
在spring mvc的核心配置文件中加上:<mvc:annotation-driven /> 就会自动帮我们注册RequestMappingHandlerMapping和RequestMappingHandlerAdapter
<!-- 配置spring创建容器时要扫描的包 --> <context:component-scan base-package="cn.xh"></context:component-scan> <!-- 配置视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <mvc:annotation-driven />
下面是网上看到的一套模拟springmvc适配器的代码:
//定义一个Adapter接口 public interface HandlerAdapter { public boolean supports(Object handler); public void handle(Object handler); } //以下是三种Controller实现 public interface Controller { } public class HttpController implements Controller{ public void doHttpHandler(){ System.out.println("http..."); } } public class SimpleController implements Controller{ public void doSimplerHandler(){ System.out.println("simple..."); } } public class AnnotationController implements Controller{ public void doAnnotationHandler(){ System.out.println("annotation..."); } } //下面编写适配器类 public class SimpleHandlerAdapter implements HandlerAdapter { public void handle(Object handler) { ((SimpleController)handler).doSimplerHandler(); } public boolean supports(Object handler) { return (handler instanceof SimpleController); } } public class HttpHandlerAdapter implements HandlerAdapter { public void handle(Object handler) { ((HttpController)handler).doHttpHandler(); } public boolean supports(Object handler) { return (handler instanceof HttpController); } } public class AnnotationHandlerAdapter implements HandlerAdapter { public void handle(Object handler) { ((AnnotationController)handler).doAnnotationHandler(); } public boolean supports(Object handler) { return (handler instanceof AnnotationController); } } //模拟一个DispatcherServlet import java.util.ArrayList; import java.util.List; public class DispatchServlet { public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>(); public DispatchServlet(){ handlerAdapters.add(new AnnotationHandlerAdapter()); handlerAdapters.add(new HttpHandlerAdapter()); handlerAdapters.add(new SimpleHandlerAdapter()); }
public void doDispatch(){ //此处模拟SpringMVC从request取handler的对象 //不论实现何种Controller,适配器总能经过适配以后得到想要的结果 //HttpController controller = new HttpController(); //AnnotationController controller = new AnnotationController(); SimpleController controller = new SimpleController(); //得到对应适配器 HandlerAdapter adapter = getHandler(controller); //通过适配器执行对应的controller对应方法 adapter.handle(controller); } public HandlerAdapter getHandler(Controller controller){ for(HandlerAdapter adapter: this.handlerAdapters){ if(adapter.supports(controller)){ return adapter; } } return null; } public static void main(String[] args){ new DispatchServlet().doDispatch(); } }
四:执行处理器,返回ModelAndView给*控制器
这里的ModelAndView类指的是执行完处理器以后需要在视图显示的数据和视图,Model数据,View视图这个名字就很清晰的表明了该类的作用。执行处理器后,将数据保存在ModelAndView的Model属性中,将要显示的视图(通常为逻辑视图名)保存在View属性中,然后返回,ModelAndView类可以将处理器和视图渲染之间的紧密联系解耦和。
@RequestMapping("/findModelAndView") public ModelAndView findModelAndView(){ System.out.println("modelAndView"); ModelAndView md = new ModelAndView(); User u1 = new User(); u1.setUid(1); u1.setName("zhangsan"); u1.setAge(23); md.addObject("user",u1); md.setViewName("aa"); return md; }
五:*控制器调用ViewResolver(视图解析器)根据处理器返回的ModelAndView中的逻辑视图名为*控制器返回一个可用的view实例。
public interface ViewResolver { @Nullable View resolveViewName(String viewName, Locale var2) throws Exception; }
接口ViewResolver里面有一个方法:resolveViewName,可以根据逻辑视图名viewName返回一个View实例。
public interface View { void render(@Nullable Map<String, ?> model, HttpServletRequest var2, HttpServletResponse var3) throws Exception; }
View接口里面有一个方法render,可以将数据model渲染到视图。