1、Spring Web MVC是什么
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
另外还有一种基于组件的、事件驱动的Web框架在此就不介绍了,如Tapestry、JSF等。
Spring Web MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(ViewResolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndViewhandleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
2、Spring Web MVC能帮我们做什么
√让我们能非常简单的设计出干净的Web层和薄薄的Web层;
√进行更简洁的Web层的开发;
√天生与Spring框架集成(如IoC容器、AOP等);
√提供强大的约定大于配置的契约式编程支持;
√能简单的进行Web层的单元测试;
√支持灵活的URL到页面控制器的映射;
√非常容易与其他视图技术集成,如Velocity、FreeMarker等等,因为模型数据不放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用);
√非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
√提供一套强大的JSP标签库,简化JSP开发;
√支持灵活的本地化、主题等解析;
√更加简单的异常处理;
√对静态资源的支持;
√支持Restful风格。
3、Spring Web MVC架构
Spring Web MVC框架也是一个基于请求驱动的Web框架,并且也使用了前端控制器模式来进行设计,再根据请求映射规则分发给相应的页面控制器(动作/处理器)进行处理。首先让我们整体看一下Spring Web MVC处理请求的流程:
2.3.1、Spring Web MVC处理请求的流程
图1-1
具体执行步骤如下:
1、 首先用户发送请求————>前端控制器,前端控制器根据请求信息(如URL)来决定选择哪一个页面控制器进行处理并把请求委托给它,即以前的控制器的控制逻辑部分;图1-1中的1、2步骤;
2、 页面控制器接收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,这个对象在Spring Web MVC中叫命令对象,并进行验证,然后将命令对象委托给业务对象进行处理;处理完毕后返回一个ModelAndView(模型数据和逻辑视图名);图2-1中的3、4、5步骤;
3、 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染;图2-1中的步骤6、7;
4、 前端控制器再次收回控制权,将响应返回给用户,图1-1中的步骤8;至此整个结束。
问题:
1、 请求如何给前端控制器?
2、 前端控制器如何根据请求信息选择页面控制器进行功能处理?
3、 如何支持多种页面控制器呢?
4、 如何页面控制器如何使用业务对象?
5、 页面控制器如何返回模型数据?
6、 前端控制器如何根据页面控制器返回的逻辑视图名选择具体的视图进行渲染?
7、 不同的视图技术如何使用相应的模型数据?
首先我们知道有如上问题,那这些问题如何解决呢?请让我们先继续,在后边依次回答。
2.3.2、Spring Web MVC架构
1、Spring Web MVC核心架构图,如图2-2
图2-2
核心架构的具体流程步骤如下:
1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、 DispatcherServlet——>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、 ModelAndView的逻辑视图名——> ViewResolver,ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
在此我们可以看出具体的核心开发步骤:
1.DispatcherServlet在web.xml中的部署描述,从而拦截请求到Spring Web MVC
<servlet>
<servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springMVC需要加载的配置文件
spring-dao.xml,spring-service.xml,spring-web.xml
Mybatis - >spring -> springmvc
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 默认匹配所有的请求 -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
以上配置了spring的映射文件,与请求的后缀名。
2.HandlerMapping的配置,从而将请求映射到处理器(根据规则取找handler)
非注解的映射方式:1
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
非注解的映射方式:2
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/add1.action">UserController</prop>
<prop key="/add2.action">UserController</prop>
</props>
</property>
</bean>
3.HandlerAdapter的配置,从而支持多种类型的处理器(根据规则取处理handler)
非注解的方式 1
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
要求编写的Handler实现Controller接口
非注解的方式 2
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
要求编写的Handler实现 HttpRequestHandler接口
用request或是response对象向前端返回json串。
4 .ViewResolver的配置,从而将逻辑视图名解析为具体视图技术(返回视图)
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"value="org.springframework.web.servlet.view.JstlView">
</property <property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix"value=".jsp"></property>
</bean>
5、处理器(页面控制器)的配置,从而进行功能处理(页面控制器)
<beanname="/add.action" class="com.cn.hnust.controller.UserController"></bean>
public class UserController implements org.springframework.web.servlet.mvc.Controller{
@Resource
private IUser iuser;
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
User u=new User();
u.setPassword(username);
u.setPassword(password);
iuser.addUser(u);
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject(u);
modelAndView.setViewName("showUser");
return modelAndView;
}
}
二 注解方式
1. DispatcherServlet在web.xml中的部署描述,从而拦截请求到Spring Web MVC
<servlet>
<servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置springMVC需要加载的配置文件
spring-dao.xml,spring-service.xml,spring-web.xml
Mybatis - >spring -> springmvc
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 默认匹配所有的请求 -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
以上配置了spring的映射文件,与请求的后缀名。
2 HandlerMapping的配置,从而将请求映射到处理器(根据规则取找handler)
在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。
3, HandlerAdapter的配置,从而支持多种类型的处理器(根据规则取处理handler)
在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter注解适配器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器。
2. <!-- 注解映射器 -->
3. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
4. <!-- 注解适配器 -->
5. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
6.
7. <!-- 使用mvc:annotation-driven代替上边注解映射器和注解适配器配置
8. mvc:annotation-driven默认加载很多的参数绑定方法,
9. 比如json转换解析器就默认加载了,如果使用mvc:annotation-driven就不用配置上边的
10. RequestMappingHandlerMapping和RequestMappingHandlerAdapter
11.实际开发时使用mvc:annotation-driven-->
12.<!-- <mvc:annotation-driven></mvc:annotation-driven>-->
4.ViewResolver的配置,从而将逻辑视图名解析为具体视图技术(返回视图)
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"value="org.springframework.web.servlet.view.JstlView"></property <property name="prefix"value="/WEB-INF/jsp/"></property>
<property name="suffix"value=".jsp"></property>
</bean>
5 处理器(页面控制器)的配置,从而进行功能处理(页面控制器)
<!-- 4.扫描web相关的bean进行主键扫描 -->
<context:component-scan base-package="com.cn.hnust.controller"></context:component-scan>
<!-- 配置SpringMVC -->
<!-- 1.开启SpringMVC注解模式 -->
<!-- 简化配置:
(1)自动注册DefaultAnootationHandlerMapping,AnotationMethodHandlerAdapter
(2)提供一些列:数据绑定,数字和日期的format @NumberFormat, @DateTimeFormat, xml,json默认读写支持
-->
<mvc:annotation-driven> </mvc:annotation-driven>
@Controller
public class UserController{
@Resource
private IUser iuser;
@RequestMapping("/add.action")
public String toIndex(HttpServletRequestrequest,Model model){
String username = request.getParameter("username");
String password = request.getParameter("password");
User u=new User();
u.setPassword(username);
u.setPassword(password);
iuser.addUser(u);
model.addAttribute("user",u);
return "showUser";
}
}
Handler(controller)的返回值类型:
ModeAndView:
需要定义ModeAndView分别对model和view进行设置
String:如果controller方法返回string为逻辑视图名
1.直接返回视图
2.请求重定向(redirect)
Redirect浏览器地址栏中的url会变化,修改提交的request数据无法传到重定向的地址,因为重定向后重新进行request.
3.请求转发(forward)
通过forward进行页面转发,浏览器地址栏url不变,request可以共享
Void:
Springmvc:参数绑定过程
从客户端绑定key/value数据,经过参数绑定,将key/value数据绑定到方法的参数上
Springmvc接收页面提交的数据是通过方法形参来接收的,而不是在Controller类定义成员变量接受的。
Spiringmvc默认支持的参数绑定类型:
直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。
Httpservletrequest:request对象
Httpservletresponse:response对象
Httpsession:session对象
Model:model是接口,modelmap是接口实现
简单类型:通过@requestParam这个注解来对简单类型的参数进行绑定。如果不用那么要求请求参数与controller中的参数一致。如果使用@requestParam注解,就可以不用保证请求参数与controller中的参数一致。
解决springmvc中的post乱码
<filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
解决springmvc中的get乱码:
Get/post乱码,解决方案。