web拦截方式
springconfig.xml
<!--不拦截静态资源-->
<mvc:default-servlet-handler/>
/拦截所有不包含jsp ,包括今天资源,css,js,图片
/*拦截所有(真拦截)
web.xml
<!-- 配置SpringMVC前端控制器 --> <servlet> <servlet-name>spring_mvc_test</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springconfig.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>spring_mvc_test</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
@RequestMapping
通过@RequestMapping注解可以定义不同的处理器映射规则。
@RequestMapping(“”)作用
标注在方法上:控制器访问的uri;
标注在类上:区别是那个功能,控制器访问的uri前增加一层路径
URL路径映射
@RequestMapping(value="item")或@RequestMapping("/item") value的值是数组,可以将多个url映射到同一个方法 /** * 查询商品列表 * @return */ @RequestMapping(value = { "itemList", "itemListAll" }) public ModelAndView queryItemList() { // 查询商品数据 List<Item> list = this.itemService.queryItemList(); // 创建ModelAndView,设置逻辑视图名 ModelAndView mv = new ModelAndView("itemList"); // 把商品数据放到模型中 mv.addObject("itemList", list); return mv; }
添加在类上面
在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,可以使用此方法对url进行分类管理,如下图
此时需要进入queryItemList()方法的请求url为:
http://127.0.0.1:8080/springmvc-web2/item/itemList.action
或者
http://127.0.0.1:8080/springmvc-web2/item/itemListAll.action
请求方法限定
除了可以对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方法返回值
返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。
返回void
在Controller方法形参上可以定义request和response,使用request或response指定响应结果: 1、使用request转发页面,如下: request.getRequestDispatcher("页面路径").forward(request, response); request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response); 2、可以通过response页面重定向: response.sendRedirect("url") response.sendRedirect("/springmvc-web2/itemEdit.action"); 3、可以通过response指定响应结果,例如响应json数据如下: response.getWriter().print("{\"abc\":123}");
返回字符串
逻辑视图名
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。 //指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/itemList.jsp return "itemList";
Redirect重定向
Contrller方法返回字符串可以重定向到一个url地址 如下商品修改提交后重定向到商品编辑页面。 /** * 更新商品 * * @param item * @return */ @RequestMapping("updateItem") public String updateItemById(Item item) { // 更新商品 this.itemService.updateItemById(item); // 修改商品成功后,重定向到商品编辑页面 // 重定向后浏览器地址栏变更为重定向的地址, // 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失 // 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数 return "redirect:/itemEdit.action?itemId=" + item.getId(); }
forward转发
Controller方法执行后继续执行另一个Controller方法 如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中。 /** * 更新商品 * * @param item * @return */ @RequestMapping("updateItem") public String updateItemById(Item item) { // 更新商品 this.itemService.updateItemById(item); // 修改商品成功后,重定向到商品编辑页面 // 重定向后浏览器地址栏变更为重定向的地址, // 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失 // 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数 // return "redirect:/itemEdit.action?itemId=" + item.getId(); // 修改商品成功后,继续执行另一个方法 // 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址, // 转发并没有执行新的request和response,所以之前的请求参数都存在 return "forward:/itemEdit.action"; } //结果转发到editItem.action,request可以带过去 return "forward: /itemEdit.action";
需要修改之前编写的根据id查询商品方法
因为请求进行修改商品时,请求参数里面只有id属性,没有itemId属性
修改,如下图::
文件上传
配置虚拟目录
在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:
<Context docBase="D:\develop\upload\temp" path="/pic" reloadable="false"/>
访问http://localhost:8080/pic即可访问D:\develop\upload\temp下的图片。
加入jar包
<!--文件上传需要的包start--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!--文件上传需要的包end-->
配置上传解析器
在springmvc.xml中配置文件上传解析器 <!-- 文件上传,id必须设置为multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置文件上传大小 --> <property name="maxUploadSize" value="5000000" /> </bean>
上传
在更新商品方法中添加图片上传逻辑 /** * 更新商品 * * @param item * @return * @throws Exception */ @RequestMapping("updateItem") 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数据交互
@RequestBody
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上。
传统的请求参数: itemEdit.action?id=1&name=zhangsan&age=12 现在的请求参数: 使用POST请求,在请求体里面加入json数据 { "id": 1, "name": "测试商品", "price": 99.9, "detail": "测试商品描述", "pic": "123456.jpg" } 本例子应用: @RequestBody注解实现接收http请求的json数据,将json数据转换为java对象进行绑定
@ResponseBody
作用:
@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
本例子应用:
@ResponseBody注解实现将Controller方法返回java对象转换为json响应给客户端。
加入jar包
<!--json start --> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.4.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.4.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.4.0</version> </dependency> <!--json end-->
查询图书列表, 返回json
@ResponseBody @RequestMapping(value = { "/jsonlist" }) public List<Book> selectBookList1() { // 查询所有记录 List<Book> list = service.selectBookList(); return list; }
RESTful支持
什么是restful
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。
传统方式操作资源
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上获取参数
使用RESTful风格开发的接口,根据id查询商品,接口地址是: http://127.0.0.1/item/1 我们需要从url上获取商品id,步骤如下: 1. 使用注解@RequestMapping("item/{id}")声明请求的url {xxx}叫做占位符,请求的URL可以是“item /1”或“item/2” 2. 使用(@PathVariable() Integer id)获取url上的数据 /** * 使用RESTful风格开发接口,实现根据id查询商品 * * @param id * @return */ @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,用于对处理器进行预处理和后处理。
拦截器定义
实现HandlerInterceptor接口,如下: 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; } }
拦截器配置
上面定义的拦截器再复制一份HandlerInterceptor2,注意新的拦截器修改代码: System.out.println("HandlerInterceptor2....preHandle"); 在springmvc.xml中配置拦截器 <!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 所有的请求都进入拦截器 --> <mvc:mapping path="/**" /> <!-- 配置具体的拦截器 --> <bean class="com.jy.interceptor.HandlerInterceptor1" /> </mvc:interceptor> <mvc:interceptor> <!-- 所有的请求都进入拦截器 --> <mvc:mapping path="/**" /> <!-- 配置具体的拦截器 --> <bean class="com.jy.interceptor.HandlerInterceptor2" /> </mvc:interceptor> </mvc:interceptors>