SpringMVC学习day-68:过滤器和拦截器的使用,SpringMVC的运行原理

一、文件的下载

1.文件下载的实现步骤:

  • 从服务器读取需要下载的文件;
    (1)获取服务器的目录;
    (2)设置属性下载文件的长度;
    (3)设置下载文件的类型;
    (4)设置响应头信息;
  • 把读取到的文件写入到本地。

2.代码的实现:

@RequestMapping("downLoad")
    public void downLoad(String filename,String filetype,HttpServletRequest request,HttpServletResponse response) throws IOException{
        //读取服务器中需要下载的文件
        //获取服务器的目录
        String realPath = request.getServletContext().getRealPath("/upload");
        File file = new File(realPath+"/"+filename);
        InputStream inputStream = new FileInputStream(file);
        
        //设置属性下载到本地
        //设置下载文件的长度
        response.setContentLength((int) file.length());
        //设置文件下载的类型
        response.setContentType(filetype);
        //设置响应头信息
        response.setHeader("Content-Disposition","attachment;filename="+filename);
        //把读取的文件写到本地
        OutputStream outputStream = response.getOutputStream();
        IOUtils.copy(inputStream, outputStream);
        outputStream.close();
        inputStream.close();
    }

二、过滤器

1.使用过滤器解决请求的中文乱码(post请求)

  • 自定义过滤器:
    (1)创建Filter接口的实现类:
package com.zlw.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class EncFilter implements Filter {
    //定义参数
    String enc;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //初始化参数
        enc = filterConfig.getInitParameter("e");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //到达目标资源之前的预处理
        request.setCharacterEncoding(enc);
        //执行目标资源方法或者下一个过滤器
        chain.doFilter(request, response);
        
        //离开服务器之前的处理操作
    }

    @Override
    public void destroy() {
    }
}

