Spring MVC基本配置和实现(三)
Item
public class Item {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
QueryVo
import java.util.List;
public class QueryVo {
private Item item;
private List<Item> itemList;
private Integer[] ids;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public List<Item> getItemList() {
return itemList;
}
public void setItemList(List<Item> itemList) {
this.itemList = itemList;
}
public Integer[] getIds() {
return ids;
}
public void setIds(Integer[] ids) {
this.ids = ids;
}
}
一、高级参数绑定
1. 绑定至数组
商品列表页面中,每个商品前有一个checkbook,选中多个商品后点击删除按钮,把商品id传递给Controller,根据商品id删除商品信息。前端传入表单如下:
<td><input name="ids" value="1" type="checkbox"></td>
<td><input name="ids" value="2" type="checkbox"></td>
<td><input name="ids" value="3" type="checkbox"></td>
<td><input name="ids" value="4" type="checkbox"></td>
......
Controller接收方式,可以用Integer[]接收,或者pojo的Integer[]属性接收。两种方式任选其一即可。
@RequestMapping(value = "/delete")
public String deleteItems(Integer[] ids) {
// 大多数情况下一个参数名对应一个参数值,但有时一个参数名可以对应多个参数值,多个值以String数组的形式返回。
return "";
}
@RequestMapping(value = "/delete")
public String deleteItems(QueryVo vo) {
// Spring MVC会将表单内容绑定到QueryVo的Integer[] ids中
return "";
}
2. 绑定至List
要想实现商品数据的批量修改,需要在商品列表中可以对商品信息进行修改,并且可以批量提交修改后的商品数据。前端传入表单如下:
<tr>
<td><input type="text" name="itemList[0].id" value="${item.id}"/></td>
<td><input type="text" name="itemList[0].name" value="${item.name }"/></td>
</tr>
<tr>
<td><input type="text" name="itemList[1].id" value="${item.id}"/></td>
<td><input type="text" name="itemList[1].name" value="${item.name }"/></td>
</tr>
可以在List中存放Item对象,并将List<Item>放在包装类QueryVo中,使用QueryVo对象接收
@RequestMapping(value = "/update")
public String updateItems(QueryVo vo) {
// Spring MVC根据 表单中itemList的索引 组装Item对象,并将对象存放至QueryVo的List<Item> itemList属性中
// 注意:接收List类型的数据必须是pojo的属性,方法的形参为List类型无法正确接收到数据(即使用List<pojo>而不是List)
return "";
}
二、@RequestMapping
1. URL路径映射
@RequestMapping("/item")
@RequestMapping(value = "/item")
@RequestMapping(vaule = {"/item", "/list"}) // value的值可以是数组,用以将多个URL映射到同一个方法
2. 窄化请求映射
@Controller
@RequestMapping(value = "/item")
public class Controller { @RequestMapping(value = "/queryItem")
public String queryItem() {
return "";
} } // 最终的访问地址为:/item/queryItem
3. 请求方法限定
限定GET方法
@RequestMapping(method = RequestMethod.GET) 如果通过Post访问则报错:
HTTP Status 405 - Request method 'POST' not supported
三、Controller方法返回值
1. 返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。 2. 返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
a、使用request转向页面,如下:request.getRequestDispatcher("页面路径").forward(request, response);
b、也可以通过response页面重定向:response.sendRedirect("url")
c、也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串"); 3. 返回字符串 3.1 逻辑视图名
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
return "item/editItem"; //指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/item/editItem.jsp 3.2 Redirect重定向
Contrller方法返回结果重定向到一个url地址,如下商品修改提交后重定向到商品查询方法,参数无法带到商品查询方法中。
return "redirect:queryItem.action"; //重定向到queryItem.action地址,request无法带过去 redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,转发后执行了一个新的request和response。由于新发起一个request,原来request域的属性在转发时就不能传递到下一个URL,如果要传递参数可以/item/queryItem.action后边加参数,如下:/item/queryItem?...&….. 3.3 forward转发
controller方法执行后继续执行另一个controller方法,如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中。
return "forward:editItem.action"; //结果转发到editItem.action,request域的属性可以带过去 forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。
四、异常处理器
五、上传图片
1. 配置虚拟目录
http://blog.csdn.net/h3243212/article/details/50819218
2. 引入Maven依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<!--只需要引入commons-fileupload依赖即可,commons-io会被自动引入-->
3. 在springmvc.xml中配置解析器
<!-- 文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
4. 前端表单填写
<form id="itemForm" action="${pageContext.request.contextPath }/item/editItemSubmit.action" method="post" enctype="multipart/form-data">
<input type="file" name="pictureFile"/>
</form>
5. Controller方法
@RequestMapping(value = "/updateItem", method = RequestMethod.POST)
public String update(Items items, MultipartFile pictureFile) throws Exception {
// 1. 获取文件的原始名称
String originalFilename = pictureFile.getOriginalFilename();
// 2. 使用随机生成的字符串 + 原文件扩展名 为图片命名, 防止重名现象发生
String s = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 3. 将文件保存到硬盘
pictureFile.transferTo(new File("/Users/Eric/Pictures/tomcat_tmp/" + s)); // 4. 将新文件名保存到数据库
items.setPic(s);
itemsService.updateItems(items); return "redirect:/list.action";
}
六、JSON数据交互
1. @RequestBody与@ResponseBody
1. @RequestBody作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。例如请求:List.action?id=1&name=zhangsan&age=12 2. @ResponseBody作用:
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
2. 引入Maven依赖
<!--仅需此依赖即可完成json支持, 共导入3个包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.2</version>
</dependency>
3. 配置JSON转换器
注意:如果使用<mvc:annotation-driven /> 则无需手动定义。
4. Controller编写
// 假设前端通过JS提交一个JSON字符串:{"id":88,"name":"BeJson"}
@RequestMapping("/editItemSubmit_RequestJson")
public @ResponseBody Items editItemSubmit_RequestJson(@RequestBody Items items) throws Exception {
// 将JSON字符串转换成一个Items对象
System.out.println(items);
return items; // 把items对象转换成JSON字符串返回
}

七、RESTful支持
1. 什么是RESTful支持?
Restful是一种资源定位及资源操作的风格。它不是标准也不是协议,只是一种风格,是对http协议的诠释。
资源定位:互联网所有的事物都是资源,要求url中没有动词,只有名词。没有参数(?key=value)
Url格式:http://blog.csdn.net/beat_the_world/article/details/45621673
资源操作:使用put、delete、post、get,使用不同方法对资源进行操作。分别对应添加、删除、修改、查询。一般使用时还是post和get。Put和Delete几乎不使用。
2. 修改servlet-mapping
<!-- 把url-pattern改成/,因为.do形式的请求URL不符合RESTful风格 -->
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3. URL模板映射模式
/** 在@RequestMapping(value="/viewItems/{id}")中:{x}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,
* 通过在方法中使用@PathVariable获取{x}中的x变量。@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
*/
@RequestMapping("/viewItems/{id}")
public @ResponseBody viewItems(@PathVariable("id") String id, Model model) throws Exception{
//本方法中形参String id和"/viewItems/{id}"名称相同,因为@PathVariable括号中可以不指定"id"//调用 service查询商品信息
ItemsCustom itemsCustom = itemsService.findItemsById(id);
return itemsCustom;
}
4. 静态资源访问<mvc:resources>
如果在DispatcherServlet中设置<url-pattern>为 / 则必须对静态资源进行访问映射。需要设置spring mvc的<mvc:resources mapping="" location="">实现对静态资源进行映射访问。如下是对js文件访问配置:<mvc:resources location="/js/" mapping="/js/**"/> tomcat在/conf/web.xml中定义了”/”到default Servlet的映射,而org.apache.catalina.servlets.DefaultServlet作为default Servlet,可以处理html和xml文件;并且web.xml定义了”*.jsp”和”*.jspx”到JspServlet的映射,在JspServlet(org.apache.jasper.servlet.JspServlet)中可以处理jsp和jspx文件 因此:.jsp和.html在 / 与 /* 情况下正好有不同的表现
/ -- DispatcherServlet成为默认servlet:
.jsp在web.xml中的扩展映射优先级高于默认映射,因此可以被JspServlet正常处理;
静态文件不能像default Servlet那样被DispatcherServlet处理,也不可能有Controller会匹配处理它,所以静态文件必须配置<mvc:resources>指定目录映射后,才能被访问到。
/* -- DispatcherServlet成为一个匹配所有的路径映射,只有精确路径映射优先级高于它
.jsp在web.xml中的扩展映射优先级低于DispatcherServlet的路径映射,被当做控制器url处理,会提示noHandlerFound
html/xml的静态文件也不会被org.apache.catalina.servlets.DefaultServlet捕获,也无法正常工作
八、处理器拦截器
1. 定义
Spring Web MVC的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。http://jinnianshilongnian.iteye.com/blog/1670856
2. 拦截器接口
Public class HandlerInterceptor1 implements HandlerInterceptor{
/**
* controller执行前调用此方法;返回true表示继续执行,返回false中止执行;这里可以加入登录校验、权限拦截等
*/
@Override
Public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// TODO Auto-generated method stub
Return false;
}
/**
* controller执行后但未返回视图前调用此方法;这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
*/
@Override
Public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
/**
* controller执行后且视图返回后调用此方法;这里可得到执行controller时的异常信息,可记录操作日志,资源清理等
*/
@Override
Public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// TODO Auto-generated method stub
}
}
3. 拦截器设置
<!--针对某种mapping配置拦截器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/> <!--针对所有mapping配置拦截器-->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.it.springmvc.filter.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="cn.it.springmvc.filter.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
4. 正常测试流程
定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2,每个拦截器的preHandler方法都返回true。 运行流程纪录:
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle.. HandlerInterceptor2..postHandle..
HandlerInterceptor1..postHandle.. HandlerInterceptor2..afterCompletion..
HandlerInterceptor1..afterCompletion..

