SpringMVC(二)|SpringMVC(二) 页面转发、重定向、异步、Restful、异常处理、拦截器

SpringMVC(二) 页面转发、重定向、异步、Restful、异常处理、拦截器 页面跳转之转发 方式一:简单方式

  • 页面
普通转发

  • 后台
//页面转发方式1 @RequestMapping("/respServlet/forward1") public String forward1() { return "success"; }

方式二:使用forward转发
在返回中使用forward:url表示使用forward转发
  • 页面
forward转发

  • 后台
@RequestMapping("/forward2") public String forward2() { return "forward:/WEB-INF/fail.jsp"; }

方式三:使用Servlet原生API
通过SpringMVC前端控制器传递回来的参数可以接收到HttpServletRequest HttpServletResponse对象,使用ServletAPI可以进行转发
  • 页面
Servlet原生API

  • 后台
@RequestMapping("/forward3") public void forward3(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF/fail.jsp") .forward(request, response); }

转发携带数据
进行页面转发时,通常我们都会携带数据,SpringMVC中我们
  • 可以使用HttpServletRequest request
@RequestMapping("/forward4") public String forward4(HttpServletRequest request) { //使用Request传值 request.setAttribute("pageValue", "zs"); return "success"; }

  • 还可以使用Model 对象
@RequestMapping("/forward5") public String forward5(Model model) { //传递数据 model.addAttribute("pageValue", "ss"); return "success"; }

  • 还可以使用ModelAndView对象
@RequestMapping("/forward6") public ModelAndView forward6() { //构造ModelAndView对象 ModelAndView modelAndView = new ModelAndView(); //设置数据 modelAndView.addObject("pageValue", "fromModelAndView"); //设置逻辑视图 modelAndView.setViewName("success"); return modelAndView; }

页面跳转之重定向 使用redirect重定向
在Controller的返回中使用 redirect:url代表页面重定向
  • 页面
redirect重定向

  • 后台
@RequestMapping("/redirect1") public String redirect1() { return "redirect:/success.jsp"; }

使用Servlet原生API
  • 页面
使用Servlet原生API

  • 后台
@RequestMapping("/redirect2") public void redirect2(HttpServletRequest request, HttpServletResponse response) throws IOException { response.sendRedirect(request.getContextPath() + "/success.jsp"); }

使用重定向的方式进入外界无法访问的WEB-INF目录下
我们知道在javaWeb项目中,WEB-INF目录下的资源是无法通过外界访问的。但是可以通过服务器内部的请求转发访问到,现在我们想使用页面重定向技术进行访问WEB-INF目录下的资源。我们可以经过一次转发来达到通过重定向技术来访问WEB-INF目录下的资源
  • 页面
使用重定向-转发来访问WEB-INF下的资源

  • 【SpringMVC(二)|SpringMVC(二) 页面转发、重定向、异步、Restful、异常处理、拦截器】后台
    @RequestMapping("/redirect3") public String redirect3() { return "redirect:/respServlet/redirforwardtoSuccess"; } //转发方法 @RequestMapping("/redirforwardtoSuccess") public String redirectForward() { //转发到指定资源中return "forward:/WEB-INF/fail.jsp"; }

释放静态资源 当有静态资源需要加载时,比如js css 等,如果在url-pattern中配置的是/,代表除了.jsp请求不拦截,其他的所有请求都会拦截,包括一些静态文件,而拦截之后,SpringMVC又找不到对应的处理器来处理,因此我们需要释放静态资源,来让静态资源能够被正常加载
方式一

方式二 指定处理器映射器寻找不到对应的处理方法时,暂时不要报错,而是直接丢给外部的默认Servlet,也就是tomcat处理

Ajax+json实现异步交互 在SpringMVC中,前端发送Ajax异步请求,后端返回json响应。这个功能主要是通过两个注解@RequestBody和@ResponseBody实现的
SpringMVC默认使用MappingJackson2HttpMessageConverter对json数据进行转换,需要加入jackson的包
com.fasterxml.jackson.core jackson-databind 2.9.8

@RequestBody接收ajax请求
@RequestBody用于接收前端传递的请求体重的json数据,并可以自动转换封装进指定的对象中
  • 页面
    • 其中contentType代表请求参数类型
    • dataType代表响应数据类型

  • 封装实体类
public class User { private String name; private Integer age; @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; }public String getName() { return name; }public void setName(String name) { this.name = name; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; } }

  • 后台
@ResponseBody @RequestMapping("/ajaxReq") public List ajaxReq(@RequestBody List users) { System.out.println(""); users.stream().forEach(user -> System.out.println(user)); return users; }

@ResponseBody返回Json数据
@responseBody用于将controller方法返回的对象通过转换器转换为指定的格式(通常为json),
@ResponseBody @RequestMapping("/ajaxReqStr") public String ajaxReqStr(@RequestBody User user) { System.out.println(user); return "ok"; }

Spring还提供了一个@RestController 表示@Controller+@ResponseBody
Restful风格 定义 REST是一种软件架构风格,其强调HTTP应当以资源为中心
REST规范了HTTP请求动作,使用四个词语分别表示对资源的CRUD操作
也就是说Restful风格是通过方法的method类型来区分各种不同的业务
原来 Restful
保存 /saveUser post /usr
修改 /updateUser?id=1 Put /user/1
删除 /deleteUser?id=1 delete /user/1
查询所有 /findAllUser get /user
查询一个 /findUserById?id=1 get /user/1
保存
  • 页面
$("#save").click(function () { $.ajax({ type: "POST", url: "${pageContext.request.contextPath}/user", contentType: "application/json", dataType: "text", data: '{"name":"user1","age":11}', success: function (data) { alert(data); } }); })

  • 后台
注解@PostMapping 相当于@RequestMapping(value="https://www.it610.com/user" method="POST")
@PostMapping("/user") //@PostMapping 相当于@RequestMapping(value = "https://www.it610.com/user",method = RequestMethod.POST) @ResponseBody public String saveUser(@RequestBody User user) { System.out.println("收到的参数" + user); return "ok"; }

查询 get请求没有请求体,所以参数需要在请求地址中传递
  • 页面
$("#find").click(function () { $.ajax({ type: "GET", url: "${pageContext.request.contextPath}/user/name/user1/age/11", contentType: "application/json", dataType: "text", success: function (data) { alert(data); }}); });

  • 后台
@GetMapping("/user/name/{name}/age/{age}") @ResponseBody public String findUser(@PathVariable String name, @PathVariable String age) { System.out.println("接收到的参数" + name + age); return "ok"; }

异常处理机制 Spring框架,我们通常将异常抛到框架中,然后指定Spring的异常处理器来统一处理异常
方式一:自定义异常处理器
可以实现HandlerExceptionResolver接口,实现接口方法来自定义异常处理器
public class MyExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { return new ModelAndView("error", "err", e.getMessage()); } }

  • 加入扫描注解

方式二:@ControllerAdvice
使用注解@ControllerAdvice注解 @ExceptionHandler(Exception.class)
@ControllerAdvice public class MyExceptionHandler2 implements HandlerExceptionResolver { //声明处理哪些异常 @ExceptionHandler(Exception.class) @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { return new ModelAndView("WEB-INF/error", "err", e.getMessage()); } }

拦截器 什么是拦截器
拦截器是Spring提供的一种技术,类似于Servlet的Filter
拦截器的特点
  • 会在请求进入controller之前
  • 离开controller之后
  • 页面渲染完毕之后
自定义拦截器
自定义一个类实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("进入控制器之前"); //代表是否放心true 代表放行 false代表不放心 return false; }@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("离开控制器之后"); }@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("页面渲染完成之后"); } }

  • Springmvc中配置拦截规则

自定义拦截器链 开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链
开发步骤和单个拦截器是一样的,只不过注册多个拦截器的时候,注册的顺序代表拦截器的执行顺序
  • 定义第二个拦截器

拦截器和过滤器的区别
  • 拦截器属于SpringMVC框架,只有使用了SpringMVC框架才能使用拦截器,Servlet属于JavawebAPI 只要是JavaWeb工程都可以使用
  • 过滤器在url-pattern中配置了/之后,可以对所有资源拦截,拦截器配置了/ 之后 只会拦截访问的控制器方法,不会拦截静态资源
案例 使用拦截器完成用户访问的拦截
req:
  • 用户访问一个页面index.jsp
  • 如果用户已经登录,可直接进入index.jsp
  • 如果用户没有登录,跳转到登录页面
  • 页面
  • login.jsp
Title - 锐客网
用户名:
密码:

  • index.jsp
Title - 锐客网 登录完成 ${username}

  • 后台Controller
@Controller public class UserController { @RequestMapping("/login") public String login(String username, String password, HttpSession session) { if (username != null && !username.equals("")) { if (username.equals("admin")) { //登录成功 存入session session.setAttribute("loginName", username); return "forward:/index"; } } return "redirect:/login.jsp"; }@RequestMapping("/index") public String toIndex() { return "WEB-INF/index"; } }

  • 拦截器
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //判断是否已经存储 String loginName = (String) request.getSession().getAttribute("loginName"); if (loginName != null && !"".equals(loginName)) { //不为空 放行 return true; } else { //为空 重定向到登录页面 response.sendRedirect(request.getContextPath() + "/login.jsp"); return false; } }@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {} }

  • 拦截器配置

    推荐阅读