(2)web.xml文件的配置:

    
  enc    
  com.bjsxt.filter.EncFilter    
        
    e      
    utf-8    
    
  
    
  enc    
  /servlet/*  

  • 使用Spring中提供的字符编码过滤器:

    
        encod
        org.springframework.web.filter.CharacterEncodingFilter
        
        
            encoding
            utf-8
        
    
    
        encod
        /*
    

三、拦截器

1.拦截器和过滤器的区别:

  • 过滤器:

主要做三件事:
(1)达到目标资源之前的预处理;
(2)执行下一个过滤器或者目标资源;
(3)离开服务器之前的处理;
过滤器主要针对:我们配置的所有请求。

  • 拦截器:

主要针对的是控制单元的方法。
拦截器的底层就是AOP面向切面实现的;控制单元类似于切点;
使用拦截器需要在springmvc.xml配置文件中配置拦截器bean和拦截范围,配置全局拦截。

示例图

2.拦截器中的方法:

(1)preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2)

  • 作用:拦截单元方法,返回值为false则拦截,返回值为true则放行 。
  • 参数:
    HttpServletRequest arg0,拦截的请求的request对象 ;
    HttpServletResponse arg1, 拦截的请求的response对象 ;
    Object arg2 封存了单元方法对象的HandleMethod对象 ;

(2)postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)

  • 作用:用于控制单元中模块的测试;恶意字符的替换。
  • 参数:
    HttpServletRequest arg0, 拦截的请求的request对象 ;
    HttpServletResponse arg1, 拦截的请求的response对象 ;
    Object arg2, 封存了单元方法对象的HandleMethod对象 ;
    ModelAndView arg3 封存了单元方法的返回值资源路径和请求转到的Map数据 ;

(3) afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)

  • 作用:主要就是页面渲染操作和最后的垃圾回收。
  • 参数:
    HttpServletRequest arg0, 拦截的请求的request对象 ;
    HttpServletResponse arg1, 拦截的请求的response对象 ;
    Object arg2, 封存了单元方法对象的HandleMethod对象 ;
    Exception arg3 存储了责任链的异常信息 ;

(4)拦截器方法执行的顺序:

preHandle--->单元方法--->postHandle--->afterCompletion

3.多拦截器:

SpringMVC多拦截器的执行顺序先进后出,是按照配置文件的先后;

  • 例如:有两个拦截器MyInter2(先)和MyInter(后)
    配置文件:
  
    
            
            
   

执行顺序:

preHandle(Myinter2) --> preHandle(MyInter) --> 控制器方法(HandlerMethod) --> postHandle(MyInter) --> postHandle(MyInter2) --> afterCompletion(MyInter) --> afterCompletion(MyInter2);

4.代码示例:

  • 配置文件:
 
        
           
            
                
                
            
        
  • 实现接口HandlerInterceptor:
package com.zlw.interceptor;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInceptor implements HandlerInterceptor {

    /**
     * 执行的时机:在进入控制单元方法之前 这个方法的返回值决定了是否继续执行控制单元的方法 返回值是true就进入控制单元继续执行
     * 返回值是false就不会继续执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        // 作用一:进行中文乱码的处理
        request.setCharacterEncoding("utf-8");
        // 作用二:进行页面的拦截
        // response.sendRedirect("index.jsp");
        System.out.println("preHandle!!!");

        return true;
    }

    /**
     * 执行时机:在进行数据处理之后 object:控制单元的方法 mv:视图模型对象
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object,
            ModelAndView modelAndView) throws Exception {
        /**
         * 作用一:用于控制单元中模块的测试 modelAndView.setViewName("redirect:/index.jsp")
         * 
         * 作用二:恶意字符的替换 获取map集合中的值
         * 
         */
        // modelAndView.setViewName("redirect:/index.jsp");
        Map map = modelAndView.getModel();
        String error = (String) map.get("error");
        if (error.contains("XX")) {
            String all = error.replaceAll("XX", "**");
            map.put("error", all);
        }
    }

    /**
     * 执行时机:在进行页面渲染时执行 主要用于页面渲染操作和最后的垃圾回收
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception ex)
            throws Exception {
        System.out.println("afterComletion!!!");
    }
}

四、SpringMVC的运行原理

1.SpringMVC运行原理:

(1)BeanDefinitionParser 接口,实现类负责解析配置文件中自定义命名空间对应的标签。
(2) 实际注册了两个
        a.HandlerMapping接口的实现类DefaultAnnotationHandlerMapping, 判断URL合法性。
        b.HandlerAdapter接口实现类AnnotationMethodHandlerAdapter,寻找@RequestMapping(),调用对应的方法。

2.核心组件(SpringMVC的四大组件):

(1)DispatchServlet: Servlet分发器,整个SPringMVC框架入口;
(2)HandlerMapping:寻找URL所请求的HandlerMethod,找@RequestMapping() ;
        a.使用实现类DefaultAnnotationHandlerMapping实际工作;
(3)HandlerAdapter:实际调用HandlerMethod的组件;
        a.使用实现类AnnotationMethodHandlerAdapter ;
(4)ViewResovler:视图解析器.作用解析HandlerMethod返回值,把逻辑视图转换为需要调用的物理视图。
        a.自定义时:InternalResourceViewResolver;

3.使用的组件和接口:

(1)Controller : 控制器类 ;
(2)HandlerMethod: 控制器方法 ;
(3)View: 视图 ;
(4)Model: 模型;
(5)ModelAndView:模型和视图.SpringMVC所有HandlerMethod最终都会转换为ModelAndView;
(6)HandlerInterceptor: 拦截器 ;
(7)HandlerExceptionResolver:异常映射解析器;
(8)MultipartResolver: Multipart解析器 ;
(9)CharacterEncodingFilter: 字符编码过滤器 ;

4.SpringMVC运行原理图解:

  • 详细图:


    示例图
  • 时序图:


    时序图
  • SpringMVC请求处理流程:


    处理流程

5.SpringMVC运行原理文字解释:

当用户发起请求后,执行DiapacherServlet,如果是JSP直接调用jsp页面。如果不是JSP,DiapacherServlet调用HandlerMapping判断请求URL是否合法,如果URL不存在报错,如果URL存在使用HandlerAdapter调用具体的HandlerMethod,当Handler执行完成后会返回ModelAndView,会被ViewResovler解析,调用具体的物理视图。最终响应给客户端浏览器。

五、邮箱系统的练习

1.需求:

(1)实现用户的登录;
(2)完成邮件信息的查询;
(3)完成邮件的发送;

2.实现步骤:

  • 数据库创建表格:
- 用户表
create TABLE t_user(
    uid int(5) PRIMARY key auto_increment,
    uname VARCHAR(20),
    pwd VARCHAR(20)
)
- 邮件表
create table t_email(
    eid int(5) PRIMARY KEY auto_increment,
    etitle VARCHAR(30),
    econ VARCHAR(100),
    filename VARCHAR(100),
    recid int(10),
    sendid int(10),
    edate date 
)
  • 导包:


    jar包
  • 创建实体类(生成getter和setter及构造方法):

    private int eid;
    private String etitle;
    private String econ;
    private String filename;
    private int recid;
    private int sendid;
    private Date edate;
    private String uname;//用户名
    private int uid;
    private String uname;
    private String pwd;
  • applicationContext.xml配置文件:


    
        
        
        
        
    
    
        
        
    
    
        
        
    
    
   
  • mapper接口和映射文件:
    (1)EmailMapper.xml



    
    
        insert into t_email values(default,#{etitle},#{econ},#{filename},#{recid},#{sendid},#{edate})
    

(2)UserMapper.xml

  
    
  
  • test测试:
package com.zlw.test;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zlw.pojo.Email;
import com.zlw.service.UserService;

public class Test01 {
    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-mybatis.xml");
        UserService us = app.getBean("userService",UserService.class);
        List list = us.findMore(1);
        for (Email email : list) {
            
            System.out.println(email.getUname());
        }
    }
}
结果

  • web.xml:


  x_ssmEmail02
  
    
        encod
        org.springframework.web.filter.CharacterEncodingFilter
        
        
            encoding
            utf-8
        
    
    
        encod
        /*
    
    
    
        contextConfigLocation
        classpath:applicationContext-*.xml
    
    
        org.springframework.web.context.ContextLoaderListener
    
    
    
        mvc
        org.springframework.web.servlet.DispatcherServlet

        
            contextConfigLocation
            classpath:springmvc.xml
        
    
    
        mvc
        /
    

  • springmvc.xml:



    
    

    
    
    
    
    
    
    
        
    

  • Controller控制单元:
    (1)EmailController
package com.zlw.controller;


import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import com.zlw.pojo.Email;
import com.zlw.pojo.User;
import com.zlw.service.UserService;

@Controller
public class EmailController {
    
    @Autowired
    private UserService userService;
    //查询邮件
    @RequestMapping("findEmail")
    public String findEmail(HttpSession session,HttpServletRequest request){
        User user = (User) session.getAttribute("user");
        
        List  list = userService.findMore(user.getUid());
        request.setAttribute("list", list);
        return "forward:/mian.jsp";
        
    }
    //发送邮件操作
    @RequestMapping("send")
    public String send(Email email,MultipartFile fl,HttpSession session) throws IllegalStateException, IOException{
        User user = (User) session.getAttribute("user");
        email.setFilename(fl.getOriginalFilename());
        email.setEdate(new java.sql.Date(new Date().getTime()));
        email.setSendid(user.getUid());
        int i = userService.send(email);
        
        fl.transferTo(new File("D:/img/"+fl.getOriginalFilename()));
        if(i>0){
            return "redirect:/success.jsp";
        }
        return "send.jsp";
    }

}

(2)UserController

package com.zlw.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.zlw.pojo.User;
import com.zlw.service.UserService;

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    
    //登录操作
    @RequestMapping("login")
    public String login(String uname,String pwd,HttpServletRequest request,HttpSession session){
        User user = userService.findOne(uname, pwd);
        if(user!=null){
            session.setAttribute("user", user);
            return "redirect:findEmail";
        }
        request.setAttribute("error", "登录失败!");
        return "login.jsp";
    }
}
  • jsp页面:
    (1)登录界面:

    

用户名:${error }

密码:

(2)邮件信息:


  
    
标题 时间 发送人
${em.etitle } ${em.edate } ${em.uname}

发送邮件

登录页面

(3)发送邮件:

 
    

收件人:

主题:

正文:

附件

(4)成功界面:

 
    邮件发送成功!点击跳转跳转到主页面
  

3.实现效果:

  • 登录界面:


    登录
  • 展现页面:


    邮件信息
  • 发送界面:


    发送.png
  • 发送成功:


    成功

你可能感兴趣的:(SpringMVC学习day-68:过滤器和拦截器的使用,SpringMVC的运行原理)