Spring MVC高级应用
Spring MVC高级应用
1. 拦截器使用
监听器、过滤器、拦截器对比
Servlet: 处理Request请求和Response响应
- 监听器
实现了javax.servlet.ServletContextListener接口的服务器端组件,它随Web应用的启动而启动,只初始化一次,然后会一直运行监视,随Web应用的停止而销毁。
作用1:做一些初始化的工作,web应用中spring容器启动ContextLoadListener
作用2:监听web的特定事件,比如HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。比如统计在线人数,利用HttpSessionLisener等
配置在web.xml中
- 过滤器
对Request请求起到过滤的作用,作用在Servlet之前,如果配置为/*可以对所有的资源访问进行过滤处理
配置在web.xml中
- 拦截器
是Spring MVC、Struts等表现层框架自己的,不会拦截jsp/html/css/image的访问等,只会拦截访问的控制器方法(Handler)
执行的三个时机:
- 在Handler业务逻辑执行之前拦截一次
- 在Handler逻辑执行完毕但未跳转页面之前拦截一次
- 在跳转页面之后拦截一次
配置在表现层框架自己的配置文件中。
执行流程如下:
如果有多个拦截器呢?
拦截器编写:
- 编写一个拦截器
public class MyIntercepter implements HandlerInterceptor {
    /**
     *
     * @param request
     * @param response
     * @param handler
     * @return  返回值boolean代表是否放?,true代表放?,false代表中?
     * @throws Exception
     */
    @Override
    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行preHandle");
        return true;
    }
    /**
     * 会在handler?法业务逻辑执?之后尚未跳转??时执?
     * @param request
     * @param response
     * @param handler
     * @param modelAndView  封装了视图和数据,此时尚未跳转??呢,你可以在这?针对返回的数据和视图信息进?修改
     * @throws Exception
     */
    @Override
    public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }
    @Override
    public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}
- 配置
 
        
            
             
     
2. 处理multipart形式的数据
上传文件介绍:
- 引入依赖
    commons-fileupload 
    commons-fileupload 
    1.3.1 
 
- 配置文件上传解析器
 
- 前端form
- 后端接收代码
  @RequestMapping("/upload")
    public String upload(MultipartFile uploadFile, HttpServletRequest request) throws IOException {
        String originalFilename = uploadFile.getOriginalFilename();
        System.out.println("原始文件名:"+originalFilename);
        // 获取?件的扩展名,如jpg
        String extendName =
                originalFilename.substring(originalFilename.lastIndexOf(".") + 1,
                        originalFilename.length());
        String uuid = UUID.randomUUID().toString();
        // 新的?件名字
        String newName = uuid + "." + extendName;
        String realPath=request.getServletContext().getRealPath("/uploads");
        String datePath=new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        File floder=new File(realPath+datePath);
        if(!floder.exists()){
            floder.mkdirs();
        }
        uploadFile.transferTo(new File(floder,newName));
        return "success";
    }
注意:前端input file的name的值要和后端接收的MultipartFile uploadFile的参数名称保持一致。
3. 全局异常处理
// 可以让我们优雅的捕获所有Controller对象handler?法抛出的异常
@ControllerAdvice
public class GlobalExceptionResolver {
    @ExceptionHandler(ArithmeticException.class)
    public ModelAndView handleException(ArithmeticException exception,
                                        HttpServletResponse response) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", exception.getMessage());
        modelAndView.setViewName("error");
        return modelAndView;
    }
}
也可以在handleException方法上加上@ResponseBody直接返回json数据。
4. 基于Flash属性的跨重定向请求数据传递
我们有两种方式来跳转请求,一种是重定向,一种是请求转发。
- 请求转发:请求参数不变,浏览器url也不变
- 重定向:参数丢失,浏览器url变
那么我们怎么携带参数进行重定向呢?
方法1:拼接url
 @RequestMapping("/testRedirect")
    public String redirect(String name){
        return "redirect:/demo/testName?name="+name;
    }
方法2:使用RedirectAttributes
@RequestMapping("/testRedirect")
    public String redirect(String name,RedirectAttributes redirectAttributes){
        //该属性会暂存在session中,跳转页面后该属性销毁
        redirectAttributes.addFlashAttribute("name",name);
        return "redirect:/demo/testName";
    }
    @RequestMapping("/testName")
    public String testName(HttpSession session,@ModelAttribute("name") String name){
        System.out.println(name);
        return "success";
    }