请求限制

一些情况下我们可能需要对请求进行限制,比如仅允许POST,GET等...

RequestMapping注解中提供了多个参数用于添加请求的限制条件

  • value 请求地址
  • path 请求地址
  • method 请求方法
  • headers 请求头中必须包含指定字段
  • params 必须包含某个请求参数
  • consumes 接受的数据媒体类型 (与请求中的contentType匹配才处理)
  • produce 返回的媒体类型 (与请求中的accept匹配才处理)

案例:

@RequestMapping(value = "/editCourse",method = RequestMethod.POST,headers = {"id"},params = {"name"},consumes = {"text/plain"},produces = {"text/html"})//含义:url为/editCourse 请求方法为POST hander必须包含id字段  参数必须包含name 只接受text/plain类型数据 返回数据类型为text/html

为了简化书写,MVC还提供了集合路径和方法限制的注解,包括常见的请求方法:

PostMappingGetMappingDeleteMappingPutMapping例:@PostMapping("/editCourse")

handler返回值

handler方法可以是三种类型的返回值,用于不同场景

ModelAndView

返回值为视图和数据的包装类型,用于返回逻辑视图名称和视图需要展示的数据

等同于在Request中添加了属性,然后进行了请求转发

例:

@RequestMapping("/test")public ModelAndView test() {    ModelAndView modelAndView = new ModelAndView();    modelAndView.setViewName("index.jsp");    modelAndView.addObject("msg", "hello ssm!");    return modelAndView;}

void

表示handler不返回任何数据,用于当需要直接操作response完成响应的场景

例:

@RequestMapping("/test2")public void test2(String name,HttpServletResponse response) throws IOException {    response.getWriter().println(name.toUpperCase());}

String

返回一个字符串类型的值,返回的内容可以是视图名称也可以是其他请求地址

其背后采用的是请求转发的方式

例:

@RequestMapping("/test3")public String test3(Model model) {    model.addAttribute("msg","hello XXX");    return "index.jsp";}@RequestMapping("/test4")public String test4() {    return "/test";}

转发和重定向:

也可指定对目标地址的请求是通过重定向或请求转发;

例:

@RequestMapping("/test5")public String test5() {    return "forward:/index.jsp";}@RequestMapping("/test6")public String test6() {    return "redirect:/index.jsp";}

当然了 默认就是forward所以可以省略;

json交互

当下,大多数公司都会有移动端App,当我们的后台服务需要为App提供接口时,就不得不使用到json数据了,当然还有前后端分离项目中前端和后台同样采用json来交换数据;

在开始前,需要导入jackson依赖,用于实现json的序列化与反序列化;

<dependency>  <groupId>com.fasterxml.jackson.core</groupId>  <artifactId>jackson-databind</artifactId>  <version>2.9.9</version></dependency>

返回json数据

@ResponseBody注解用于标注一个handler方法返回的是json数据,同时方法的返回值将作为返回给前台的数据;

例:

