美文网首页Android知识Android开发经验谈程序员
VMware WorkStation、SpringMVC的烦心事

VMware WorkStation、SpringMVC的烦心事

作者: cmazxiaoma | 来源:发表于2017-12-25 12:45 被阅读0次
    diary_report.jpg

    Interesting things

    有2天没有写diary report了,因为这几天都在火车上颠簸。上个星期五晚上9点的火车从广州到武汉,星期日在学校考试,然后晚上9点的火车又匆忙的赶回广州。今天是8点30赶到的广州,很累。今天老大给我布置了一个新的Task,实现FastDFS的集群和负载均衡。看来今天是要加班的,FastDFS对我来说是一个未知的领域,Spring Security 和 Filter、Interceptor的demo还没有写出来。(目测又要delay)我的时间计划表是每天6点30起床,晚上加班到10点(正常是6点),笨鸟先飞。

    What did you do today

    • 可插拔性,在软件系统的设计中,可插拔是一个重要特性。它意味着给系统添加新功能的时候(或者将原来功能的实现替换成新的实现而保持接口不变),不改变系统已有的功能。
    • CMD (Common Module Definition):公共模块定义,对于模块的依赖,CMD是延迟执行,推崇依赖就近。
    • 今天安装VMware Workstation,这个玩意大学上嵌入式的时候用过(设置ip和掩码:ifconfig eth0 192.168.1.2 netmask 255.255.255.0就是这样用,设置的ip是一次性,重启虚拟机后就失效, 设置网关:route add default gw 192.168.1.1),可是在我自己的笔记本我一直用Virtural Box。用起来Vmware还真不习惯,首先遇到一个问题就是虚拟机ping不同主机(真尼玛蛋疼),所以记录一下。
    • 进入虚拟机设置,把网络连接设置为桥接模式。


      image.png
      • 点“高级”按钮,记录我们的MAC地址00:0C:29:67:76:2F


        image.png
      • 如果/etc/sysconfig/network-scripts目录没有ifcfg-eth0文件,那么我们就创建ifcfg-eth0文件,cd /etc/sysconfig/network-scripts, touch ifcfg-eth0

      • vi ifcfg-eth0 ,对这个文件进行编辑。具体的编辑内容可以参考图片。


        image.png
      • vi /etc/resolv.conf 进入resolv.conf文件设置dns。


        image.png
      • vim /etc/rc.d/rc.local,配置ifup eth0,让开始时重启eth0。


        image.png
      • 重启网络服务,service network restart


        image.png
      • 我们满怀期待的输入ping 192.168.12.61(这个是主机地址),然后结果啪啪啪打脸,根本就ping不通嘛。


        image.png
      • 冥思苦想一下,发现是本地防火墙开启的问题,那么我们关掉防火墙再试一试。果然是防火墙的问题,草他妈。


        image.png
      • 我们本地的防火墙肯定不能关闭,那么有没有一种策略,能实现虚拟机ping通主机同时又保证本地防火墙保持开启状态呢?肯定是有的,打开Windows防火墙,找到高级设置。


        image.png
      • 我们在入站规则中找到“文件和打印机共享(回显请求 - ICMPv4-In)”,然后启动该规则即可解决问题。


        image.png
      • 但是我们又发现一个问题,我们ping不通www.baidu.com,这个问题就很操蛋了。

        image.png
      • 我们只需要把nameserver 设置为 114.114.114.114就能解决虚拟机ping不通外网的问题。


        image.png
        image.png

    后续更新文章

    如果你没有插网线的话, ifconfig应该是没有本地适配器的ip。反之你是wifi连接的话,ifconfig会出现网卡的ip和网关。我们在配置虚拟机使 ip和网卡的ip在同一网段,网关应该和电脑网卡保持一致即可。

    Vmware的三种模式配置,我之前这篇文章有讲过你应该知道的VirtualBox虚拟机网络配置

    这里我再复述一遍(以前内容取自于网络):

    • VMWare提供了三种工作模式,它们是bridged(桥接模式)、NAT(网络地址转换模式)和host-only(主机模式)。要想在网络管理和维护中合理应用它们,你就应该先了解一下这三种工作模式。

    • Bridged(桥接模式)

      • 在这种模式下,VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器。在桥接模式下,你需要手工为虚拟系统配置IP地址、子网掩码,而且还要和宿主机器处于同一网段,这样虚拟系统才能和宿主机器进行通信。同时,由于这个虚拟系统是局域网中的一个独立的主机系统,那么就可以手工配置它的TCP/IP配置信息,以实现通过局域网的网关或路由器访问互联网。
      • 使用桥接模式的虚拟系统和宿主机器的关系,就像连接在同一个Hub上的两台电脑。想让它们相互通讯,你就需要为虚拟系统配置IP地址和子网掩码,否则就无法通信。
      • 如果你想利用VMWare在局域网内新建一个虚拟服务器,为局域网用户提供网络服务,就应该选择桥接模式。
    • host-only(主机模式)

      • 在某些特殊的网络调试环境中,要求将真实环境和虚拟环境隔离开,这时你就可采用host-only模式。在host-only模式中,所有的虚拟系统是可以相互通信的,但虚拟系统和真实的网络是被隔离开的。
      • 提示:在host-only模式下,虚拟系统和宿主机器系统是可以相互通信的,相当于这两台机器通过双绞线互连。
      • 在host-only模式下,虚拟系统的TCP/IP配置信息(如IP地址、网关地址、DNS服务器等),都是由VMnet1(host-only)虚拟网络的DHCP服务器来动态分配的。
      • 如果你想利用VMWare创建一个与网内其他机器相隔离的虚拟系统,进行某些特殊的网络调试工作,可以选择host-only模式。
    • NAT(网络地址转换模式)

      • 使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。也就是说,使用NAT模式可以实现在虚拟系统里访问互联网。NAT模式下的虚拟系统的TCP/IP配置信息是由VMnet8(NAT)虚拟网络的DHCP服务器提供的,无法进行手工修改,因此虚拟系统也就无法和本局域网中的其他真实主机进行通讯。采用NAT模式最大的优势是虚拟系统接入互联网非常简单,你不需要进行任何其他的配置,只需要宿主机器能访问互联网即可。
      • 如果你想利用VMWare安装一个新的虚拟系统,在虚拟系统中不用进行任何手工配置就能直接访问互联网,建议你采用NAT模式。
    提示:以上所提到的NAT模式下的VMnet8虚拟网络,host-only模式下的VMnet1虚拟网络,以及bridged模式下的VMnet0虚拟网络,都是由VMWare虚拟机自动配置而生成的,不需要用户自行设置。VMnet8和VMnet1提供DHCP服务,VMnet0虚拟网络则不提供。

    言归正传, 如果你的虚拟机出现了ping不通百度的情况。一个原因是DNS,另一个原因就是没有配置VMware Virtual Ethernet Adapter for VMnet8 的ip和网关地址。 这里的ip同样要和电脑网卡的ip处于同一网段, 网关地址和电脑网卡一样即可。

    这里在衍生一个问题。 同一个物理地址下内的不同逻辑网段能否通信 ?

    • 小马 :其实是不能的。这里要扯出子网掩码的概念,子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址。

    • 小马: 例如两台电脑分别是192.168.0.1/24和192.168.0.135/25,用192.168.0.1去ping 192.168.0.135,因为192.168.0.1/24中包含192.168.0.135,数据包可以发送到,但是192.168.0.135这台电脑仅能访问192.168.0.129-254,所以返回的数据不能直接传给192.168.0.1,而是要把数据发给网关进行转发,如果没有网关,则会将数据包丢弃。

    • 小马: 192.168.0.1/24,说明前24位是网络地址, 后8位是主机地址。如果要算广播IP的话,就是主机地址都为1。因此我们可以算出其子网掩码是255.255.255.0。子网掩码按位与IP地址可以算出网络地址是192.168.0.0, 广播地址是192.168.0.255。子网掩码的长度也是32位,左边是网络位,用二进制数字“1”表示,1的数目等于网络位的长度;右边是主机位,用二进制数字“0”表示,0的数目等于主机位的长度。这样做的目的是为了让掩码与ip地址做按位与运算时用0遮住原主机数,而不改变原网络段数字,而且很容易通过0的位数确定子网的主机数(2的主机位数次方-2,因为主机号全为1时表示该网络广播地址,全为0时表示该网络的网络号,这是两个特殊地址)。所以我们可以算出子网的ip数是2的8次方 - 2 = 254(第一个地址是网络地址和最后一个地址是广播地址, 需要去掉)。那么其子网ip的范围就是192.168.0.1 - 192.168.0.254

    • 小马: 同理可得192.168.0.135/25的子网掩码是255.255.255.128,网络地址是192.168.0.128,广播地址是192.168.0.255,子网ip范围是192.168.0.129-192.168.0.254。子网ip数量=2的7次方-2 = 126。所以解答了同一物理地址下内的不同逻辑网段是不能通信的。

    • 小马: 扩展知识, 网络地址=IP地址&子网掩码, 主机地址=IP地址&按位非(子网掩码),广播地址=主机位都是1。A类地址开头是0, 0-127。B类地址开头是10, 128-191,
      C类地址开头是110, 192-223。


    • 关于<mvc:annotation-driven />这个问题,我们接着上一篇博客讲,我上一篇博客的观点出自于使用@Controller注解为什么要配置<mvc:annotation-driven />,这篇博客作者的观点是"要使用spring mvc中的@Controller注解,就必须要配置<mvc:annotation-driven />,否则org.springframework.web.servlet.DispatcherServlet无法找到控制器并把请求分发到控制器。" 当我刚开始学习SpringMVC的时候,就看过这篇文章,这篇文章某些观点的确解决了我的一些开发问题,但是我上面列举的作者观点就错的有点离谱。 下面我就用代码去证明这个观点是错的!
      • 我们在spring-servlet注释<mvc:annotation-driven />这一行代码。


        image.png
      • 定义一个MvcAnnotationDrivenTestController
      @RequestMapping("/mvc")
    @Controller
    public class MvcAnnotationDrivenTestController {
    
        @RequestMapping(value = "/testMvcAnnotationDriven", method = RequestMethod.GET)
        public ModelAndView testMvcAnnotationDriven() {
            return new ModelAndView("mvc_annotation_driven_test");
        }
    }
    
    • 在/WEB-INF/jsp/下面,定义mvc_annotation_driven_test.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>mvc_annotation_driven_test</title>
        </head>
        <body>
            hello, this is mvc_annotation_driven_test
        </body>
    </html>
    
    • 我们启动tomcat,输入http://localhost:8080/mvc/testMvcAnnotationDriven,我们就证明了"使用spring mvc中的@Controller注解,就必须要配置<mvc:annotation-driven />" 这个观点是错的了。
      image.png
    • 接下来我们在定义一个TestController,我们可以提供一个问题:“如果不在spring-servlet文件中配置<mvc:annotation-driven />,我们能成功的去访问http://localhost:8080/test/interceptor1这个链接吗?” 答案是不能访问!!!
    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @GetMapping("/interceptor1")
        public String testInterceptor1(HttpSession session) {
            session.setAttribute("test1", "interceptor1");
            session.invalidate();
            return "testInterceptor1";
        }
    
        @GetMapping("/interceptor2")
        public String testInterceptor2(HttpSession session) {
            session.setAttribute("test2", "interceptor2");
            session.invalidate();
            return "testInterceptor2";
        }
    }
    
    * 会抛出"[20:02:37:859] [WARN] - org.springframework.web.servlet.DispatcherServlet.noHandlerFound(DispatcherServlet.java:1176) - No mapping found for HTTP request with URI [/test/interceptor1] in DispatcherServlet with name 'filter_interceptor_mvc'"这个错误,造成404。
    
    image.png
    • 我们可以去官方的一些文档找到答案。<mvc:annotation-driven/>其实是毫无意义的。它声明了对注解驱动(@RequestMapping, @Controller)的mvc控制器的显式支持,尽管对这些的支持是默认行为。
    <mvc:annotation-driven /> is actually rather pointless. It declares explicit support for annotation-driven MVC controllers (i.e.@RequestMapping, @Controller, etc), even though support for those is the default behaviour.
    
    • 翻译后的意思就是:我的建议总是声明<context:annotation-config/>,但是不要打扰<mvc:annotation-driven/>,除非你想通过Jackson来支持Json。
    My advice is to always declare <context:annotation-config>, but don't bother with <mvc:annotation-driven /> unless you want JSON support via Jackson.
    
    • 我想上面的解释能解开你们心中的疑惑。美滋滋!

    • 接下来的篇幅会讲Listener、Filter、Interceptor的demo(终于可以还债了)。

      • 创建TestInterceptor1、TestInterceptor2。
    @Slf4j
    public class TestInterceptor1 extends HandlerInterceptorAdapter {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("TestInteceptor1 preHandle");
    
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("TestInterceptor1 postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("TestInterceptor1 afterCompletion");
        }
    }
    
    @Slf4j
    public class TestInterceptor2 extends HandlerInterceptorAdapter {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("TestInterceptor2 preHandle");
    
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("TestInterceptor2 postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("TestInterceptor2 afterCompletion");
        }
    }
    
    • 创建TestFilter1、TestFilter2。
    @Slf4j
    public class TestFilter1 extends OncePerRequestFilter {
        private String username;
        private String password;
    
        public TestFilter1() {}
    
        public TestFilter1(String username, String password) {
            this.username = username;
            this.password = password;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
            log.info("TestFilter1 doFilterInternal started, username = {} , password = {} ", username, password);
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            log.info("TestFilter1 doFilterInternal end, username = {} , password = {}", username, password);
        }
    }
    
    
    @Slf4j
    public class TestFilter2 extends OncePerRequestFilter {
        private String username;
        private String password;
    
        public TestFilter2() {}
    
        public TestFilter2(String username, String password) {
            this.username = username;
            this.password = password;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
            log.info("TestFilter2 doFilterInternal started");
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            log.info("TestFilter2 doFilterInternal end");
        }
    }
    
    • 创建ContextListener、RequestListener、RequestAttributeListener、SessionListener。
    @Slf4j
    public class ContextListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            log.info("context initialized");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            log.info("context destroyed");
        }
    
    }
    
    
    @Slf4j
    public class RequesListener implements ServletRequestListener {
    
        @Override
        public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
            log.info("request destroyed");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent servletRequestEvent) {
            log.info("request initialized");
        }
    }
    
    @Slf4j
    public class RequestAttributeListener implements ServletRequestAttributeListener {
    
        @Override
        public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
            log.info("attribute added");
        }
    
        @Override
        public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
            log.info("attribute removed");
        }
    
        @Override
        public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
            log.info("attribute replaced");
        }
    }
    
    @Slf4j
    public class SessionListener implements HttpSessionListener {
    
        @Override
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            log.info("session created");
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            log.info("session destroyed");
        }
    }
    
    • 在web.xml配置Filter、Listener
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
    
        <display-name>filter_interceptor</display-name>
        <welcome-file-list>
            <welcome-file>cmazxiaoma.jsp</welcome-file>
        </welcome-file-list>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:spring-config.xml
            </param-value>
        </context-param>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
        </listener>
    
        <listener>
            <listener-class>com.cmazxiaoma.demo.listener.ContextListener</listener-class>
        </listener>
        
        <listener>
            <listener-class>com.cmazxiaoma.demo.listener.RequesListener</listener-class>
        </listener>
    
        <listener>
            <listener-class>com.cmazxiaoma.demo.listener.RequestAttributeListener</listener-class>
        </listener>
        
        <listener>
            <listener-class>com.cmazxiaoma.demo.listener.SessionListener</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>filter_interceptor_mvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-servlet.xml</param-value>
            </init-param>
    
            <init-param>
                <param-name>detectAllHandlerExceptionResolvers</param-name>
                <param-value>false</param-value>
            </init-param>
    
            <load-on-startup>1</load-on-startup>
            <async-supported>true</async-supported>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>filter_interceptor_mvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <filter>
            <filter-name>characterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <async-supported>true</async-supported>
    
            <init-param>
                <param-name>encoding</param-name>
                <param-value>utf-8</param-value>
            </init-param>
    
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
    
        </filter>
    
        <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        <filter>
            <filter-name>testFilter1</filter-name>
            <filter-class>com.cmazxiaoma.demo.filter.TestFilter1</filter-class>
            <async-supported>true</async-supported>
            
            <init-param>
                <param-name>username</param-name>
                <param-value>testFilter1</param-value>
            </init-param>
    
            <init-param>
                <param-name>password</param-name>
                <param-value>123</param-value>
            </init-param>
        </filter>
    
        <filter-mapping>
            <filter-name>testFilter1</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
       
        <filter>
            <filter-name>testFilter2</filter-name>
            <filter-class>com.cmazxiaoma.demo.filter.TestFilter2</filter-class>
            <async-supported>true</async-supported>
    
            <init-param>
                <param-name>username</param-name>
                <param-value>testFilter2</param-value>
            </init-param>
    
            <init-param>
                <param-name>password</param-name>
                <param-value>456</param-value>
            </init-param>
        </filter>
        
        <filter-mapping>
            <filter-name>testFilter2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    </web-app>
    
    • 在servlet-servlet中配置Interceptor。
        <mvc:interceptors>
    
            <mvc:interceptor>
                <mvc:mapping path="/test/interceptor1"/>
                <bean class="com.cmazxiaoma.demo.interceptor.TestInterceptor1" />
            </mvc:interceptor>
            
            <mvc:interceptor>
                <mvc:mapping path="/test/interceptor2"/>
                <bean class="com.cmazxiaoma.demo.interceptor.TestInterceptor2" />
            </mvc:interceptor>
        </mvc:interceptors>
    
    [21:19:03:666] [INFO] - com.cmazxiaoma.demo.listener.RequesListener.requestInitialized(RequesListener.java:18) - request initialized
    [21:19:03:666] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:666] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:667] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:667] [INFO] - com.cmazxiaoma.demo.filter.TestFilter1.doFilterInternal(TestFilter1.java:44) - TestFilter1 doFilterInternal started, username = testFilter1 , password = 123 
    [21:19:03:667] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:667] [INFO] - com.cmazxiaoma.demo.filter.TestFilter2.doFilterInternal(TestFilter2.java:42) - TestFilter2 doFilterInternal started
    [21:19:03:680] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:680] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:680] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:681] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:681] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:681] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:685] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:686] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:686] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:691] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:03:691] [INFO] - com.cmazxiaoma.demo.interceptor.TestInterceptor1.preHandle(TestInterceptor1.java:15) - TestInteceptor1 preHandle
    [21:19:03:705] [INFO] - com.cmazxiaoma.demo.listener.SessionListener.sessionDestroyed(SessionListener.java:18) - session destroyed
    [21:19:03:718] [INFO] - com.cmazxiaoma.demo.interceptor.TestInterceptor1.postHandle(TestInterceptor1.java:22) - TestInterceptor1 postHandle
    [21:19:03:718] [INFO] - com.cmazxiaoma.demo.interceptor.TestInterceptor1.afterCompletion(TestInterceptor1.java:27) - TestInterceptor1 afterCompletion
    [21:19:03:719] [INFO] - com.cmazxiaoma.demo.filter.TestFilter2.doFilterInternal(TestFilter2.java:44) - TestFilter2 doFilterInternal end
    [21:19:03:719] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeRemoved(RequestAttributeListener.java:18) - attribute removed
    [21:19:03:719] [INFO] - com.cmazxiaoma.demo.filter.TestFilter1.doFilterInternal(TestFilter1.java:46) - TestFilter1 doFilterInternal end, username = testFilter1 , password = 123
    [21:19:03:719] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeRemoved(RequestAttributeListener.java:18) - attribute removed
    [21:19:03:719] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeRemoved(RequestAttributeListener.java:18) - attribute removed
    [21:19:03:719] [INFO] - com.cmazxiaoma.demo.listener.RequesListener.requestDestroyed(RequesListener.java:13) - request destroyed
    
    image.png
    [21:19:46:054] [INFO] - com.cmazxiaoma.demo.listener.RequesListener.requestInitialized(RequesListener.java:18) - request initialized
    [21:19:46:055] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:056] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:056] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:056] [INFO] - com.cmazxiaoma.demo.filter.TestFilter1.doFilterInternal(TestFilter1.java:44) - TestFilter1 doFilterInternal started, username = testFilter1 , password = 123 
    [21:19:46:056] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:057] [INFO] - com.cmazxiaoma.demo.filter.TestFilter2.doFilterInternal(TestFilter2.java:42) - TestFilter2 doFilterInternal started
    [21:19:46:057] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:057] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:058] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:058] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:059] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:059] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:059] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:060] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:060] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:061] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeAdded(RequestAttributeListener.java:13) - attribute added
    [21:19:46:061] [INFO] - com.cmazxiaoma.demo.interceptor.TestInterceptor2.preHandle(TestInterceptor2.java:15) - TestInterceptor2 preHandle
    [21:19:46:061] [INFO] - com.cmazxiaoma.demo.filter.TestFilter2.doFilterInternal(TestFilter2.java:44) - TestFilter2 doFilterInternal end
    [21:19:46:062] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeRemoved(RequestAttributeListener.java:18) - attribute removed
    [21:19:46:062] [INFO] - com.cmazxiaoma.demo.filter.TestFilter1.doFilterInternal(TestFilter1.java:46) - TestFilter1 doFilterInternal end, username = testFilter1 , password = 123
    [21:19:46:062] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeRemoved(RequestAttributeListener.java:18) - attribute removed
    [21:19:46:062] [INFO] - com.cmazxiaoma.demo.listener.RequestAttributeListener.attributeRemoved(RequestAttributeListener.java:18) - attribute removed
    [21:19:46:063] [INFO] - com.cmazxiaoma.demo.listener.RequesListener.requestDestroyed(RequesListener.java:13) - request destroyed
    
    • 通过对比log和返回的视图,我们发现了Interceptor1执行了preHandler()、postHandler()、afterCompletion()这三个方法,而Interceptor2只执行了preHandler()这个方法。通过比较它们的源码,我们发现了Interceptor1的preHandler()返回的是true,而Interceptor2的preHandler()返回的是false。而第一个url我们拦截了请求,返回了视图,第二个url我们拦截了请求,返回没有视图。

    • preHandle方法是进行处理拦截用的,该方法将在Controller处理之前调用,Interceptor拦截器是链式的,并且可以中断,当返回false的时候整个请求结束。

    • 当preHandle返回true时,postHandle()才会执行,在Controller的方法调用之后执行,但是它会在DispatcherServlet进行视图的渲染之前执行。

    • 当preHandle返回ture才会执行,该方法将在整个请求完成之后,也就是DispatcherServlet渲染视完毕才执行,主要作用是情理资源。

    • 从启动日志来看,Listener > Filter > Interceptor > Servlet,自定义Listener和Filter很简单,也不需要讲。


    What to do tomorrow

    • 明天去看FastDFS的集群和负载均衡,Spring Security的demo又要delay了。

    Summary

    笨鸟先飞

    相关文章

      网友评论

        本文标题:VMware WorkStation、SpringMVC的烦心事

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