SpringMVC总结帖
SpringMVC是基于MVC设计理念的一款优秀的Web框架,是目前最流行的MVC框架之一,SpringMVC通过一套注解,让POPJ成为处理请求的控制器,而无需实现任何接口,然后使用实现接口的控制器也完全没问题;支持REST风格的URL请求;采用松散耦合架构,比其他MVC框架更具有灵活性和扩展性。关于SpringMVC工程如何搭建请点击:Spring学习之第一个Spring MVC程序(IDEA开发环境)。
0 XML配置文件
web.xml配置DispatcherServlet,DispatcherServlet默认会加载/WEB-INF/xxx-servlet.xml的Spring配置信息,启动Web层的Spring容器。当然,也可以通过配置contextConfigLocation来自定义配置文件名称和位置,如下所示:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
0.1 xxx-servlet.xml配置
xxx-servlet.xml中一般配置自动扫描的包信息、HandlerMapping、ViewResolver,如果没有配置HandlerMapping,则默认使用的是BeanNameURLHandlerMapping;如果没有配置ViewResolver,则默认使用的InternalResourceViewResolver。
<!-- 配置自定义扫描的包-->
<context:component-scan base-package="com.luoxn28"></context:component-scan> <!-- ViewResolver 视图解析器 如果没有配置的话,则InternalResourceViewResolver就是默认的 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="1"/> <!-- ViewResolver优先级 -->
<!-- 前缀 和 后缀 -->
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
1 使用@RequestMapping映射请求
SpringMVC中使用@RequestMapping注解为handler指定可以处理那些URL请求,该注解可以在方法及类定义处使用,DispatcherServlet处理请求时,通过handler的@RequestMapping提供的映射信息确定请求的处理类(或方法)。@RequestMapping在类和方法定义不同之处在于:
- 类定义处:提供初步的请求映射信息,相对于 WEB 应用的根目录。
- 方法处:提供进一步的细分映射信息。,相对于类定义处的 URL,若类定义处未标注@RequestMapping,则方法处标记的 URL 相对于WEB 应用的根目录。
使用@RequestMapping示例如下所示:
@Controller
@RequestMapping("/test")
public class Test { @RequestMapping("/testperson")
public String testUser(Person person) {
System.out.println(person); return "index";
}
}
1.1 @RequestMapping映射请求头、请求方法、参数
@RequestMapping 除了可以使用请求URL映射请求外,还可以使用请求方法、请求参数及请求头映射请求,这些从@RequestMapping注解源码也可以看得出来。@RequestMapping 的 value、method、params 及 heads分别表示请求 URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可让请求映射更加精确化。
@RequestMapping(value = "/delete", method = RequestMethod.POST, params = "userId")
public String delete() {
// ...
return "xxx";
} @RequestMapping(value = "/show", headers = "contentType=text/*")
public String show() {
// ...
return "xxx";
}
1.2 @RequestMapping映射URL绑定的占位符
带占位符的URL是Spring3.0之后新增的功能,该功能是SpringMVC向REST风格挺进发展一个重要标志。通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable("xxx") 绑定到操作方法的入参中。
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") Integer id) {
UserDao.delete(id);
return "index";
}
ps: 关于什么是REST请翻到最后:finally REST部分。
2 映射请求参数
- Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应人参中。
- Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。
- 必要时可以对方法及方法入参标注相应的注解(@PathVariable、@RequestParam、@RequestHeader 等)、SpringMVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理。
2.1 使用@RequestParam绑定请求参数
在方法入参出使用@RequestParam把请求参数传递到方法中。-value是参数名,-requered是否必须,默认为true,表示如果该请求参数中不存在对应的参数,则抛出异常。
@RequestMapping("/userinfo")
public String getUserInfo(@RequestParam(value = "usrename", required = false) String username,
@RequestParam("age") int age) {
// ...
return "xxx";
}
2.2 使用@RequestHeader绑定请求头参数
请求头包含了若干个属性,服务器可据此获知客户端的信息,通过@RequestHeader即可将请求头中的属性值绑定到处理方法的入参中。
@RequestMapping("/hreaderinfo")
public String getUserInfo(@RequestHeader("Accept-Encoding") String encoding) {
// ...
return "xxx";
}
2.3 使用@CookieValue绑定Cookie值
@RequestMapping("/sessioninfo")
public String getUserInfo(@CookieValue("sessionId") String sessionId) {
// ...
return "xxx";
}
2.4 使用POPJ对象绑定请求参数值
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
@RequestMapping("/personinfo")
public String getUserInfo(Person person) {
// ...
return "xxx";
}
当请求URL为 /personinfo?name=luoxn28&age=23 时,就会进行POPJ对象的填充,Person类如下所示:
public class Person {
String name;
int age;
// xxx
}
2.5 使用ServletAPI类型的参数
@RequestMapping("/servlet")
public String getUserInfo(HttpServletRequest request, HttpServletResponse response) {
// ...
return "xxx";
}
SpringMVC的handler方法可以接受HttpServletRequest/HttpServletResponse/HttpSession或者是java.security.Principal/Locale/InputStream/OutputStream/Reader/Writer类型的参数。
3 处理数据模型
SpringMVC有几种方式用于数据模型输出,有ModelAndView、Map及Model、@SessionAttributes、@ModelAttribute等。
- ModelAndView: 处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据。
- Map及Model: 入参为org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map中的数据会自动添加到模型中。
- @SessionAttributes: 将模型中的某个属性暂存到HttpSession 中,以便多个请求之间可以共享这个属性。
- @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中。
@RequestMapping("/model")
public String getUserInfo(Map<String, Object> map) {
map.put("time", new Date());
return "xxx";
}
@Controller
@RequestMapping("/test")
@SessionAttributes("time")
public class Test { @RequestMapping("/session")
public String getUserInfo(Map<String, Object> map) {
map.put("time", new Date());
return "index";
}
}
当访问url为 /test/session 时,会往服务器session中加入time属性,其值为当前时间(new Date())。
@ModelAttribute
在方法定义上使用 @ModelAttribute 注解:Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
在方法的入参前使用 @ModelAttribute 注解:
- 可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参
- 将方法入参对象添加到模型中
@Controller
@RequestMapping("/test")
@SessionAttributes("time")
public class Test { /**
* 该方法会往隐含模型中添加一个名为time的模型数据
* 注意:同一个浏览器同一段时间内,该函数只会被调用一次
*/
@ModelAttribute("time")
public Date getDate() {
Date time = new Date();
System.out.println("getDate -- " + time);
return time;
} @RequestMapping("/model")
public String getUserInfo(@ModelAttribute("time") Date time, Map<String, Object> map) {
System.out.println(time);
map.put("date", new Date());
return "index";
}
}
3.1 由@SessionAttribute引发的异常
如果在处理类定义处标注了@SessionAttributes(“xxx”),则尝试从会话中获取该属性,并将其赋给该入参,然后再用请求消息填充该入参对象。如果在会话中找不到对应的属性,则抛出 HttpSessionRequiredException 异常。
所以,为了避免发生异常,一般都会在请求到达handler方法前往数据模型(session域)中添加属性,比如上面代码中的public Date getDate()方法一样。
4 视图和视图解析器
SpringMVC是如何解析视图的呢?在handler方法返回String、ModelAndView或者View后,都会被SpringMVC内部转换为ModelAndView类型(如果handler方法为void类型的,则该方法自己负责数据渲染和返回结果)。
Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是Excel、JFreeChart 等各种表现形式的视图。对于最终究竟采取何种视图对象对模型数据进行渲染,handler并不关心,handler工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦。

