美文网首页
SpringMVC学习day-68:过滤器和拦截器的使用,Spr

SpringMVC学习day-68:过滤器和拦截器的使用,Spr

作者: 开源oo柒 | 来源:发表于2019-10-25 23:38 被阅读0次

    一、文件的下载

    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文件的配置:

    <filter>    
      <filter-name>enc</filter-name>    
      <filter-class>com.bjsxt.filter.EncFilter</filter-class>    
      <init-param>      
        <param-name>e</param-name>      
        <param-value>utf-8</param-value>    
      </init-param>  
    </filter>  
    <filter-mapping>    
      <filter-name>enc</filter-name>    
      <url-pattern>/servlet/*</url-pattern>  
    </filter-mapping>
    
    • 使用Spring中提供的字符编码过滤器:
    <!-- 配置字符编码过滤器 -->
        <filter>
            <filter-name>encod</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            
            <init-param>
                <param-name>encoding</param-name>
                <param-value>utf-8</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>encod</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    三、拦截器

    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(后)
      配置文件:
      <!--全局配置-->
      <mvc:interceptors>  
               <bean class="com.bjsxt.interceptor.MyInter2"></bean> 
               <bean class="com.bjsxt.interceptor.MyInter"></bean> 
       </mvc:interceptors>
    

    执行顺序:

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

    4.代码示例:

    • 配置文件:
     <!-- 配置拦截器 -->
            <mvc:interceptors>
               <!--<bean class="com.bjsxt.interceptor.MyInter2"></bean> -->
                <mvc:interceptor>
                    <mvc:mapping path="/login"/>
                    <bean id="my" class="com.zlw.interceptor.MyInceptor"></bean>
                </mvc:interceptor>
            </mvc:interceptors>
    
    • 实现接口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<String, Object> 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)<mvc:annotation-driven/> 实际注册了两个<bean> :
            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配置文件:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd 
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
        <bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
            <property name="url" value="jdbc:mysql://localhost:3306/bjsxt"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
        <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="typeAliasesPackage" value="com.zlw.pojo"></property>
        </bean>
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="factory"></property>
            <property name="basePackage" value="com.zlw.mapper"></property>
        </bean>
        <context:component-scan base-package="com.zlw.service"></context:component-scan>
    </beans>   
    
    • mapper接口和映射文件:
      (1)EmailMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.zlw.mapper.EmailMapper">
        <select id="findMore" resultType="email">
            select * from t_user u join t_email e 
                on u.uid = e.sendid 
                where e.recid = #{0}
        </select>
        <insert id="send" >
            insert into t_email values(default,#{etitle},#{econ},#{filename},#{recid},#{sendid},#{edate})
        </insert>
    </mapper>
    

    (2)UserMapper.xml

      <mapper namespace="com.zlw.mapper.UserMapper">
        <select id="findOne" resultType="user">
            select *from t_user where uname = #{0} and pwd = #{1}
        </select>
      </mapper>
    
    • 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<Email> list = us.findMore(1);
            for (Email email : list) {
                
                System.out.println(email.getUname());
            }
        }
    }
    
    结果
    • web.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>x_ssmEmail02</display-name>
      <!-- 配置字符编码过滤器 -->
        <filter>
            <filter-name>encod</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            
            <init-param>
                <param-name>encoding</param-name>
                <param-value>utf-8</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>encod</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext-*.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <!-- 核心配置 -->
        <servlet>
            <servlet-name>mvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>mvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
    • springmvc.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd 
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!-- @Contorller -->
        <context:component-scan base-package="com.zlw.controller"></context:component-scan>
    
        <!-- @RequestMapping -->
        <mvc:annotation-driven></mvc:annotation-driven>
        <!-- 配置拦截器 -->
        
        <!-- 创建上次文件的组件对象 -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 上传文件的名称中文乱码问题 -->
            <property name="defaultEncoding" value="utf-8"></property>
        </bean>
    </beans>
    
    • 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 <Email> 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)登录界面:
    <body>
        <form action="login" method="post">
            <p>
                用户名:<input type="text" name="uname" />${error }
            </p>
            <p>
                密码:<input type="password" name="pwd" />
            </p>
            <p>
                <input type="submit" value="登录" />
            </p>
        </form>
    </body>
    

    (2)邮件信息:

    <body>
      <table border="1px">
        <tr>
            <th>标题</th>
            <th>时间</th>
            <th>发送人</th>
        </tr>
        <c:forEach items="${list }" var="em">
        <tr>
            <th>${em.etitle }</th>
            <th>${em.edate }</th>
            <th>${em.uname}</th>
        </tr>
        </c:forEach>
      </table>
      <p>
        <a href="send.jsp">发送邮件</a>
      </p>
      <p>
        <a href="login.jsp">登录页面</a>
      </p>
      </body>
    

    (3)发送邮件:

    <body> 
        <form action="send" enctype="multipart/form-data" method="post">
            <p>
                收件人:<input type="text" name="recid"/>
            </p>
            <p>
                主题:<input type="text" name="etitle"/>
            </p>
            <p>
                正文:<input type="text" name="econ"/>
            </p>
            <p>
                附件<input type="file" name="fl"/>
            </p>
            <p>
                <input type="submit" value="发送"/>
            </p>
        </form>
      </body>
    

    (4)成功界面:

     <body>
        邮件发送成功!点击跳转<a href="findEmail">跳转</a>到主页面
      </body>
    

    3.实现效果:

    • 登录界面:


      登录
    • 展现页面:


      邮件信息
    • 发送界面:


      发送.png
    • 发送成功:


      成功

    相关文章

      网友评论

          本文标题:SpringMVC学习day-68:过滤器和拦截器的使用,Spr

          本文链接:https://www.haomeiwen.com/subject/ekwevctx.html