SpringMVC——高级参数绑定(数组、集合),@RequestMapper 的使用,Controller方法的三种返回值类型,异常处理器,上传图片,JSON数据交互,配置拦截器
一.高级参数绑定
1、将前端传来的参数绑定数组/集合中
1)数组直接接收
@RequestMapping(value = "/arrayTest.action")
public void arrayTest(Integer[] ids){
System.out.println(Arrays.toString(ids));
}
2)POJO中的数组接收
@RequestMapping(value = "/arrayTest.action")
public void arrayTest(QueryVo vo){
System.out.println(Arrays.toString(vo.getIds()));
}
3)集合直接接收(报错,无法直接接收)
@RequestMapping(value = "/arrayTest.action")
public void arrayTest(List<Integer> ids){
System.out.println(ids);
}
4)POJO中的集合接收
@RequestMapping(value = "/arrayTest.action")
public void arrayTest(QueryVo vo){
System.out.println(vo.getIds());
}
2、将前端传来的所有参数保存到集合中
JSP页面样式

<form action="${pageContext.request.contextPath }/arrayTest.action" method="post">
商品列表:
<table width="100%" border=1>
<tr>
<td>选择</td>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
<td><input type="checkbox" name="ids" value="${item.id }"></td>
<td><input type="text" name="itemsList[${s.index}].name" value="${item.name }"></td>
<td><input type="text" name="itemsList[${s.index }].price" value="${item.price }"></td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
<input type="submit"/>
</form>
QueryVO.java
public class QueryVo {
List<Item> itemsList;
public List<Item> getItemsList() {
return itemsList;
}
public void setItemsList(List<Item> itemsList) {
this.itemsList = itemsList;
}
}
测试类
@RequestMapping(value = "/arrayTest.action")
public void arrayTest(QueryVo vo){
System.out.println(vo.getItemsList());
}
二.@RequestMapper
1、URL路由映射
@RequestMapping(value = "/xxx.action")
2、在类上加
// 简化请求路径 /itemList ==> /item/itemList
@RequestMapping("/item")
public class ItemsController {
3、方法限定
限定GET方法:@RequestMapping(method = RequestMethod.GET)
限定POST方法:@RequestMapping(method = RequestMethod.POST)
GET和POST都可以:@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
4、多个URL映射到同一方法
@RequestMapping(value = "{/itemList.action,/item123.action}")
三.Controller方法返回值
1、返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。(一般用于异常处理器中)
// 配置请求的url
@RequestMapping(value = "/itemList.action")
public ModelAndView queryItemList(){
// 创建页面需要显示的商品数据
List<Item> items = itemService.selectItemsList();
ModelAndView modelAndView = new ModelAndView();
// 放到request域中
modelAndView.addObject("itemList",items);
//modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");
modelAndView.setViewName("itemList");
return modelAndView;
}
2、返回String
优点:解耦,返回视图路径,model带数据,官方推荐此种方式。解耦,数据,视图,分离,MVC 。
// 配置请求的url
@RequestMapping(value = "/itemList.action")
public String queryItemList(Model model){
// 创建页面需要显示的商品数据
List<Item> items = itemService.selectItemsList();
// 放到request域中
model.addAttribute("itemList",items);
//return "itemList"; // 直接返回一个视图文件(jsp)
//return "redirect:/itemEdit.action?itemId=1"; // 重定向到其他URL
return "forward: /itemEdit.action?itemId=1"; // 转发到其他URL
}
3、返回Void(常用于ajax)
/ 配置请求的url
@RequestMapping(value = "/itemList.action")
public void queryItemList(HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model,...其他自定义的类) throws ServletException, IOException {
// 创建页面需要显示的商品数据
List<Item> items = itemService.selectItemsList();
request.setAttribute("itemList",items);
// 请求转发
request.getRequestDispatcher("/WEB-INF/jsp/itemList.jsp").forward(request,response);
}
四.异常处理器
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

自定义异常处理器
1)自定义一个异常MyException.java
public class MyException extends Exception {
private String msg;
public MyException(String msg) {
this.msg = msg;
}
public MyException() {
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
2)在程序中手动抛出这个异常
// 配置请求的url
@RequestMapping(value = "/itemList.action")
public void queryItemList(HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model) throws Exception {
if (1==1) {
throw new MyException("啦啦啦");
}
// 创建页面需要显示的商品数据
List<Item> items = itemService.selectItemsList();
request.setAttribute("itemList",items);
// 请求转发
request.getRequestDispatcher("/WEB-INF/jsp/itemList.jsp").forward(request,response);
}
3)在applicationContext.xml中配置全局异常处理器
<!-- *****************配置全局异常处理器***************** --> <bean class="cn.x5456.exception.CustomExceptionResolver"/>
4)书写异常处理器
import org.springframework.web.servlet.HandlerExceptionResolver; // 别导错包
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, // 发生异常的地方 Serivce层 方法 包名+类名+方法名(形参) 字符串
Exception e) {
ModelAndView mav = new ModelAndView();
String msg = "未知异常";
if (e instanceof MyException){
MyException myex = (MyException) e;
msg = myex.getMsg();
}
mav.addObject("msg",msg);
mav.setViewName("error");
return mav;
}
}
五.上传图片
1)配置上传文件夹的url访问路径