@RequestMapping("/getCourseList")@ResponseBodypublic List<Course> getCourseList() {  //获取所有课程    return courseService.selectCourses();}@RequestMapping("/getCourse")@ResponseBodypublic Course getCourse(Integer id) {// 根据id获取一个课程    return courseService.selectByID(id);}

ResponseBody会将响应的ContentType设置为application/json, 然后调用jackson的toJsonString将返回值转为json字符串,最后返回给客户端;

@RestController

如果需要为每一个方法添加ResponseBody的话,就显得非常麻烦,SpringMVC提供了@RestController注解,表示这是一个所有handler返回值全都是json的Controller,相当于把Controller和ResponseBody两个注解合并在一起;

例:

@RestControllerpublic class CourseController {.....}

接受json数据

SpringMVC可以帮助我们将json参数反序列化到指定的实体类型,List或Map;

需要强调的是: 客户端必须指定ContenType为application/json

@RequestMapping("/addCourse")@ResponseBodypublic Course addCourse(@RequestBody Course course) {//接收json参数映射到实体    course.setName("接收json成功");//修改name再把数据发回去 以便查看效果    return course;}@RequestMapping("/addCourses")@ResponseBodypublic List<Course> addCourse(@RequestBody List<Course> courses) {//接收json数组参数映射到list    return courses;}@RequestMapping("/addData")@ResponseBodypublic Map<String,String> addData(@RequestBody Map<String,String> data) {//接收json数据映射到map    return data;}@RequestMapping("/addInfo")@ResponseBodypublic String addInfo(@RequestBody String data) {//接收json数据不做任何转换    return data;}

当客户端传递的json比较复杂时可能无法直接转换到某个实体类型,这是我们可以通过Map来接收,或直接获取原始的json字符串自己处理; 就像上面的 addData 和 addInfo 一样

Handler拦截器

顾名思义Handler拦截器可对Handler方法进行拦截,控制Handler方法是否执行,与Servlet的过滤器非常相似

但是要注意:

​ Servlet的filter的执行时机是在SpringMVC之前,过滤的目标对象是请求;

​ 而Handler拦截器,拦截的目标对象是Handler方法

Handler拦截器可以方便的实现,登录状态验证,操作权限验证等操作;

使用案例:

1.编写拦截器

public class MyInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        //在执行handler前调用   返回值将决定是否继续执行请求        System.out.println("preHandle");        return true;    }    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {        //handler被真正执行了,已经拿到了handler的返回结果  但是DispatcherServlet还没有发送给前台        System.out.println("postHandle");    }    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {        //DispatcherServlet将视图发送给前台后的回调 (无论handler是否执行 一定有响应发给前台)        System.out.println("afterCompletion");              //Handler中出现的任何异常也会传给该方法,可以在这里进行处理          if (ex != null){            System.out.println("handler中出现异常了....");        }    }}

2.配置拦截器

<mvc:interceptors>    <mvc:interceptor>        <mvc:mapping path="/**"/>        <bean class="com.kkb.interceptor.MyInterceptor"/>    </mvc:interceptor></mvc:interceptors><!--* path用于指定拦截器拦截的url只有handler的url与之匹配才会被拦截  /** 表示拦截所有请求* interceptors中可配置多个interceptor -->

3.执行顺序

拦截器的执行顺序由配置顺序来决定,拦截器也和filter一样是一个链条的形式

在请求处理完成时,会按照相反的顺序通知interceptor(即执行afterComplation),前提是这个拦截器正常放行了请求(preHandler中返回了true),否则不会收到通知;

异常处理

一个完整的系统必然要考虑异常情况的处理,SpringMVC提供了一种非常方便的处理方法,只需要实现HandlerExceptionResolver接口,并注册Bean至容器中即可

1.编写异常处理器

@Componentpublic class MyExceptionHandler implements HandlerExceptionResolver {    @Override    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {        ModelAndView modelAndView = new ModelAndView();        modelAndView.setViewName("error.jsp");        modelAndView.addObject("exobj",ex);        return modelAndView;    }}

可以看到在处理方法的返回值为ModelAndView,我们需要在其中添加错误页面的名称和错误信息;

2.注册到容器中

​ 可以直接添加Component注解或是,在配置文件中注册

<bean class="com.kkb.exceptionhandler.MyExceptionHandler"/>

强调:无论是拦截器还是异常处理器都是针对handler而不是所有请求,举个例子如果请求本身就是错误的如404,是无法被异常Handler异常处理器处理的,仍需要到web.xml来进行配置

最新文章

  1. jQuery1.9之后使用on()绑定 动态生成元素的 事件无效
  2. Javascript中闭包问题(转载)
  3. 求空间内两条直线的最近距离以及最近点的坐标(C++)
  4. Top (参数)
  5. 选择使用c语言编写的phalcon框架
  6. memcpy、memmove、memset
  7. wpf linq数据库无法插入
  8. cmd命令行设置环境变量
  9. asp.net web api 2.2 基础框架(带例子)
  10. windows7 安装TensorFlow
  11. HTML学习笔记 CSS背景样式案例 第六节 (原创) 参考使用表
  12. golang 调用windows API 中文的处理
  13. 以API方式调用C# dll,使用OneNote2013 sp1实现OCR识别本地图片
  14. “Hello, my first blog”------第一篇博客的仪式感
  15. 2017-10-22&mdash;发光二极管
  16. nginx-高并发配置 第七章
  17. E. Train Hard, Win Easy
  18. BOM心得
  19. Java中mongodb使用and和or的复合查询
  20. c++读取文件到vector

热门文章

  1. python-内置函数-文件操作
  2. MySQL关于日期为零值的处理
  3. C#读写内置类型的数据时是否原子操作
  4. Docker镜像讲解
  5. 《前端运维》一、Linux基础--02用户与权限
  6. 《Ray Tracing in One Weekend》阅读笔记 - 9、Metal(金属)
  7. mysql order by 多样依照排序
  8. 分布式日志传输系统Databus(一)--系统介绍
  9. Jmeter 设置中文
  10. 桌面支持qt版本是多少检查