Tips:本笔记主要信息来自于传智播客2015年胡斌SpringMVC备课笔记。笔记内容为:学习资料 + 个人补充;如有内容或排版方面的错误,欢迎纠正~
SpringMVC介绍
为什么使用SpringMVC?
很多应用程序的问题在于处理业务数据和显示业务数据的视图的对象之间存在紧密耦合。通常,更新业务对象的命令都是从视图本身发起的,使视图对任何业务对象更改都有高度敏感性。而且,当多个视图依赖于同一个业务对象时是没有灵活性的。
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
MVC设计模型
MVC 是一种著名的设计模式,特别是在 Web 应用程序领域。模式全都是关于将包含业务数据的模块与显示模块的视图解耦的。这是怎样发生的?视图(例如,JSP 页面)怎样能够与其模型(例如,包含数据的 JavaBean)解耦?记得这句格言么?一个层次的重定向几乎可以解决计算机业中的所有问题。确实,在模型和视图之间引入重定向层可以解决问题。此重定向层是控制器。控制器将接收请求,执行更新模型的操作,然后通知视图关于模型更改的消息。依赖于模型的状态并且依赖于请求的控制器可以决定要显示哪个视图。图 1 演示了这种模式。
SpringMVC的强大之处
- Spring MVC 实现了即用的 MVC 的核心概念。它为控制器和处理程序提供了大量与此模式相关的功能。并且当向 MVC 添加反转控制(Inversion of Control,IoC)时,它使应用程序高度解耦,提供了通过简单的配置更改即可动态更改组件的灵活性。Spring MVC 为您提供了完全控制应用程序的各个方面的力量。
- Spring 的 Web MVC 模块是围绕 DispatcherServlet 而设计的。DispatcherServlet 给处理程序分派请求,执行视图解析,并且处理语言环境和主题解析,此外还为上传文件提供支持。
- DispatcherServlet 通过使用处理程序映射来决定哪一个处理程序应当处理传入的请求。处理程序映射只是用于标识使用哪一个处理程序来处理特定 URL 模式的映射。处理程序是只有一种方法 ModelAndView handleRequest(request,response) 的控制器接口的实现。Spring 还有一些可用的高级处理程序实现;其中一个重要的高级处理程序实现是 SimpleFormController,它提供了将命令对象绑定到表单、对其执行验证等功能。
- 在本系列教程(传智播客黑马程序员系列)的先前教程中使用了 DispatcherServlet 和简单的处理程序。在下一个部分中,将使用 SimpleFormController 并说明 Spring MVC 提供的各种即用功能。
springMVC优势
- 清晰的角色划分:前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器( Validator)、命令对象(Command 请求参数绑定到的对象就叫命令对象)、表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
- 分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要;
- 由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象;
- 和Spring 其他框架无缝集成,是其它Web框架所不具备的;
- 可适配,通过HandlerAdapter可以支持任意的类作为处理器;
- 可定制性,HandlerMapping、ViewResolver等能够非常简单的定制;
- 功能强大的数据验证、格式化、绑定机制;
- 利用Spring提供的Mock对象能够非常简单的进行Web层单元测试;
- 本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
- 强大的JSP标签库,使JSP编写更容易。
………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等。
SpringMVC的运行原理
架构图
传统的MVC架构
首先让我们了解下 MVC(Model-View-Controller)三元组的概念:
- Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或 JavaBean 组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据) 和 服务层(行为)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
领域模型,javaBean组件等价于 域模型层 + 业务逻辑层 + 持久层 - View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
- Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作,。
从上图我们还看到,在标准的 MVC 中模型能主动推数据给视图进行更新(观察者设计模式,在模型上注册视图,当模型更新时自动更新视图),但在 Web 开发中模型是无法主动推给视图(无法主动更新用户界面),因为在 Web 开发是请求-响应模型。
核心架构的具体流程步骤如下:
- 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
- DispatcherServlet——>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
- DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
- HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
- ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
- View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
- 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
DispatcherServlet核心代码分析
1 | //前端控制器分派方法 |
SpringMVC的第一个程序
创建一个javaweb工程
包:cn.itcast.controller导入Spring的jar包
配置DispatcherServlet核心分发器(web.xml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14<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:springmvc.xml</param-value>
</init-param> -->
</servlet>
<!-- 加载默认mvc配置文件:springname-servlet.xml ,必须放在WEB-INF下面-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>//或者使用默认拦截/
</servlet-mapping>
说明:/和/*
的区别?
可以实现现在很流行的REST风格。很多互联网类型的应用很喜欢这种风格的URL。
弊端:会导致静态文件(jpg,js,css)被拦截后不能正常显示。想实现REST风格,事情就是麻烦一些。后面有解决办法还算简单。
拦截/*
,这是一个错误的方式,请求可以走到Action中,但转到jsp时再次被拦截,不能访问到jsp。
配置handlerMapping映射器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<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.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">
<!-- 处理器映射器 -->
<!-- 根据bean的name进行查找Handler 将action的url配置在bean的name中 -->
<!-- 这是一个默认的映射处理器,即使不配置,那么也是默认就是这个 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>配置handlerAdapter适配器
1
2//注意:这个适配器不是必须配置的,这是默认的、他在servlet容器已启动就被加载。
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>编写一个Controller类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class TestController implements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
/**
* 1.收集参数、验证参数
* 2.绑定参数到命令对象
* 3.将命令对象传入业务对象进行处理
* 4.选择视图
*/
ModelAndView mv = new ModelAndView();
//添加模型数据,那么这个数据可以是任意的POJO对象。
mv.addObject("hello","hello world!!");
//设置逻辑视图名,视图解析器会根据该名字解析到具体的视图界面
mv.setViewName("/WEB-INF/jsps/hello.jsp");
return mv;
}
}配置自定义控制器
1
2<!-- 配置自定义controller ,使用beanName:name=”/hello.do”进行进行请求映射匹配-->
<bean name="/hello.do" class="cn.itcast.test.TestController"></bean>定义一个响应页面(hello.jsp)
配置视图解析器
1
2
3
4
5
6
7<!-- 使用视图解析器解析逻辑视图,这样跟方便,易于扩展。-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--逻辑视图前缀-->
<property name="prefix" value="/WEB-INF/jsps/"></property>
<!--逻辑视图后缀,匹配模式:前缀+逻辑视图+后缀,形成完整路径名-->
<property name="suffix" value=".jsp"></property>
</bean>
程序执行流程
1、 首先用户发送请求`http://localhost:9080/springmvc-01/hello``——>web容器,web容器根据“/hello”路径映射到DispatcherServlet(url-pattern为/)进行处理;
2、 DispatcherServlet——>BeanNameUrlHandlerMapping进行请求到处理的映射,BeanNameUrlHandlerMapping将“/hello”路径直接映射到名字为“/hello”的Bean进行处理,即HelloWorldController,BeanNameUrlHandlerMapping将其包装为HandlerExecutionChain(只包括HelloWorldController处理器,没有拦截器)
3、DispatcherServlet——> SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter将HandlerExecutionChain中的处理器(HelloWorldController)适配为SimpleControllerHandlerAdapter;
4、 SimpleControllerHandlerAdapter——> HelloWorldController处理器功能处理方法的调用,SimpleControllerHandlerAdapter将会调用处理器的handleRequest方法进行功能处理,该处理方法返回一个ModelAndView给DispatcherServlet;
5、 hello(ModelAndView的逻辑视图名)——>InternalResourceViewResolver, InternalResourceViewResolver使用JstlView,具体视图页面在/WEB-INF/jsp/hello.jsp;
6、 JstlView(/WEB-INF/jsp/hello.jsp)——>渲染,将在处理器传入的模型数据(message=HelloWorld!)在视图中展示出来;
7、 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
到此HelloWorld就完成了,步骤是不是有点多?而且回忆下我们主要进行了如下配置:
1、 前端控制器DispatcherServlet;
2、 HandlerMapping
3、 HandlerAdapter
4、 ViewResolver
5、 处理器/页面控制器
6、 视图
HandlerMapping
BeanNameUrlHandlerMapping
根据url请求去匹配bean的name属性url,从而获取Controller。HandlerMapping 将会把请求映射为 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面控制器)对象、多个 HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
配置案例:
1 | //默认映射器,即使不配置,默认就使用这个来映射请求。 |
SimpleUrlHandlerMapping
根据浏览器url匹配简单url的key,key又Controller的id找到Controller
1 | <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> |
ControllerClassNameHandlerMapping
根据类名(MyController)类名.do来访问,类名首字母小写
1 | //这个Mapping一配置:我们就可以使用Contrller的 [类名.do]来访问这个Controller. |
HandlerMapping架构图
总结:多个映射器可以共存。相互不影响。
测试策略:三个映射器全部存在于配置文件中,使用映射器的不同访问方式,全部可以访问成功。
HandlerAdapter
SimpleControllerHandlerAdapter
SimpleControllerHandlerAdapter: 执行controller,调用controller里面方法,返回modelAndView。
表示所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean 可以作为Spring Web MVC 中的处理器。如果需要其他类型的处理器可以通过实现 HadlerAdapter 来解决。
案例分析:
1 | ① 模拟一个handlerAdapter |
通过一个简单的Adapter源码分析,发现原来适配器功能这么强大,设计的如此精妙,果然不同凡响。
HttpRequestHandlerAdapter
HTTP请求处理器适配器将http请求封装成HttpServletResquest 和HttpServletResponse对象,和servlet接口类似
1 | 第一步:配置HttpRequestHandlerAdapter适配器 |
总结:适配器可以共存,只是控制器实现不同的接口使用不同的适配器而已。
注意:SimpleControllerHandlerAdapter是默认的适配器。如果使用后面这个适配器必须手动配置。否则将会访问失败。
实现了HttpRequestHandler接口:配置文件里面没有配置这个适配器报如下错误:
No adapter for handler [springMVC_01.HttpRequestController@12d527f]: Does your handler implement a supported interface like Controller?
通过这个错误,我们发现:实现Controller接口是默认的,既是说明:SimpleControllerHandlerAdapter是默认的适配器
还必须注意:实现HttpRequestHandler接口的控制器不支持ControllerClassNameHandlerMapping这个处理器映射器。
控制器
控制器架构图
Controller 简介
1、收集、验证请求参数并绑定到命令对象;
2、将命令对象交给业务对象,由业务对象处理并返回模型数据;
3、返回ModelAndView(Model部分是业务对象返回的模型数据,视图部分为逻辑视图名)。
ServletForwardingController(转发控制器)
1 | //将接收到的请求转发到一个命名的servlet,具体示例如下: |
命令控制器(AbstractCommandController)
通过get请求方式传递参数
① 命令控制器编写
1 | public class CommandController extends AbstractCommandController{ |
② 配置bean
1 | <!-- 配置命令控制器bean --> |
③ 编写JSP页面(add/add.jsp)
④ 传递参数
访问路径:localhost:8080/springmvc/add.do?name=zhangsan&password=123
使用post请求进行表单提交
模拟提交学生表单信息:
1 | ① 编写跳转命令控制器(跳转到添加页面) |
参数控制器(ParameterizableViewController)
1 | <bean name="/toIndex.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController"> |
使用注解的方式实现SpringMVC
注解快速入门
新建一个web工程并导入jar包
配置springMVC配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<?xml version="1.0" encoding="UTF-8"?>
<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.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- 添加注解扫描!!! -->
<context:component-scan base-package="cn.itcast"></context:component-scan>
<!-- 添加注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!-- 注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsps/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
<!-- 注解映射器和注解适配器可以使用<mvc:annotation-driven />代替。
<mvc:annotation-driven />默认注册了注解映射器和注解适配器等bean。
-->配置web.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>springMVC_01</display-name>
<!-- 配置编码过滤器,解决post请求的乱码问题 -->
<filter>
<filter-name>character</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>character</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置springmvc框架,设置springmvc配置文件路径 -->
<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:springMVC.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>编写Controller
1
2
3
4
5
6
7
8
"/user") (
public class MyOneController {
"/fun") (
public String fun(){
return "hello";
}
}编写hello的JSP页面
Controller
- @Controller:用于标识是处理器类.表示把我的控制器对象交给spring来创建。
- Controller起作用:只需要扫描即可。
1
2<!-- 添加注解扫描!!! -->
<context:component-scan base-package="cn.itcast"></context:component-scan>
RequestMapping
@RequestMapping:请求到处理器功能方法的映射规则;
URL路径映射:@RequestMapping(value="/user")或@RequestMapping("/user")
RequestMapping请求方法限定:get、post
Get请求乱码
对于get请求中文参数出现乱码解决方法有两个:
修改tomcat配置文件添加编码与工程编码一致,如下:<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
另外一种方法对参数进行重新编码:1
2
3String userName =new
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码Post请求
在web.xml中加入:1
2
3
4
5
6
7
8
9
10
11
12<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>
URL模板映射
- 需求:将修改请求方式改变
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18@RequestMapping(value="/useredit/{userId}"):{×××}占位符,请求的URL可以是“/useredit/001”或“/useredit/abc”,通过在方法中使用@PathVariable获取{×××}中的×××变量
@RequestMapping("/useredit/{userid}")
public String useredit(@PathVariable String userid,Model model) throws Exception{
//方法中使用@PathVariable获取useried的值,使用model传回页面
model.addAttribute("userid", userid);
return"/user/useredit";
}
//实现restFul,所有的url都是一个资源的链接,有利于搜索引擎对网址收录。
//多个占位符:
@RequestMapping("/useredit/{groupid}/{userid}")
public String useredit(@PathVariable String groupid,@PathVariable String userid,Model model) throws Exception{
//方法中使用@PathVariable获取useried的值,使用model传回页面
model.addAttribute("groupid", groupid);
model.addAttribute("userid", userid);
return "/user/useredit";
}
根路径+子路径
1 | 根路径: |
请求方法限定
1 | • @RequestMapping(method = RequestMethod.GET) |
需要注解映射器(默认使用)
1 | <!-- 添加注解映射器 --> |
需要使用注解适配器(默认使用)
1 | <!-- 注解适配器 --> |
参数传递【请求参数绑定】
1 | ////默认支持的参数类型//// |
RequestParam
-value:参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;
-required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;
-defaultValue:默认值,表示如果请求中没有同名参数时的默认值
定义如下:
1 | public String userlist(@RequestParam(defaultValue="2",value="group",required=true) String groupid){ |
Redirect
Contrller方法返回结果重定向到一个url地址,如下方式:return "redirect:/user/userlist.do";
注意:
redirect:add.do 与 redirect:/user/add.do” 同一个类
在同一个类里面进行跳转。上面2个都可以实现跳转。但是有区别:第一个是同一个根路径下面跳转。第二个是在项目路径下进行跳转。
不同的类进行跳转
不同的类进行跳转只能使用:redirect:/user/add.do进行跳转。即是从项目路径下来查询。
redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,因为转发即执行了一个新的request和response。
由于新发起一个request原来的参数在转发时就不能传递到下一个url,如果要传参数可以/user/userlist.do后边加参数,如下:/user/userlist.action?groupid=2&…..
Forward
controller方法执行后继续执行另一个controller方法。return "forward:/user/userlist.action";
forward方式相当于request.getRequestDispatcher().forward(request,response)
,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。
如下例子:
1 | "/c") ( |
RequestBody/ResponseBody处理Json数据
- 作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。
本例子应用:
@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象
请求Json响应Json
添加处理json数据配置
1
2
3
4
5
6
7
8<!-- 注解适配器 :添加json转换器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean>编写代码【请求json、返回json】
1
2
3
4
5
6
7
8
9
"json") (
public class MyJsonController {
"requestJson.do") (
public User requestJson(Model model,@RequestBody User u){
System.out.println("用户信息:"+u);
return u;
}
}编写页面ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
//请求json,返回json
function request_json(){
var user = JSON.stringify({userName:"张思德",age:21});
$.ajax({
type:'POST',//请求方式
url: '${pageContext.request.contextPath}/json/requestJson.do',//请求地址
contentType:'application/json;charset=utf-8',//发送数据类型
data:user,//传递数据
success : function(data){ //请求成功后的回调函数
alert(data.userName+":"+data.age);
}
})
}
</script>
</head>
<body>
<input type="button" onclick="request_json()" value="请求json,返回json">
</body>
</html>
请求pojo响应json
添加处理json数据配置【同上】
前台请求数据构造:key=value&key=value.
编写Controller代码
1
2
3
4
5
6
7
8
9
"json") (
public class MyJsonController {
"responseJson.do") (
public User responseJson(User user){
System.out.println(user);
return user;
}
}编写页面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
//请求pojo,返回json
function response_json(){
$.ajax({
type:'POST',
url: '${pageContext.request.contextPath}/json/responseJson.do',
data:'userName=张三&age=12',
success : function(data){
alert(data.userName+":"+data.age);
}
})
}
</script>
</head>
<body>
<input type="button" onclick="response_json()" value="请求pojo,返回json">
</body>
</html>
<mvc:annotation-driven />
配置:
注解映射器和注解适配器可以使用<mvc:annotation-driven />
代替。<mvc:annotation-driven />
默认注册了注解映射器和注解适配器等bean。
如下:
1 | 以下配置可用<mvc:annotation-driven />代替: |
多视图
视图是展示给用户的内容,控制器先得到对应的数据模型,对于非逻辑视图,则直接将数据模型渲染便结束;对于逻辑视图,则要先通过视图解析器对其进一步解析,以定位真实视图。
对多视图的配置
1 | <!-- 相当于配置requestmapping和requestAdapter以及json支持 --> |
1 | //Controller代码 |
- 多视图解析需要结合restful风格使用,访问 :multiView.xml||json 验证
注意
json视图需要导入jackson相关包
xml视图需要导入spring-oxm相关包
springMVC的其他视图:freemaker
freemaker是springmvc本身的视图解析器,可以实现页面静态化
准备工作
- 导包:freemaker.jar
- 准备相关文件(index.ftl)
修改springmvc配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<bean id="freeMarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/jsp/"></property>
<property name="defaultEncoding" value="UTF-8"></property>
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">0</prop>
<prop key="default_encoding">UTF-8</prop>
<prop key="number_format">0.##########</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="classic_compatible">true</prop>
<prop key="template_exception_handler">ignore</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="suffix" value=".ftl"></property>
<property name="contentType" value="text/html;charset=utf-8"></property>
</bean>编写controller
ftl文件内容格式
1 | <!DOCTYPE html> |
页面缓存(oscache为例)
需求:使用页面缓存来提高用户体验度
相关概念
缓存原理
优点:提升性能
缺点:不访问数据库,不是实时数据分布式缓存
分布式缓存能控制颗粒的大小,分布式缓存使用的是redis,memcached等等。这相当于是数据库,那么我们是不是在任何一层都可以进行操作数据库。所以可以进行颗粒大小的控制。
使用oscache管理缓存
准备工作
在src根目录下创建oscache.properties
1
2
3
4//oscache.properties常用参数
cache.memory=false//不能缓存内存
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener//持久化类
cache.path=F:\\cache//持久化到F盘导入oscacha-2.4.1.jar
- 配置缓存过滤器
oscache的使用
1 | <!-- 在jsp页面中导入oscache标签库 --> |
注意
缓存是通过“url=页面缓存”的形式保存的,故当请求地址发生变化后,缓存就不起作用了
文件上传
需求分析:使用响应json格式数据的形式上传图片并回显
准备工作
- 导入jar文件(fileupload、io、jersey-client、jersey-core)
- 配置视图解析器
1
2
3
4<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 文件上传的最大值,单位为byte -->
<property name="maxUploadSize" value="10240000"/>
</bean>
代码编写
1 |
|
1 | //页面回显ajax |
拦截器
定义
&emap;SpringWebMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理
局部拦截器
针对某个handlerMapping进行配置只对当前HandlerMapping有效。
1 | //在配置文件中的配置 |
拦截器的代码实践:实现HandlerInterceptor
1 | Public class HandlerInterceptor1 implements HandlerInterceptor{ |
全局拦截器
1 | //相关配置 |
拦截器测试
1 | //测试1 |
- 拦截器的应用(用户身份认证)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Public class LoginInterceptor implements HandlerInterceptor{
Public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//如果是登录页面则放行
if(request.getRequestURI().indexOf("login.action")>=0){
return true;
}
HttpSession session = request.getSession();
//如果用户已登录也放行
if(session.getAttribute("user")!=null){
return true;
}
//用户没有登录挑战到登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
}
SSM整合(SpringMVC,Spring,Mybatis)
为了更好的学习Springmvc和mybatis整合开发的方法,需要将Springmvc和mybatis进行整合,整合目标为:控制层采用SpringMvc,持久层使用mybatis实现
需求
实现商品查询列表,从mysql数据库查询商品信息
jar包
包括:Spring(包括SpringMvc),mybatis,mybatis-Spring整合包,数据库驱动,第三方连接池
Dao
目标:spring管理SqlSessionFactory、mapper
详细参考mybatis教程与spring整合章节。
db.properties
1 | jdbc.driver=com.mysql.jdbc.Driver |
log4j.properties
1 | # Global logging configuration,建议开发环境中要用debug |
sqlMapConfig.xml
1 | //在classpath下创建mybatis/sqlMapConfig.xml |
applicationContext-dao.xml
配置数据源、事务管理,配置SqlSessionFactory、mapper扫描器。
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
ItemsMapper.xml
1 | <?xml version="1.0" encoding="UTF-8" ?> |
ItemsMapper.java
1 | public interface ItemsMapper { |
Service
目标:Service由spring管理;spring对service进行事务控制
applicationContext-service.xml
配置service接口
ApplicationContext-transaction.xml
1 | ////配置事务管理器 |
OrderService
1 | public interface OrderService { |
Action
springmvc.xml
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
web.xml
1 | ////加载spring容器,配置springmvc前置控制器。 |
OrderController
1 |
|