2)配置applicationContext.xml
<!-- *************配置文件上传的实现类,id必须设置为multipartResolver*************-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件上传大小 -->
<property name="maxUploadSize" value="5000000" />
</bean>
<!-- 文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸位30M -->
<property name="maxUploadSize" value="31457280" />
<property name="defaultEncoding" value="UTF-8" />
<!-- 是否延迟加载,在需要的时候才进行上传文件的解析 -->
<property name="resolveLazily" value="true" />
<!-- 文件上传的临时路径,文件上传完成后,临时目录中的临时文件会被自动清除 -->
<property name="uploadTempDir" value="upload/temp" />
</bean>
3)修改form标签
<form id="itemForm" action="${pageContext.request.contextPath }/updateitem.action" method="post" enctype="multipart/form-data">
4)书写Controller
@RequestMapping(value = "/updateitem.action")
public String arrayTest(Item itemPOJO, MultipartFile pictureFile) throws IOException { // 接收前端传来的pic文件对象
// 1.保存图片
// 为避免重复,使用uuid
String picName = UUID.randomUUID().toString().replaceAll("-", "");
// 获取文件名的后缀
String ext = FilenameUtils.getExtension(pictureFile.getOriginalFilename());
// 保存文件
pictureFile.transferTo(new File("D:\\upload\\"+picName+"."+ext));
// 2.更新商品信息
itemPOJO.setPic(picName+"."+ext);
itemService.updateItem(itemPOJO);
return "redict:/itemEdit.action?id="+itemPOJO.getId();
}
六.JSON数据交互
前端
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
$(function () {
// 不能使用
// $.post(url,params,
// function(data){
// 回调
// },
// "json"); 因为这个jasn指的是响应是json格式的数据
var params = '{"id": 1,"name": "测试商品","price": 99.9,"detail": "测试商品描述","pic": "123456.jpg"}'; // 字典+引号==json字符串
$.ajax({
url : "${pageContext.request.contextPath }/json.action",
data : params,
contentType : "application/json;charset=UTF-8",//发送数据的格式
type : "post",
dataType : "json",//回调
success : function(data){
alert(data.name);
}
})
})
</script>
后端
@RequestMapping(value = "/json.action")
public @ResponseBody Item jsonTest(@RequestBody Item item){
System.out.println(item);
return item;
}
七.拦截器
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
配置拦截器
applicationContext.xml
<!-- *************配置拦截器************* -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 所有的请求都进入拦截器 -->
<mvc:mapping path="/**" />
<!-- 配置具体的拦截器 -->
<bean class="cn.x5456.interceptor.HandlerInterceptor1" />
</mvc:interceptor>
<mvc:interceptor>
<!-- 所有的请求都进入拦截器 -->
<mvc:mapping path="/**" />
<!-- 配置具体的拦截器 -->
<bean class="cn.x5456.interceptor.HandlerInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
HandlerInterceptor1.java
package cn.x5456.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.portlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HandlerInterceptor1 implements HandlerInterceptor {
// controller执行后且视图返回后调用此方法
// 这里可得到执行controller时的异常信息
// 这里可记录操作日志
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("HandlerInterceptor1....afterCompletion");
}
// controller执行后但未返回视图前调用此方法
// 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1....postHandle");
}
// Controller执行前调用此方法
// 返回true表示继续执行,返回false中止执行
// 这里可以加入登录校验、权限拦截等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// 获取session
// HttpSession session =request.getSession();
System.out.println("HandlerInterceptor1....preHandle");
// 设置为true,测试使用
return true;
}
}
结果
控制台打印:
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor2..postHandle..
HandlerInterceptor1..postHandle..
HandlerInterceptor2..afterCompletion..
HandlerInterceptor1..afterCompletion..
处理流程
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
- postHandler在拦截器链内所有拦截器返成功调用
afterCompletion按拦截器定义逆序调用
- afterCompletion只有preHandle返回true才调用
SpringMVC与Struts2拦截器的区别
他们的拦截器都是继承servlet的filter;且都能传递了request和response作用域。spring过滤后是去找controller,struts过滤后是去struts的配置文件找action。
// 获取应用的url
request.getScheme() +"://" + request.getServerName() + ":" +request.getServerPort() +request.getContextPath();
// 获取应用的绝对路径
request.getServletContext().getRealPath("/")
浙公网安备 33010602011771号