SpringMVC_02---参数绑定、异常处理、图片上传、json交互、拦截器
一、参数绑定、@RequestMapping、Controller返回值
绑定数组:在jsp页面中传入数组,在Controller页面接收
//数组参数绑定测试
//jsp页面传来一个 Integer数组
@RequestMapping(value="/deletes.action")
public ModelAndView deletes(Integer[] ids){ //ids为多个id,数组形式
//测试输出数组
for (Integer integer : ids) {
System.out.println(integer);
}
ModelAndView modelAndView = new ModelAndView();
//跳转到成功界面
modelAndView.setViewName("editItem");
return modelAndView;
}
绑定List:
作用:可批量修改表单
描述:在jsp页面提交List,在Controller页面接收
jsp页面
在<c:forEach> 中使用 varStatus。 目的:使用循环变量状态作为集合序号
<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
<td><input type="checkbox" name="ids" value="${item.id}"/></td>
<!-- itemList[0]在集合中放入名称、价格 itemList[${s.index }].name -->
<td><input type="text" name="itemList[${s.index }].name" value="${item.name }" /></td>
<td><input type="text" name="itemList[${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 }/toEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
Controller代码
//集合参数绑定测试
//jsp页面传来list(多个对象)
@RequestMapping(value="/updates.action")
public ModelAndView updates(QueryVo vo) throws MessageException{ //list集合需要存入QueryVo中
//测试输出List
for (Items item : vo.getItemList()) {
System.out.println(item.getName());
System.out.println(item.getPrice());
}
ModelAndView modelAndView = new ModelAndView();
//跳转到成功界面
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping
作用:通过@RequestMapping注解可以定义不同的处理器映射规则
1)URL路径映射 @RequestMapping(value="路径")
2)指定通用请求前缀:在class上添加@RequestMapping(url)
3)请求方法限定:限定get/post请求方式
[email protected](method = RequestMethod.GET)
[email protected](method = RequestMethod.POST)
[email protected](method = {RequestMethod.GET,RequestMethod.POST})
Controller方法返回值
1)返回ModelAndView 带着数据与视图路径 不建议使用
2)返回void ajax、json 异步请求使用
3)返回字符串 返回视图路径 并使用model带数据 (官方推荐:原因、解耦 .数据视图分离)
1.Redirect重定向
2.forward转发
二、异常
两类:
1)未知异常
2)预期异常
springMVC异常处理流程:
未知异常
实现步骤:
1)自定义异常类,实现 HandlerExceptionResolver 接口
2)配置springmvc.xml
<!-- springMVC 自定义异常处理器实例化 -->
<bean class="springmvc.exception.ExceptionResolver"/>
未知异常示例:
/**
* 自定义实现异常处理器
*
* 实现接口HandlerExceptionResolver
* @author 一万年行不行
*
*/
public class ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException( HttpServletRequest req, HttpServletResponse res, Object obj,Exception e) {
//obj 为发生异常的地方 为字符串格式(包名+类名+方法名) 日志中会记录obj
//e 子类异常会被Exception接收
ModelAndView mav = new ModelAndView();
mav.addObject("error","未知异常");
mav.setViewName("error"); //设置跳转视图
return mav;
}
}
预期异常
实现步骤:
1)创建异常信息类 、配置springmvc.xml
2)在Controller中设定异常信息,并抛出异常
3)异常处理器,处理异常
1)创建异常信息类
//继承Exception类 可作为子类在自定义异常中输出msg
public class MessageException extends Exception {
private String msg;
//构造器
public MessageException(String msg) {
super();
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
2)在Controller中设定异常信息,并抛出异常
//集合参数绑定测试
//jsp页面传来list(多个对象)
@RequestMapping(value="/updates.action")
public ModelAndView updates(QueryVo vo) throws MessageException{ //list集合需要存入QueryVo中
//创建未知异常
//Integer i = 1/0;
//创建预期异常
if(null == null){
throw new MessageException("商品信息不能为空");
}
ModelAndView modelAndView = new ModelAndView();
//跳转到成功界面
modelAndView.setViewName("success");
return modelAndView;
}
3)异常处理器,处理异常
/**
* 自定义实现异常处理器
*
* 实现接口HandlerExceptionResolver
* @author 一万年行不行
*
*/
public class ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(
HttpServletRequest req, HttpServletResponse res,
Object obj,Exception e) {
//obj 为发生异常的地方 为字符串格式(包名+类名+方法名) 日志中会记录obj
//e 子类异常会被Exception接收
ModelAndView mav = new ModelAndView();
//判断异常类型
if(e instanceof MessageException){ //e为预期异常,
//将父类异常e 转为子类MessageException
MessageException me = (MessageException) e;
System.out.println(me.getMsg());
//将异常信息设置到 error中
mav.addObject("error",me.getMsg());
}else {
mav.addObject("error","未知异常");
}
mav.setViewName("error"); //设置跳转视图
return mav;
}
}
三、上传图片
配置虚拟目录
目的:在本地建立目录保存图片,而不是放进WebRoot中
作用:防止项目在上线或操作过程中图片丢失
上传实现:
1)导入上传图片所需jar包
2)springmvc.xm中l配置上传解析器
3)jsp表单修改提交类型 : enctype="multipart/form-data"
4)Controller中实现图片上传
1)导入上传图片所需jar包
2)springmvc.xm中l配置上传解析器
<!-- 上传图片实现类 id与class值固定-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传图片大小 5M -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
3)jsp表单修改提交类型 : enctype="multipart/form-data"
<form id="itemForm" action="${pageContext.request.contextPath }/updateitem.action" method="post" enctype="multipart/form-data">
4)Controller中实现图片上传
//提交修改
@RequestMapping(value = "/updateitem.action")
public String updateitem(Items items,MultipartFile pictureFile) throws Exception{ //接收图片类型
//保存图片到本地E:\springmvc_pic
//为图片设置名称,防止名称重复
String picName = UUID.randomUUID().toString();
// 获取文件名
String oriName = pictureFile.getOriginalFilename();
// 获取图片后缀
String extName = oriName.substring(oriName.lastIndexOf("."));
// 开始上传 pictureFile.transferTo() 可将图片直接保存到指定地址
pictureFile.transferTo(new File("E:\\springmvc_pic\\" + picName + extName));
items.setPic(picName + extName); //保存到数据库的图片名
items.setCreatetime(new Date());
//修改
itemService.updateByPrimaryKeyWithBLOBs(items);;
return "redirect:/toEdit.action?id=" + items.getId(); //重定向到修改页面,查看是否上传成功
}
四、json数据交互
知识点:
1)@RequestBody
作用:用于读取http请求的内容(字符串),
细节:通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上。
本例应用:
@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象进行绑定
2)@ResponseBody
作用:用于将Controller的方法返回给对象,
细节:通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
本例应用:@ResponseBody注解实现将Controller方法返回java对象转换为json响应给客户端。
实现步骤:
1)导入jar包、
2)引入js、ajax编写
3)Controller编写
1)导入jar包
2)引入js、ajax编写
ajax编写
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
$(function(){
//定义Json格式字符串
var params = '{"id": 1,"name": "测试商品","price": 99.9,"detail": "测试商品描述","pic": "123456.jpg"}';
$.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>
3)Controller编写**
//测试json格式的数据交互
@RequestMapping(value = "/json.action")
public @ResponseBody
Items json(@RequestBody Items item){
return item; //返回对象
}
五、拦截器
SpringMVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
三种控制时机
1)preHandler:进入方法前
2)postHandler:进入方法后
3)afterCompletion:视图渲染后
多个拦截器调用时序
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
实现步骤:
1)创建拦截器类,实现HandlerInterceptor接口,编写拦截方法
2)springmvc.xml中配置拦截器
1)创建拦截器类,实现HandlerInterceptor接口,编写拦截方法
/**
* 拦截器:实现接口 HandlerInterceptor
* @author 一万年行不行
*
*/
public class Interceptor2 implements HandlerInterceptor {
// Controller执行前调用此方法
// 返回true表示继续执行,返回false中止执行
// 这里可以加入登录校验、权限拦截等
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("方法前");
// 设置为true,测试使用
return true;
}
// controller执行后但未返回视图前调用此方法
// 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("方法后");
}
// controller执行后且视图返回后调用此方法
// 这里可得到执行controller时的异常信息
// 这里可记录操作日志
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("渲染后");
}
}
2)springmvc.xml中配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置拦截器1 -->
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 设置被拦截的path -->
<bean class="springmvc.interceptor.Interceptor1"/> <!-- 拦截进入的类 -->
</mvc:interceptor>
<!-- 配置拦截器2 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="springmvc.interceptor.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
拦截器应用:拦截是否登陆
流程:
a) 拦截用户请求,判断用户是否登录(登录请求不能拦截)
b) 如果用户已经登录。放行
c) 如果用户未登录,跳转到登录页面。
1)创建拦截器类
/**
* 拦截器:实现接口 HandlerInterceptor
*
* 是/否放行--- true/false
*
* @author 一万年行不行
*
*/
public class Interceptor1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
System.out.println("方法前1111");
//得到当前URI 判断用户是否在登陆页面
String requestURI = request.getRequestURI();
if (!requestURI.contains("/login")) { //用户不在login页面,判断是否登陆
String username = (String) request.getSession().getAttribute("USER_SESSION");
if(username == null){ //用户为登陆,跳转到登陆界面
response.sendRedirect(request.getContextPath() + "/login.action");
return false; //不放行
}
}
return true; //用户在登陆界面,直接放行
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("方法后11111");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("页面渲染后11111");
}
}
2)springmvc.xml中配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<!-- 配置拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 设置被拦截的path -->
<bean class="springmvc.interceptor.Interceptor1"/> <!-- 拦截进入的类 -->
</mvc:interceptor>
</mvc:interceptors>
3)Controller编写
//去登陆界面 //筛选get请求
@RequestMapping(value="/login.action",method = RequestMethod.GET)
public String login(){
return "login";
}
//提交登陆 //筛选post请求
@RequestMapping(value="/login.action",method = RequestMethod.POST)
public String login(String username,HttpSession session){
session.setAttribute("USER_SESSION", username); //将用户名设置进session
return "redirect:/itemList.action"; //重定向到列表页面
}