一、什么是MVC
V 是View (视图),代表与用户交互界面。
M 是Model(模型层),业务流程/状态的处理以及业务规则的制定。模型层接受视图层的请求,并返回最终的处理结果。
C 是Controller(控制层),分发,决定使用哪个模型,返回哪个视图。
二、SpringMVC
相关组件:
DispatcherServlet l拦截请求,发送给SpringMVC控制器;
HandlerMapping映射器,记录url与处理器的映射,方式有注解、xml配置等,DispatcherServlet通过查询HandlerMapping来查询具体的请求对应哪个控制器,然后分发;
Handler处理器,后端控制器,具体的业务代码,对用户的请求进行处理;
HandlerAdapter,处理器适配器将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多种类型的处理器。调用处理器响应处理方法,返回一个ModelAndView对象,包含模型数据、逻辑视图名;
ViewResolver视图解析器将把逻辑视图名称解析为具体的View;
View根据传过来的Model模型数据进行渲染;
返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,至此一个流程结束。
web.xml配置示例:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
spring-mvc.xml配置示:
<beans>
<!-- 配置映射处理器:根据bean(自定义Controler)的name属性的url去寻找hanler;springmvc默认的映射处理器是
BeanNameUrlHandlerMapping
-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置处理器适配器来执行Controlelr ,springmvc默认的是
SimpleControllerHandlerAdapter
-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置自定义Controler -->
<bean id="myController" name="/hello.do" class="org.controller.MyController"></bean>
<!-- 配置sprigmvc视图解析器:解析逻辑试图;
后台返回逻辑试图:index
视图解析器解析出真正物理视图:前缀+逻辑试图+后缀====/WEB-INF/jsps/index.jsp
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsps/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
此处配置也可以通过注解实现,在spring-mvc.xml中配置扫描对应控制器的包:
<context:component-scan base-package="xxx.xxx.controller" />
controller包下增加对应的controller类代码:
注解时的写法:
@Controller
@RequestMapping("/xxx")
public class XxxController {
xml写法:
public class MyController implements Controller{
public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略。
映射处理器有三种,三种可以共存,相互不影响,分别是BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping、ControllerClassNameHandlerMapping;
//默认映射器,即使不配置,默认就使用这个来映射请求。
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
//映射器把请求映射到controller
<bean id="testController" name="/hello.do" class="org.controller.TestController"></bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/ss.do">testController</prop>
</props>
</property>
</bean>
//那么上面的这个映射配置:表示多个*.do文件可以访问多个Controller或者一个Controller。
//前提是:都必须依赖自定义的控制器bean
<bean id="testController" name="/hello.do" class="org.controller.TestController"></bean>
//这个Mapping一配置:我们就可以使用Contrller的 [类名.do]来访问这个Controller.
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
处理适配器有SimpleControllerHandlerAdapter和HttpRequestHandlerAdapter,前者是默认的处理器,后者将http请求封装为HttpServletRequest和HttpServletResponse两个对象。
<!-- 配置HttpRequestHandlerAdapter适配器 -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
代码示例:
public class HttpController implements HttpRequestHandler{
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//给Request设置值,在页面进行回显
request.setAttribute("hello", "这是HttpRequestHandler!");
//跳转页面
request.getRequestDispatcher("/WEB-INF/jsps/index.jsp").forward(request, response);
}
}
部分源码:
public interface Controller
{
public abstract ModelAndView handleRequest(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws Exception;
}
public interface HandlerAdapter
{
public abstract boolean supports(Object obj);
public abstract ModelAndView handle(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, Object obj)
throws Exception;
public abstract long getLastModified(HttpServletRequest httpservletrequest, Object obj);
}
public class SimpleControllerHandlerAdapter
implements HandlerAdapter
{
public boolean supports(Object handler)
{
return handler instanceof Controller;
}
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
{
return ((Controller)handler).handleRequest(request, response);
}
public long getLastModified(HttpServletRequest request, Object handler)
{
if(handler instanceof LastModified)
return ((LastModified)handler).getLastModified(request);
else
return -1L;
}
}
从其他地方看来的dispatcher实现:
public class Dispatcher {
public static List<HandlerAdapter> handlerAdapter = new ArrayList<HandlerAdapter>();
public Dispatcher(){
handlerAdapter.add(new SimpleHandlerAdapter());
}
//核心功能
public void doDispatch() {
SimpleController handler = new SimpleController();
AnnotationController handler = new AnnotationController();
//传递给对应的处理器适配器(HandlerAdapter)
HandlerAdapter handlerAdapter = getHandlerAdapter(handler);
//处理器适配器调用相应的Handler方法
handlerAdapter.handle(handler);
}
//通过Handler找到对应的处理器适配器(HandlerAdapter)
public HandlerAdapter getHandlerAdapter(Controller handler) {
for(HandlerAdapter adapter : handlerAdapter){
if(adapter.supports(handler)){
return adapter;
}
}
return null;
}
}
public class Test {
public static void main(String[] args) {
Dispatcher dispather = new Dispatcher();
dispather.doDispatch();
}
}
前后端交互时防止乱码,在web.xml中增加过滤器:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>