5. 中断流程测试
定义两个拦截器分别为:HandlerInterceptor3和HandlerInteptor4。 运行流程记录:
HandlerInterceptor3的preHandler方法返回false,HandlerInterceptor4返回true,运行流程如下:
HandlerInterceptor3..preHandle..
从日志看出第一个拦截器的preHandler方法返回false后,第一个拦截器只执行了preHandler方法,其它两个方法没有执行;第二个拦截器的所有方法不执行;且controller也不执行了。 HandlerInterceptor3的preHandler方法返回true,HandlerInterceptor4返回false,运行流程如下:
HandlerInterceptor3..preHandle..
HandlerInterceptor4..preHandle..
HandlerInterceptor3..afterCompletion..
从日志看出第二个拦截器的preHandler方法返回false后,第一个拦截器的postHandler没有执行;第二个拦截器的postHandler和afterCompletion没有执行;且controller也不执行了。

6. 总结
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用 postHandler只有拦截器链内所有拦截器都返回true才调用
afterCompletion只有preHandle返回true才调用
代码下载:https://github.com/echo1937/spring-webmvc-demo下的ssm-advanced模块
Spring MVC基本配置和实现(三)的更多相关文章
- Maven 工程下 Spring MVC 站点配置 (三) C3P0连接池与@Autowired的应用
Maven 工程下 Spring MVC 站点配置 (一) Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作 前两篇文章主要是对站点和数据库操作配置进行了演示,如果单 ...
- spring mvc+myBatis配置详解
一.spring mvc Spring框架(框架即:编程注解+xml配置的方式)MVC是Spring框架的一大特征,Spring框架有三大特征(IOC(依赖注入),AOP(面向切面),MVC(建模M- ...
- 基于Spring MVC的Web应用开发(三) - Resources
基于Spring MVC的Web应用开发(3) - Resources 上一篇介绍了在基于Spring MVC的Web项目中加入日志,本文介绍Spring MVC如何处理资源文件. 注意到本项目的we ...
- Spring MVC 事务配置
Spring MVC事务配置 要了解事务配置的所有方法,请看一下<Spring事务配置的5种方法> 本文介绍两种配置方法: 一. XML,使用tx标签配置拦截器实现事务 一. ...
- Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作
详细的Spring MVC框架搭配在这个连接中: Maven 工程下 Spring MVC 站点配置 (一) Maven 工程下 Spring MVC 站点配置 (二) Mybatis数据操作 这篇主 ...
- Maven 工程下 Spring MVC 站点配置 (一)
最近,查找一些具体资料时,虽然会有很多,但是系统的却很少,尤其是对maven 下 spring mvc 站点搭建的配置,总是说的很多但让新手一目了然的步骤却少之又少. 对此闲暇时整理了一下,做了一套较 ...
- Spring mvc系列一之 Spring mvc简单配置
Spring mvc系列一之 Spring mvc简单配置-引用 Spring MVC做为SpringFrameWork的后续产品,Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块 ...
- Spring MVC的配置与DispatcherServlet的分析
Spring MVC是一款Web MVC框架,是目前主流的Web MVC框架之一. Spring MVC工作原理简单来看如下图所示: 接下来进行Spring MVC的配置 首先我们配置Spring M ...
- Spring学习日志之Spring MVC启动配置
对DispatcherServlet进行配置 Spring MVC的配置实际上就是对DispatcherServlet的配置 public class DispatcherServletConfig ...
随机推荐
- hdu-1277--字典树坑题
hdu-1227 字典树,坑题!!当字典树练手 Problem Description 我们大家经常用google检索信息,但是检索信息的程序是很困难编写的:现在请你编写一个简单的全文检索程序. 问题 ...
- 【gcc】命令记录
编译程序gcc -o <eecutable> <soure_code.c>
- hibernate_Session接口_load_get
hibernate读取数据库内容,用 1,session.get(Class类型,主键); 立马发出sql语句.从数据库中取出值装到对象里去 2,session.load(Class类型,主键); 从 ...
- mongo 语法 增删改查
1.增 db.collection.insert()与db.collection.save() 都是增加,区别:save()遇到相同_id后,则更新此_id数据. 而insert()则报错 > ...
- 《LeetBook》leetcode题解(12):Integer to Roman[M]
我现在在做一个叫<leetbook>的免费开源书项目,力求提供最易懂的中文思路,目前把解题思路都同步更新到gitbook上了,需要的同学可以去看看 书的地址:https://hk029.g ...
- maven上传源码到私服
上传源码 项目中采用了分模块的方式构建,直接将maven-source-plugin写到父pom中,尝试了很多次发现源码一直不能上传到私服中,纠结了很长时间才发现原来多模块项目和普通一个项目的配置是有 ...
- digestmd5.c:4037:15: error: #elif with no expression
执行如下:sed -i.bak 's/#elif WITH_DES/#elif defined(WITH_DES)/' \ plugins/digestmd5.c
- ES6 读书笔记
一.let和const命令 二.变量的解构赋值 三.字符串的扩展 四.数值的扩展 五.正则的扩展 六.数组的扩展 七.函数的扩展 八.对象的扩展 九.symbol 十.proxy和reflect 十一 ...
- 【angular5项目积累总结】优秀组件以及应用实例
1.手机端 图片预览组件 组件:sideshow 效果图:(预览图全屏 且可以左右移动) code: <div class="row ui-app-s ...
- 常用 JavaScript 小技巧及原理详解
善于利用JS中的小知识的利用,可以很简洁的编写代码 1. 使用!!模拟Boolean()函数 原理:逻辑非操作一个数据对象时,会先将数据对象转换为布尔值,然后取反,两个!!重复取反,就实现了转换为布尔 ...