Spring-MVC-2

109 阅读2分钟

请求转发

默认转发方式

//默认转发方式
//url http:localhost:8080/forward1
@RequestMapping("/forward1")
public String forward1(){
    return "success";
}

forward方式

如果想自定义返回地址,不拼接前后缀,可以使用forward方式

@RequestMapping("/forward2")
public String forward2(){
    return "forward:/login.jsp";
}

原生API方式

//原生API方式
@RequestMapping("/forward3")
public void forward3(HttpServletRequest request,HttpServletResponse response) {
    try {
        request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
    } catch (ServletException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

转发传递参数

request传递参数

//request传递参数
@RequestMapping("/forward4")
public String forward4(HttpServletRequest request){
    request.setAttribute("name","hawk");
    return "success";
}

Model传递参数

@RequestMapping("/forward5")
public String forward5(Model model){
    model.addAttribute("name","dover");
    return "success";
}

ModelAndView传递参数

这种方式只能转发到页面,并且会拼接视图解析器的前后缀,不能转发到其他handler

@RequestMapping("/forward6")
public ModelAndView forward6(ModelAndView modelAndView){
    modelAndView.addObject("name","hawk");
    modelAndView.setViewName("success");
    return modelAndView;
}

请求重定向

redirect方式

@RequestMapping("/redirect1")
public String redirect1(){
    return "redirect:/login.jsp";
}

原生API方式

public void redirect2(HttpServletResponse response){
    try {
        response.sendRedirect("/login.jsp");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

重定向访问WEB-INF下资源

重定向不能直接访问WEB-INF下的资源,但是可以通过重定向到另一个请求,通过行的请求转发到WEB-INF下的资源

@RequestMapping("/redirect3")
public String redirect3(){
    return "redirect:/forward1";
}

请求响应JSON数据

  • @RequestBody

    用于接收前端传递的请求体中的json数据,并可以自动转换封装进指定的对象中。

  • @ResponseBody

    将controller方法返回的数据通过转换器转换为指定的格式(通常为json)之后,再进行响应。 后台接收和响应JSON数据

@RequestMapping("/select")
public List<User> select(@RequestBody User user){
    System.out.println(user);
    List<User> list = new ArrayList<>();
    list.add(new User(1,"dover","123","♀"));
    list.add(new User(2,"hawk","123","♂"));
    return list;
}

RESTful风格

REST(Representational State Transfer)中文意思是表述(表征)性状态转移。他是一种设计风格。

RESTful很大一个特点是URL中没有动词,通过URL+HTTP请求类型确定要执行的操作。

  • HTTP请求方式

    • GET:查询
    • POST:新增(更新)
    • PUT:更新
    • DELETE: 删除

RESTFul注解

  • @RestController = @Controller + @ResponseBody
  • @PostMapping = @RequestMapping(method = RequestMethod.POST)
  • @GetMapping = @RequestMapping(method = RequestMethod.GET)
  • @PutMapping = @RequestMapping(method = RequestMethod.PUT)
  • @DeleteMapping = @RequestMapping(method = RequestMethod.DELETE)

RESTful风格 - 保存

//@RequestMapping(value = "/user",method = RequestMethod.POST)
@PostMapping("user")
public String save(@RequestBody User user){
    System.out.println(user);
    return "保存成功";
}

RESTful风格 - 修改

//@RequestMapping(value = "/user",method = RequestMethod.PUT)
@PutMapping("/user")
public String update(@RequestBody User user){
    System.out.println(user);
    return "修改成功";
}

RESTful风格 - 查询(id)

//@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
@GetMapping("/user/{id}")
public User findById(@PathVariable Integer id){
    System.out.println(id);
    return new User(1,"dover","123","女");
}

RESTful风格 - 删除(id)

//@RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
@DeleteMapping("/user/{id}")
public String delete(@PathVariable("id") Integer id){
    System.out.println(id);
    return "删除成功";
}

统一异常处理

自定义异常类,实现HandlerExceptionResolver接口(Object o 封装的本次请求controller和method相关信息,Exception e 异常相关信息)

  • 记录异常信息
  • 返回友好提示页面
@Component
public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                         HttpServletResponse httpServletResponse,
                                         Object o, Exception e) {
        //异常位置
        StackTraceElement[] stackTrace = e.getStackTrace();
        System.out.println(Arrays.toString(stackTrace));
        //异常描述
        System.out.println(e.getMessage());
        //异常类型
        System.out.println(e.getClass());

        //友好提示返回
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("forward:/WEB-INF/error/500.jpg");
        return modelAndView;
    }
}

@ControllerAdvice方式可以对不同类型的异常进行个性处理

该方式不需要实现接口,类中自定义方法即可,在方法上通过注解@ExceptionHandler标注要处理的异常。

@ControllerAdvice
public class MyExceptionHandler2 {

    @ExceptionHandler(ArithmeticException.class)
    public String ArithmeticException(ArithmeticException a) {
        System.out.println("算数异常");
        //位置
        System.out.println(a.getStackTrace()[0]);
        //信息
        System.out.println(a.getMessage());

        //友好提示
        return "forward:/WEB-INF/error/500.jpg";
    }
}

拦截器

拦截器是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 true;
    }

    @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("终执行");
    }
}

配置拦截器

在sping-mvc.xml中配置拦截器

<mvc:interceptors>
    <mvc:interceptor>
        <!--拦截所有请求-->
        <mvc:mapping path="/**"/>
        <!--不拦截的请求-->
        <mvc:exclude-mapping path="/funB"/>
        <!--拦截器对象-->
        <bean class="com.eponine.mvc.interceptor.MyInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

拦截器链

可以同时使用多个拦截器形成一条拦截器链。

开发步骤和单个拦截器是一样的,只不过注册的时候注册多个,注册的顺序就代表拦截器执行的顺序。

符合path拦截规则的拦截器会被执行。

放行的拦截器,afterCompletion()方法一定会执行