请求限制
一些情况下我们可能需要对请求进行限制,比如仅允许 POST,GET 等...
RequestMapping 注解中提供了多个参数用于添加请求的限制条件
案例:
@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 还提供了集合路径和方法限制的注解,包括常见的请求方法:
PostMapping
GetMapping
DeleteMapping
PutMapping
例:
@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")
@ResponseBody
public List<Course> getCourseList() { //获取所有课程
return courseService.selectCourses();
}
@RequestMapping("/getCourse")
@ResponseBody
public 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 两个注解合并在一起;
例:
@RestController
public class CourseController {.....}
复制代码
接受 json 数据
SpringMVC 可以帮助我们将 json 参数反序列化到指定的实体类型,List 或 Map;
需要强调的是: 客户端必须指定 ContenType 为 application/json
@RequestMapping("/addCourse")
@ResponseBody
public Course addCourse(@RequestBody Course course) {//接收json参数映射到实体
course.setName("接收json成功");//修改name再把数据发回去 以便查看效果
return course;
}
@RequestMapping("/addCourses")
@ResponseBody
public List<Course> addCourse(@RequestBody List<Course> courses) {//接收json数组参数映射到list
return courses;
}
@RequestMapping("/addData")
@ResponseBody
public Map<String,String> addData(@RequestBody Map<String,String> data) {//接收json数据映射到map
return data;
}
@RequestMapping("/addInfo")
@ResponseBody
public 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.编写异常处理器
@Component
public 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 来进行配置
看完三件事❤️
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
关注公众号 『 java 烂猪皮 』,不定期分享原创知识。
同时可以期待后续文章 ing🚀
关注后回复【666】扫码即可获取学习资料包
注:本文来源于网络,非作者原创
评论