一.RequestMapping
- URL路径映射:置于方法上,可多个URL映射同一个方法,格式:@RequestMapping(value="item")或@RequestMapping("/item")
- 窄化路径:置于类上,限制此类下所有的URL以其开头
- 请求方法限定:限定请求进来的方法,如下:
限定GET方法 @RequestMapping(method = RequestMethod.GET) 如果通过POST访问则报错: HTTP Status 405 - Request method 'POST' not supported 例如: @RequestMapping(value = "itemList",method = RequestMethod.POST) 限定POST方法 @RequestMapping(method = RequestMethod.POST) 如果通过GET访问则报错: HTTP Status 405 - Request method 'GET' not supported GET和POST都可以 @RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
二.Controller方法的返回值
1.1. 返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。
携带数据+返回视图路径给解析器
public ModelAndView itemList(){ //从Mysql中查询 List<Items> list = itemService.selectItemsList(); ModelAndView mav = new ModelAndView(); //数据 mav.addObject("itemList", list); mav.setViewName("itemList"); return mav; }
1.2.返回字符串(返回视图路径或者请求转发与重定向)
使用model或者modeltype携带数据,返回路径
转发或者重定向
修改商品成功后,重定向到商品编辑页面 // 重定向后浏览器地址栏变更为重定向的地址, // 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失 // 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数 return "redirect:/itemEdit.action?itemId=" + item.getId(); 修改商品成功后,继续执行另一个方法 // 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址, // 转发并没有执行新的request和response,所以之前的请求参数都存在 return "forward:/itemEdit.action";
优点:数据与视图分类,符合解耦合原则
1.3.无返回值:void
model携带数据,不返回视图----->应用:ajax界面,异步请求无需跳转视图
三.异常处理
异常分为两类:预期异常和运行时异常。可以在springmvc中设置异常处理器进行处理。使用方法:
1.自定义异常
2.设置异常处理器
public class CustomHandleException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) {
// 定义异常信息
String msg;
// 判断异常类型
if (exception instanceof MyException) {
// 如果是自定义异常,读取异常信息
BusinessException me = (BusinessException)e;
msg = me.getMessage();
} else {
// 如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
Writer out = new StringWriter();
PrintWriter s = new PrintWriter(out);
exception.printStackTrace(s);
msg = out.toString();
}
// 把错误信息发给相关人员,邮件,短信等方式
// TODO
// 返回错误页面,给用户友好页面显示错误信息
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", msg);
modelAndView.setViewName("error");
return modelAndView;
}
}
3.在springmvc.xml中配置异常处理器
<bean id="customHandleException" class="cn.itcast.ssm.exception.CustomHandleException"/>
4.写错误页面
5.在controller层配置抛出异常的方法
/** * 查询商品列表*/ @RequestMapping(value = { "itemList", "itemListAll" }) public ModelAndView queryItemList() throws Exception { // 自定义异常 if (true) { throw new MyException("自定义异常出现了~"); } // 运行时异常 int a = 1 / 0; // 查询商品数据 List<Item> list = this.itemService.queryItemList(); // 创建ModelAndView,设置逻辑视图名 ModelAndView mv = new ModelAndView("itemList"); // 把商品数据放到模型中 mv.addObject("itemList", list); return mv; }
四.上传图片
实现在页面上上传图片到数据库的功能
1.导包
2.jsp页面修改
3.springmvc.xml配置解析器(代码的id不可改动)
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置文件上传大小 --> <property name="maxUploadSize" value="5000000" /> </bean>
4.修改控制器
@RequestMapping("updateItem")
//接口名必须与input name一致 public String updateItemById(Item item, MultipartFile pictureFile) throws Exception { // 图片上传 // 设置图片名称,不能重复,可以使用uuid String picName = UUID.randomUUID().toString(); // 获取文件名 String oriName = pictureFile.getOriginalFilename(); // 获取图片后缀 String extName = oriName.substring(oriName.lastIndexOf(".")); // 开始上传 pictureFile.transferTo(new File("C:/upload/image/" + picName + extName)); // 设置图片名到商品中 item.setPic(picName + extName); // --------------------------------------------- // 更新商品 this.itemService.updateItemById(item); return "forward:/itemEdit.action"; }
五.json类型交互
在控制器中添加
/** * 测试json的交互 * @param item * @return */ @RequestMapping("testJson") public @ResponseBody
Item testJson(@RequestBody Item item) { return item; }
//如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面
六.RESTful支持
Restful就是一个资源定位及资源操作的风格。
传统方式操作资源
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTful操作资源
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
我们需要从url上获取商品id,步骤如下:
1. 使用注解@RequestMapping("item/{id}")声明请求的url
{xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”
2. 使用(@PathVariable() Integer id)获取url上的数据
/** * 使用RESTful风格开发接口,实现根据id查询商品 */ @RequestMapping("item/{id}") @ResponseBody public Item queryItemById(@PathVariable() Integer id) { Item item = this.itemService.queryItemById(id); return item; }
如果@RequestMapping中表示为"item/{id}",id和形参名称一致,@PathVariable不用指定名称。如果不一致,例如"item/{ItemId}"则需要指定名称@PathVariable("itemId")。
http://127.0.0.1/item/123?id=1
注意两个区别
1. @PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)
2. 如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,目前返回的json数据。如果不加,就走视图解析器,返回页面
七.拦截器
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1.开发拦截器
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 arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception { System.out.println("HandlerInterceptor1....postHandle"); } // Controller执行前调用此方法 // 返回true表示继续执行,返回false中止执行 方法前 // 这里可以加入登录校验、权限拦截等 @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {System.out.println("HandlerInterceptor1....preHandle"); // 设置为true,测试使用 return true; } }
2配置拦截器
<!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 所有的请求都进入拦截器 --> <mvc:mapping path="/**" /> <!-- 配置具体的拦截器 --> <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1" /> </mvc:interceptor> <mvc:interceptor> <!-- 所有的请求都进入拦截器 --> <mvc:mapping path="/**" /> <!-- 配置具体的拦截器 --> <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2" /> </mvc:interceptor> </mvc:interceptors>
3.总结
- preHandle按拦截器定义顺序调用
- postHandler按拦截器定义逆序调用
- afterCompletion按拦截器定义逆序调用
- postHandler在拦截器链内所有拦截器返成功调用
- afterCompletion只有preHandle返回true才调用