springMVC进阶
1.高级参数绑定(划重点)
1>数组绑定:可以在controller的方法(Integer[] ids),也可以在QueryVo中有参数Integer ids[],前台页面复选框参数name="ids"
@RequestMapping(value = "/item/getIds.action")
public ModelAndView getIds(QueryVo vo){
2>List集合绑定:在QueryVo中有参数List<Items> itemList
@RequestMapping(value = "/item/getList.action")
public ModelAndView getList(QueryVo vo){
前台数据格式:
<td><input type="text" name="itemsList[0].name" value="${item.name }"></td>
<td><input type="text" name="itemsList[0].price" value="${item.price }"></td>
c:forEach格式:与前一种是相同的
<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>
[email protected]解析
通过@RequestMapping注解可以定义不同的处理器映射规则:
value的值是数组,可以将多个url映射到同一个方法
@RequestMapping(value = { "itemList", "itemListAll" })
在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头
@RequestMapping("/item")
public class ItemController {//访问路径就变成了/item/itemList
除了可以对url进行设置,还可以限定请求进来的方法
@RequestMapping(value = "/item/itemlist.action",method={RequestMethod.GET,RequestMethod.POST})
@RequestMapping(value = "/item/itemlist.action",method = RequestMethod.POST)
3.Contrller方法返回值(划重点)
1>返回ModelAndView:controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。
//创建ModelAndView对象
ModelAndView mav = new ModelAndView();
//传递参数:request.setAttr....
List<Items> list = new ArrayList<>();
mav.addObject("itemList", list);
//设置跳转路径地址
mav.setViewName("itemList");
return mav;
2>返回Strng(常用)
跳转到jsp页面:
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/itemList.jsp
return "itemList";
重定向到一个action:重定向后浏览器地址栏变更为重定向的地址,request.getRequestDispatcher("/itemEdit.action").forward(request, response);
//相当于执行了新的request和response如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数
return "redirect:/itemEdit.action?itemId=" + item.getId();
内部转发到一个action:转发后浏览器地址栏还是原来的请求地址,response.sendRedirect("/itemEdit.action");
// 使用转发的方式实现。转发并没有执行新的request和response,所以之前的请求参数都存在
return "forward:/itemEdit.action";
3>返回void(ajax)
通过方法绑定形参reponse来返回json字符串
4.异常处理器
系统中异常包括两类:预期异常和运行时异常RuntimeException
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理
2>自定义异常类
public class MyException extends Exception {
// 异常信息
private String message;
get/set,两个构造方法
3>自定义异常处理器:实现springmvc的异常接口
public class CustomHandleException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object object,
Exception e) {
ModelAndView mav = new ModelAndView();
// 定义异常信息
String msg;
if(e instanceof MyException){
MyException me = (MyException)e;
mav.addObject("error", me.getMessage());
}else{
mav.addObject("error", "未知异常");
}
mav.setViewName("error");//跳转到erro的jsp页面
return mav;
}
4>springmvcxml中异常处理器配置
<!-- 异常处理类 -->
<bean class="com.imwj.exception.CustomHandleException"/>
5>erro.jsp
${erro}
6>测试:controller添加异常
/* int i = 1/0;//未知异常
if(null == null){//已知异常
throw new MyException("已知异常");
}
*/
5.上传图片(划重点)
1>配置虚拟目录:这样可以在tomcat上面访问到c:\upload\image里面的图片(地址:http://localhost:8080/pic/文件名加后缀)
2>加入springmvc对文件上传的jar包
commons-fileupload-1.2.2.jar、commons-io-2.4.jar
3>在springmvc.xml中配置文件上传解析器
<!-- 文件上传,id必须设置为multipartResolver -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件上传大小B 1m=1*1024*1024-->
<property name="maxUploadSize" value="5000000" />
</bean>
4>jsp页面修改action表单提交内容
<!-- 上传图片是需要指定属性 enctype="multipart/form-data" -->
<!-- <form id="itemForm" action="" method="post" enctype="multipart/form-data"> -->
5>controller中的方法
//文件上传
@RequestMapping(value = "updateitem.action")
public String updateitem(QueryVo vo,MultipartFile pictureFile) throws Exception{
//保存图片到 F:upload,pictureFile是jsp页面中input的name="pictureFile"
//文件重命名为uuid格式
String name = UUID.randomUUID().toString().replaceAll("-", "");
//文件后缀名:jpg
String ext = FilenameUtils.getExtension(pictureFile.getOriginalFilename());
//保存文件到指定位置
pictureFile.transferTo(new File("F:\\upload\\" + name + "." + ext));
vo.getItems().setPic(name + "." + ext);
//修改
itemService.updateById(vo.getItems());
return "redirect:/itemEdit.action?id="+vo.getItems().getId();
}
6.json数据交互(划重点)
接受json数据:@RequestBody
返回json数据:@@ResponseBody
将接收到的josn数据封装到Items中,然后再返回一个json字符串(再将Items转成json字符串)
注意:前台的ajax请求方法的发送数据格式必须指定为json,还需要导入json支持jar包
$(function(){
var params = '{"id": 1,"name": "测试商品","price": 99.9,"detail": "测试商品描述","pic": "123456.jpg"}';
$.ajax({
url : "${pageContext.request.contextPath }/item/json.action",
data : params,
contentType : "application/json;charset=UTF-8",//发送数据的格式
type : "post",
dataType : "json",//回调
success : function(data){
alert(data.name);
}
});
});
@RequestMapping(value = "/item/json.action")
public @ResponseBody Items json(@RequestBody Items items){
return items;
}
7.restful风格
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。分别对应 添加、 删除、修改、查询。
注意:restful还将删除喝查询所需的id放到了请求路径中:http://127.0.0.1/item/1
8.拦截器(划重点)
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。springmvc已经给我提供好了拦截器接口HandlerInterceptor我们只需实现此接口,并完善之中的三个方法即可
1>实现拦截器接口
public class Interceptor2 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
System.out.println("方法前2");
return true;
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("方法后2");
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("页面渲染后2");
}
}
2>springmvc.xml中配置拦截器
<!-- 拦截器:可以配置多个拦截器 -->
<mvc:interceptors>
<!-- 自定义拦截器类:实现HandlerInterceptor接口 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.imwj.Interceptor.Interceptor1"></bean>
</mvc:interceptor>
<!-- 自定义拦截器类:实现HandlerInterceptor接口
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.imwj.Interceptor.Interceptor2"></bean>
</mvc:interceptor> -->
</mvc:interceptors>
3>拦截器规则:
preHandle(方法前):按拦截器定义顺序调用,有返回方法true是放行,false是不放行
postHandler(方法后):按拦截器定义逆序调用
afterCompletion(页面渲染后):按拦截器定义逆序调用
postHandler:在拦截器链内所有拦截器返成功调用
afterCompletion:只有preHandle返回true才调用
实现用户登陆拦截器案例:
1>拦截器类:
/**
* 先判断访问路径是否包含login,包含了则放行,没有包含就跳转到登陆页面
* 再判断用户是否登陆,如果没有登陆:重定向到登陆页面(return false不放行),如果登陆了(return true放行)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
System.err.println("方法前1");
// URL http://localhost:8080/springmvc-mybatis/login.action
//URI /login.action
String uri = request.getRequestURI();
if(!uri.contains("/login")){
String username = (String) request.getSession().getAttribute("USER_NAME");
if(null == username){
response.sendRedirect(request.getContextPath()+"/login.action");
return false;
}
}
return true;
}
2.springmvc中的配置
<!-- 拦截器:可以配置多个拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.imwj.Interceptor.Interceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
3.controller类
//去登陆页面
@RequestMapping(value = "/login.action",method=RequestMethod.GET)
public String toLogin(){
return "login";
}
//用户登陆操作
@RequestMapping(value = "/login.action",method=RequestMethod.POST)
public String login(String username,HttpSession session){
session.setAttribute("USER_NAME", username);
return "forward:/item/itemlist.action";
}