4.1 视图
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。SpringMVC中定义了一个View接口,源码如下,视图对象有视图解析器负责实例化,是无状态的,所以不会有线程安全问题。
public interface View {
String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
String PATH_VARIABLES = View.class.getName() + ".pathVariables";
String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
String getContentType();
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
常用的视图实现类:

4.2 视图解析器
SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。所有的视图解析器都必须实现 ViewResolver 接口。常用的视图解析器实现类如下所示:

可以选择一种视图解析器或混用多种视图解析器,每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常。
InternalResourceViewResolver是最常用的视图解析器,也是默认的视图解析器,负责解析JSP视图,使用方式如下所示:
<!-- ViewResolver 视图解析器 如果没有配置的话,则InternalResourceViewResolver就是默认的 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="1"/> <!-- ViewResolver优先级 -->
<!-- 前缀 和 后缀 -->
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
4.3 关于重定向
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理。如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理。
- redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
- forward:success.jsp:会完成一个到 success.jsp 的转发操作
@RequestMapping("/forward")
public String getUserInfo(Map<String, Object> map) {
//...
return "redirect:index";
}
5 REST编程
实现rest风格的增删改查,增删改查的对象是Person类,源码如下:
package com.luoxn28.attribute; import org.springframework.stereotype.Repository; import java.util.HashSet;
import java.util.Set; @Repository
public class Person {
String name;
int age; public static Set<Person> persons = null; static {
persons = new HashSet<Person>();
persons.add(new Person("aaa", 12));
persons.add(new Person("bbb", 16));
persons.add(new Person("ccc", 18));
persons.add(new Person("ddd", 24));
} public Person() {
} public Person(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Person类
显示Person、删除Person、更新Person页面list.jsp源码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html>
<head>
<title>Title</title> <script type="text/javascript" src="/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(function(){
$(".delete").click(function(){
var href = $(this).attr("href");
$("form").attr("action", href).submit();
return false;
});
})
</script>
</head>
<body> <form action="" method="POST">
<input type="hidden" name="_method" value="DELETE"/>
</form> <c:forEach var="person" items="${persons}">
姓名:${person.name} <br/>
年龄:${person.age} <br/>
<a class="delete" href="/rest/person/${person.name}">删除</a>
<a href="/rest/person/${person.name}">更新</a>
<hr/>
</c:forEach> </body>
</html>
list.jsp
添加Person页面post.jsp源码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html>
<head>
<title>Title</title>
</head>
<body> <form action="/rest/person" method="post">
名字<input type="text" name="name" placeholder="名字"/> <br/>
年龄<input type="text" name="age" placeholder="年龄"/> <br/>
<input type="submit" value="提交"/>
</form> </body>
</html>
post.jsp
Rest处理类源码如下所示:
package com.luoxn28.rest; import com.luoxn28.attribute.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import java.util.Iterator;
import java.util.Map;
import java.util.Set; @Controller
@RequestMapping("/rest")
public class Rest { // 显示所用Person
@RequestMapping("/persons")
public String persons(Map<String, Set<Person>> map) {
map.put("persons", Person.persons); return "list";
} // 添加Person
@RequestMapping(value = "/person", method = RequestMethod.POST)
public String personPost(Person person, Map<String, Set<Person>> map) {
Person.persons.add(person);
map.put("persons", Person.persons); return "list";
} // 删除Person
@RequestMapping(value = "/person/{name}", method = RequestMethod.DELETE)
public String personDelete(@PathVariable("name") String name, Map<String, Set<Person>> map) {
Iterator<Person> iter = Person.persons.iterator();
while (iter.hasNext()) {
if (iter.next().getName().equals(name)) {
iter.remove();
System.out.println("删除成功 " + name);
}
}
map.put("persons", Person.persons); return "redirect:/rest/persons";
} // 更新Person
@RequestMapping(value = "/person/{name}", method = RequestMethod.GET)
public String personUpdate(@PathVariable("name") String name, Map<String, Set<Person>> map) {
Iterator<Person> iter = Person.persons.iterator();
while (iter.hasNext()) {
Person person = iter.next();
if (person.getName().equals(name)) {
person.setAge(0);
System.out.println("更新成功 " + name);
}
}
map.put("persons", Person.persons); return "redirect:/rest/persons";
} }
finally REST
REST:即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识别符。
表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
REST示例
- – /order/1 HTTP GET :得到 id = 1 的 order
- – /order/1 HTTP DELETE:删除 id = 1的 order
- – /order/1 HTTP PUT:更新id = 1的 order
- – /order HTTP POST:新增 order
参考资料:
1、尚硅谷SpringMVC学习视频及资料
2、Spring学习之第一个Spring MVC程序(IDEA开发环境)
SpringMVC总结帖的更多相关文章
- [转帖]spring、springMvc、springBoot和springCloud的联系与区别
spring.springMvc.springBoot和springCloud的联系与区别 -- :: 尘光掠影 阅读数 文章标签: springspringmvcspringbootspringCl ...
- SpringMVC上传文件的三种方式(转帖)
/* * 通过流的方式上传文件 * @RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象 */ @Re ...
- springMVC 简单事例
本帖最后由 悲观主义者一枚 于 2015-1-31 17:55 编辑 使用SpringMvc开发Android WebService入门教程1.首先大家先创建一个JavaWeb项目2.然后加入Spri ...
- springMVC能做什么,做j2ee时候要考虑什么
转载: http://jinnianshilongnian.iteye.com/category/231099 [置顶] 跟我学SpringMVC目录汇总贴.PDF下载.源码下载 博客分类: 跟开涛学 ...
- springMVC项目国际化(i18n)实现方法
SpringMVC项目国际化(i18n)实现方法 按照作息规律,每周五晚必须是分享知识的时间\(^o^)/~,这周讲点儿啥呢,项目需要逼格,咱们国际化吧(* ̄rǒ ̄)~,项目中碰到这类需求的童鞋可能并 ...
- springmvc(二) ssm框架整合的各种配置
ssm:springmvc.spring.mybatis这三个框架的整合,有耐心一步步走. --WH 一.SSM框架整合 1.1.整合思路 从底层整合起,也就是先整合mybatis与spring,然后 ...
- SSM整合1(springMVC+mybatis)
整合目标:控制层采用springmvc.持久层使用mybatis实现 整合思路: Dao层: 1.SqlMapConfig.xml,空文件即可,但是需要文件头. 2.applicationContex ...
- 【SpringMVC】入门
一.概述 1.1 SpringMVC是什么 1.2 MVC在b/s系统的应用 1.3 SpringMVC 原理 二.入门程序 2.1 需求 2.2 引入依赖 2.3 前端控制器 2.4 springm ...
- 【分享】标准springMVC+mybatis项目maven搭建最精简教程
文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...
随机推荐
- jQuery Label Better – 友好的表单输入框提示插件
jQuery Label Better 帮助你标记您的表单输入域,带有美丽的动画效果而且不占用空间.这个插件的独特之处在于所有你需要做的就是添加一个占位符文本,只有当用户需要它的时候才显示标签. 您可 ...
- ImageLightbox.js – 响应式的图片 Lightbox 插件
ImageLightbox.js 是一款很简洁的用于显示图片灯箱效果(Lightbox)的插件,没有字幕,导航按钮或默认背景.如果默认功能不够用的话,你可以很容易地自定义 JavaScript 函数扩 ...
- [js开源组件开发]tip提示组件
tip提示组件 常见的应用场景中,总是难免会遇到提示信息,比如显示不完全时需要鼠标移上去显示title,比如验证时的错误提示,比如操作按钮的辅助说明等,所以我独立出来了一个小的js组件,tip提示组件 ...
- 一级缓存、二级缓存、延迟加载、hibernate session 域 pojo三种状态
1.一级缓存(session缓存 ).二级缓存 意义:提高hibernate查询效率. 缺点:可能会因并发,产生数据不一致. 本质:基于session 的缓存,利用hiber ...
- MS14-064 漏洞测试入侵win7
Microsoft Windows OLE远程代码执行漏洞,OLE(对象链接与嵌入)是一种允许应用程序共享数据和功能的技术, 远程攻击者利用此漏洞通过构造的网站执行任意代码,影响Win95+IE3 – ...
- 客户端调用服务端webservice的端口问题
今天有一个同事过来问:他有一个程序在A服务器上调第三方B服务器短信发送服务接口(webservice),无论是否发送成功,服务接口都会返回状态.现在客户要做每一个服务器 做入站端口管控,一切不必要的端 ...
- Android项目实战(二十):浅谈ListView悬浮头部展现效果
先看下效果:需求是 滑动列表 ,其中一部分视图(粉丝数,关注数这一部分)在滑动到顶端的时候不消失,而是停留在整个界面头部. 我们先分析要解决的问题: 1.如何实现列表ListView顶部视图跟随Lis ...
- 【代码笔记】iOS-将400电话中间加上-线
一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. ...
- iOS 使用GCD实现倒计时效果
在APP开发过程中,经常有需要实现倒计时效果, 比如语音验证码倒计时...代码如下: __block int timeout = 100; dispatch_queue_t queue = dispa ...
- Android实现欢迎界面,点击进入应用
在主线程中开启一个新线程,每隔100ms检查一下时间是否到达自己预设的显示时间,到达则进入应用 实现屏幕的触摸事件,当触摸的时候,进入应用 package com.example.administra ...