SpringMVC
注:本篇博客内容关于SpringMVC(着重基于配置文件),会提到SpringMVC的开发模式的执行流程、较浅的源码剖析、SpringMVC的配置、处理器映射器和处理器适配器、Controller开发、参数绑定、validation校验、SpringMVC于Struts2的区别、数据回显、异常处理、json的数据交互、RESTful支持以及SpringMVC拦截器。这是我以前自学Java时写过的笔记内容,也有很多类似的其他的相关笔记内容,如:版本控制工具、主流框架、开发工具等。可以到我的远程库下载,链接:https://github.com/15308232110/My-note(这是我第二次写博客,如果喜欢请留言或私信,我会根据情况决定是否继续写博客。顺便提一点,我是一个乐于助人的人哟!)
1. springmvc执行流程
1. MVC在B/S系统下的应用
2. SpringMVC框架
SpringMVC是Spring框架的一个模块,是一个基于MVC的Web框架,其与Spring整合无需中间整合层,即整合jar包,
执行流程(这个流程和上边的大流程图是重点!):
-1.发起请求到DispatcherServlet。
-2. DispatcherServlet请求HandlerMapping通过配置文件或注解方式查找 Handler。
-3. HandlerMapping向DispatcherServlet返回Handler。
-4. DispatcherServlet调用HandlerAdapter执行Handler。
-5. HandlerAdapter调用Handler处理器执行Handler。
-6.Handler处理器执行完成给HandlerAdapter返回ModelAndView。
-7. HandlerAdapter向DispatcherServlet返回ModelAndView(springmvc框架的底层对象,包括 Model和View)。
-8. DispatcherServlet请求View Resolver进行视图解析。
-9. View Resolver向DispatcherServlet返回View。
-10.DispatcherServlet进行视图渲染,将模型数据(在ModelAndView对象中)填充request域。
-11. DispatcherServlet响应结果。
组件:
.1.DispatcherServlet:用来接受请求并响应结果,相当于转发器,用来与多个组件交互,减少了其它组件之间的耦合度,相当于中央处理器。
.2. HandlerMapping:用来根据请求的url**查找Handler**。
.3.HandlerAdapter:按照特定要求去请求执行Handler(就是业务需求)。
.4. Handler处理器:按照HandlerAdapter的要求执行Handler(需要程序员开发)。
.5 View resolver:进行视图解析,根据逻辑视图名解析成真正的视图。
.6.View:是一个接口,其实现类支持不同的View类型(需要程序员开发jsp) 。
3.源码剖析:(觉得难理解可以先往后看,因为这里我省略了很多,源码毕竟那么多,我也只是零散地列出重要的步骤,所以列出的代码逻辑性不是很强,不用深究这块儿内容)
3.1. 前端控制器接收请求。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
···
}
3.2.调用处理器映射器查找Handler,处理器映射器返回执行链。
mappedHandler = getHandler(processedRequest, false);
----------
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
return getHandler(request);
}
----------
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
3. 调用处理器适配器执行Handler,处理器适配器调用Handler处理器执行Handler得到执行结果ModelAndView后依次返回。
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
3.4. 请求视图解析器进行视图解析并返回视图,在进行视图渲染后将模型数据填充request域。
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
----------
render(mv, request, response);
----------
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
----------
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
在render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)方法中得到view之后渲染。
view.render(mv.getModelInternal(), request, response);
View是一个接口。
public abstract class AbstractView extends WebApplicationObjectSupport implements View, BeanNameAware {
----------
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
for (Map.Entry<String, Object> entry : model.entrySet()) {
String modelName = entry.getKey();
Object modelValue = entry.getValue();
if (modelValue != null) {
request.setAttribute(modelName, modelValue);
if (logger.isDebugEnabled()) {
logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
"] to request in view with name '" + getBeanName() + "'");
}
}
else {
request.removeAttribute(modelName);
if (logger.isDebugEnabled()) {
logger.debug("Removed model object '" + modelName +
"' from request in view with name '" + getBeanName() + "'");
}
}
}
}
2. 入门程序
1.导入Spring相关jar包和需要的配置文件,jar包一定要包括spring-webmvc。
2.配置前端控制器。
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--contextConfigLocation中配置了springmvc需要加载的配置文件-->
<!--如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--1.*.action:访问以.action结尾的请求路径由DispatcherServlet进行解析-->
<!--2./:所有访问地址都由DispatcherServlet进行解析,但对静态资源解析存在问题-->
<!--3./*:最终转发到的jsp页面,也由DispatcherServlet解析,由于不能根据jsp页面找到Handler,会报错-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
3.配置springmvc.xml。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!--配置Handler,name属性值为该Handler的url,注意要与前端控制器的url-pattern对应-->
<bean name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1" />
<bean id="itemsController2" name="/queryItems1.action" class="cn.itcast.ssm.controller.ItemsController2" />
<!--配置处理器映射器,该处理器映射器将bean的name属性值作为url,所有的处理器映射器都实现 HandlerMapping接口-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!--另一个处理器映射器,该处理器映射器可根据Handler的id来进行url配置,多个处理器映射器可以共存-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!--对id为itemsController1的Handr进行url映射,url是/queryItems1.action-->
<prop key="/queryItems2.action">itemsController2</prop>
<!--一个Handler可进行多次url映射,现在该Handler有三个url-->
<prop key="/queryItems3.action">itemsController2</prop>
</props>
</property>
</bean>
<!--配置处理器适配器,所有处理器适配器都实现 HandlerAdapter接口,这是处理器适配器的标识,该处理器适配器能执行实现Controller接口的Handler-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!--另一个处理器适配器,该处理器映射器能执行实现HandlerAdapter接口的Handler,多个处理器适配器也可以共存-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
<!--配置视图解析器,解析jsp视图,默认使用jstl标签-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置jsp路径的前缀和后缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
4.开发Handler
4.1.实现Controller接口的Handler,由SimpleControllerHandlerAdapter处理器适配器执行。
public class ItemsController1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//创建ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相当于request.setAttribut("itemsList", itemsList);
modelAndView.addObject("itemsList", itemsList);
//相当于request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
modelAndView.setViewName("items/itemsList");
//返回ModelAndView
return modelAndView;
}
}
4.2.实现HttpRequestHandler接口的Handler,由HttpRequestHandlerAdapter处理器适配器执行。
public class <