VMware WorkStation、SpringMVC的煩心事

diary_report.jpg

Interesting things

有2天沒有寫diary report了辑莫,因為這幾天都在火車上顛簸学歧。上個星期五晚上9點的火車從廣州到武漢,星期日在學懈鞫郑考試枝笨,然后晚上9點的火車又匆忙的趕回廣州。今天是8點30趕到的廣州揭蜒,很累横浑。今天老大給我布置了一個新的Task,實現(xiàn)FastDFS的集群和負載均衡屉更♂闳冢看來今天是要加班的,F(xiàn)astDFS對我來說是一個未知的領域瑰谜,Spring Security 和 Filter欺冀、Interceptor的demo還沒有寫出來。(目測又要delay)我的時間計劃表是每天6點30起床萨脑,晚上加班到10點(正常是6點)隐轩,笨鳥先飛。

What did you do today

  • 可插拔性渤早,在軟件系統(tǒng)的設計中职车,可插拔是一個重要特性。它意味著給系統(tǒng)添加新功能的時候(或者將原來功能的實現(xiàn)替換成新的實現(xiàn)而保持接口不變)鹊杖,不改變系統(tǒng)已有的功能提鸟。
  • CMD (Common Module Definition):公共模塊定義,對于模塊的依賴仅淑,CMD是延遲執(zhí)行称勋,推崇依賴就近。
  • 今天安裝VMware Workstation涯竟,這個玩意大學上嵌入式的時候用過(設置ip和掩碼:ifconfig eth0 192.168.1.2 netmask 255.255.255.0就是這樣用赡鲜,設置的ip是一次性,重啟虛擬機后就失效庐船, 設置網(wǎng)關:route add default gw 192.168.1.1)银酬,可是在我自己的筆記本我一直用Virtural Box。用起來Vmware還真不習慣筐钟,首先遇到一個問題就是虛擬機ping不同主機(真尼瑪?shù)疤?揩瞪,所以記錄一下。
  • 進入虛擬機設置篓冲,把網(wǎng)絡連接設置為橋接模式李破。


    image.png
    • 點“高級”按鈕宠哄,記錄我們的MAC地址00:0C:29:67:76:2F


      image.png
    • 如果/etc/sysconfig/network-scripts目錄沒有ifcfg-eth0文件,那么我們就創(chuàng)建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
    • 重啟網(wǎng)絡服務辛臊,service network restart


      image.png
    • 我們滿懷期待的輸入ping 192.168.12.61(這個是主機地址),然后結果啪啪啪打臉房交,根本就ping不通嘛浪讳。


      image.png
    • 冥思苦想一下,發(fā)現(xiàn)是本地防火墻開啟的問題涌萤,那么我們關掉防火墻再試一試淹遵。果然是防火墻的問題,草他媽负溪。


      image.png
    • 我們本地的防火墻肯定不能關閉透揣,那么有沒有一種策略,能實現(xiàn)虛擬機ping通主機同時又保證本地防火墻保持開啟狀態(tài)呢川抡?肯定是有的辐真,打開Windows防火墻,找到高級設置崖堤。


      image.png
    • 我們在入站規(guī)則中找到“文件和打印機共享(回顯請求 - ICMPv4-In)”侍咱,然后啟動該規(guī)則即可解決問題。


      image.png
    • 但是我們又發(fā)現(xiàn)一個問題密幔,我們ping不通www.baidu.com楔脯,這個問題就很操蛋了。

      image.png

    • 我們只需要把nameserver 設置為 114.114.114.114就能解決虛擬機ping不通外網(wǎng)的問題胯甩。


      image.png

      image.png

后續(xù)更新文章

如果你沒有插網(wǎng)線的話, ifconfig應該是沒有本地適配器的ip昧廷。反之你是wifi連接的話,ifconfig會出現(xiàn)網(wǎng)卡的ip和網(wǎng)關偎箫。我們在配置虛擬機使 ip和網(wǎng)卡的ip在同一網(wǎng)段木柬,網(wǎng)關應該和電腦網(wǎng)卡保持一致即可。

Vmware的三種模式配置,我之前這篇文章有講過你應該知道的VirtualBox虛擬機網(wǎng)絡配置

這里我再復述一遍(以前內容取自于網(wǎng)絡):

  • VMWare提供了三種工作模式淹办,它們是bridged(橋接模式)眉枕、NAT(網(wǎng)絡地址轉換模式)和host-only(主機模式)。要想在網(wǎng)絡管理和維護中合理應用它們,你就應該先了解一下這三種工作模式速挑。

  • Bridged(橋接模式)

    • 在這種模式下谤牡,VMWare虛擬出來的操作系統(tǒng)就像是局域網(wǎng)中的一臺獨立的主機,它可以訪問網(wǎng)內任何一臺機器梗摇。在橋接模式下,你需要手工為虛擬系統(tǒng)配置IP地址想许、子網(wǎng)掩碼伶授,而且還要和宿主機器處于同一網(wǎng)段,這樣虛擬系統(tǒng)才能和宿主機器進行通信流纹。同時糜烹,由于這個虛擬系統(tǒng)是局域網(wǎng)中的一個獨立的主機系統(tǒng),那么就可以手工配置它的TCP/IP配置信息漱凝,以實現(xiàn)通過局域網(wǎng)的網(wǎng)關或路由器訪問互聯(lián)網(wǎng)疮蹦。
    • 使用橋接模式的虛擬系統(tǒng)和宿主機器的關系,就像連接在同一個Hub上的兩臺電腦茸炒。想讓它們相互通訊愕乎,你就需要為虛擬系統(tǒng)配置IP地址和子網(wǎng)掩碼,否則就無法通信壁公。
    • 如果你想利用VMWare在局域網(wǎng)內新建一個虛擬服務器感论,為局域網(wǎng)用戶提供網(wǎng)絡服務,就應該選擇橋接模式紊册。
  • host-only(主機模式)

    • 在某些特殊的網(wǎng)絡調試環(huán)境中比肄,要求將真實環(huán)境和虛擬環(huán)境隔離開,這時你就可采用host-only模式囊陡。在host-only模式中芳绩,所有的虛擬系統(tǒng)是可以相互通信的,但虛擬系統(tǒng)和真實的網(wǎng)絡是被隔離開的撞反。
    • 提示:在host-only模式下妥色,虛擬系統(tǒng)和宿主機器系統(tǒng)是可以相互通信的,相當于這兩臺機器通過雙絞線互連遏片。
    • 在host-only模式下垛膝,虛擬系統(tǒng)的TCP/IP配置信息(如IP地址、網(wǎng)關地址丁稀、DNS服務器等)吼拥,都是由VMnet1(host-only)虛擬網(wǎng)絡的DHCP服務器來動態(tài)分配的。
    • 如果你想利用VMWare創(chuàng)建一個與網(wǎng)內其他機器相隔離的虛擬系統(tǒng)线衫,進行某些特殊的網(wǎng)絡調試工作凿可,可以選擇host-only模式。
  • NAT(網(wǎng)絡地址轉換模式)

    • 使用NAT模式,就是讓虛擬系統(tǒng)借助NAT(網(wǎng)絡地址轉換)功能枯跑,通過宿主機器所在的網(wǎng)絡來訪問公網(wǎng)惨驶。也就是說,使用NAT模式可以實現(xiàn)在虛擬系統(tǒng)里訪問互聯(lián)網(wǎng)敛助。NAT模式下的虛擬系統(tǒng)的TCP/IP配置信息是由VMnet8(NAT)虛擬網(wǎng)絡的DHCP服務器提供的粗卜,無法進行手工修改,因此虛擬系統(tǒng)也就無法和本局域網(wǎng)中的其他真實主機進行通訊纳击。采用NAT模式最大的優(yōu)勢是虛擬系統(tǒng)接入互聯(lián)網(wǎng)非常簡單续扔,你不需要進行任何其他的配置,只需要宿主機器能訪問互聯(lián)網(wǎng)即可焕数。
    • 如果你想利用VMWare安裝一個新的虛擬系統(tǒng)纱昧,在虛擬系統(tǒng)中不用進行任何手工配置就能直接訪問互聯(lián)網(wǎng),建議你采用NAT模式堡赔。
提示:以上所提到的NAT模式下的VMnet8虛擬網(wǎng)絡识脆,host-only模式下的VMnet1虛擬網(wǎng)絡,以及bridged模式下的VMnet0虛擬網(wǎng)絡善已,都是由VMWare虛擬機自動配置而生成的灼捂,不需要用戶自行設置。VMnet8和VMnet1提供DHCP服務换团,VMnet0虛擬網(wǎng)絡則不提供纵东。

言歸正傳, 如果你的虛擬機出現(xiàn)了ping不通百度的情況。一個原因是DNS,另一個原因就是沒有配置VMware Virtual Ethernet Adapter for VMnet8 的ip和網(wǎng)關地址啥寇。 這里的ip同樣要和電腦網(wǎng)卡的ip處于同一網(wǎng)段, 網(wǎng)關地址和電腦網(wǎng)卡一樣即可偎球。

這里在衍生一個問題。 同一個物理地址下內的不同邏輯網(wǎng)段能否通信 ?

  • 小馬 :其實是不能的辑甜。這里要扯出子網(wǎng)掩碼的概念衰絮,子網(wǎng)掩碼不能單獨存在,它必須結合IP地址一起使用磷醋。子網(wǎng)掩碼只有一個作用猫牡,就是將某個IP地址劃分成網(wǎng)絡地址和主機地址。

  • 小馬: 例如兩臺電腦分別是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,數(shù)據(jù)包可以發(fā)送到骇陈,但是192.168.0.135這臺電腦僅能訪問192.168.0.129-254震庭,所以返回的數(shù)據(jù)不能直接傳給192.168.0.1,而是要把數(shù)據(jù)發(fā)給網(wǎng)關進行轉發(fā)你雌,如果沒有網(wǎng)關器联,則會將數(shù)據(jù)包丟棄二汛。

  • 小馬: 192.168.0.1/24,說明前24位是網(wǎng)絡地址, 后8位是主機地址。如果要算廣播IP的話拨拓,就是主機地址都為1肴颊。因此我們可以算出其子網(wǎng)掩碼是255.255.255.0。子網(wǎng)掩碼按位與IP地址可以算出網(wǎng)絡地址是192.168.0.0, 廣播地址是192.168.0.255渣磷。子網(wǎng)掩碼的長度也是32位婿着,左邊是網(wǎng)絡位,用二進制數(shù)字“1”表示醋界,1的數(shù)目等于網(wǎng)絡位的長度竟宋;右邊是主機位,用二進制數(shù)字“0”表示物独,0的數(shù)目等于主機位的長度袜硫。這樣做的目的是為了讓掩碼與ip地址做按位與運算時用0遮住原主機數(shù)氯葬,而不改變原網(wǎng)絡段數(shù)字挡篓,而且很容易通過0的位數(shù)確定子網(wǎng)的主機數(shù)(2的主機位數(shù)次方-2,因為主機號全為1時表示該網(wǎng)絡廣播地址帚称,全為0時表示該網(wǎng)絡的網(wǎng)絡號官研,這是兩個特殊地址)。所以我們可以算出子網(wǎng)的ip數(shù)是2的8次方 - 2 = 254(第一個地址是網(wǎng)絡地址和最后一個地址是廣播地址, 需要去掉)闯睹。那么其子網(wǎng)ip的范圍就是192.168.0.1 - 192.168.0.254

  • 小馬: 同理可得192.168.0.135/25的子網(wǎng)掩碼是255.255.255.128戏羽,網(wǎng)絡地址是192.168.0.128,廣播地址是192.168.0.255,子網(wǎng)ip范圍是192.168.0.129-192.168.0.254楼吃。子網(wǎng)ip數(shù)量=2的7次方-2 = 126始花。所以解答了同一物理地址下內的不同邏輯網(wǎng)段是不能通信的。

  • 小馬: 擴展知識, 網(wǎng)絡地址=IP地址&子網(wǎng)掩碼, 主機地址=IP地址&按位非(子網(wǎng)掩碼)孩锡,廣播地址=主機位都是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無法找到控制器并把請求分發(fā)到控制器默垄。" 當我剛開始學習SpringMVC的時候此虑,就看過這篇文章,這篇文章某些觀點的確解決了我的一些開發(fā)問題口锭,但是我上面列舉的作者觀點就錯的有點離譜寡壮。 下面我就用代碼去證明這個觀點是錯的!
    • 我們在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這個鏈接嗎癞尚?” 答案是不能訪問!B叶浮浇揩!
@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(終于可以還債了)。

    • 創(chuàng)建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");
    }
}
  • 創(chuàng)建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");
    }
}
  • 創(chuàng)建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和返回的視圖凳忙,我們發(fā)現(xiàn)了Interceptor1執(zhí)行了preHandler()、postHandler()禽炬、afterCompletion()這三個方法涧卵,而Interceptor2只執(zhí)行了preHandler()這個方法。通過比較它們的源碼腹尖,我們發(fā)現(xiàn)了Interceptor1的preHandler()返回的是true柳恐,而Interceptor2的preHandler()返回的是false。而第一個url我們攔截了請求热幔,返回了視圖乐设,第二個url我們攔截了請求,返回沒有視圖绎巨。

  • preHandle方法是進行處理攔截用的近尚,該方法將在Controller處理之前調用,Interceptor攔截器是鏈式的场勤,并且可以中斷戈锻,當返回false的時候整個請求結束。

  • 當preHandle返回true時却嗡,postHandle()才會執(zhí)行舶沛,在Controller的方法調用之后執(zhí)行嘹承,但是它會在DispatcherServlet進行視圖的渲染之前執(zhí)行窗价。

  • 當preHandle返回ture才會執(zhí)行,該方法將在整個請求完成之后叹卷,也就是DispatcherServlet渲染視完畢才執(zhí)行撼港,主要作用是情理資源。

  • 從啟動日志來看骤竹,Listener > Filter > Interceptor > Servlet帝牡,自定義Listener和Filter很簡單,也不需要講蒙揣。


What to do tomorrow

  • 明天去看FastDFS的集群和負載均衡靶溜,Spring Security的demo又要delay了。

Summary

笨鳥先飛

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末懒震,一起剝皮案震驚了整個濱河市罩息,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌个扰,老刑警劉巖瓷炮,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異递宅,居然都是意外死亡娘香,警方通過查閱死者的電腦和手機苍狰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烘绽,“玉大人淋昭,你說我怎么就攤上這事“步樱” “怎么了响牛?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赫段。 經(jīng)常有香客問我呀打,道長召调,這世上最難降的妖魔是什么搁嗓? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮鹃共,結果婚禮上给涕,老公的妹妹穿的比我還像新娘豺憔。我一直安慰自己,他們只是感情好够庙,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布恭应。 她就那樣靜靜地躺著,像睡著了一般耘眨。 火紅的嫁衣襯著肌膚如雪昼榛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天剔难,我揣著相機與錄音胆屿,去河邊找鬼。 笑死偶宫,一個胖子當著我的面吹牛非迹,可吹牛的內容都是我干的。 我是一名探鬼主播纯趋,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼憎兽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吵冒?” 一聲冷哼從身側響起纯命,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桦锄,沒想到半個月后扎附,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡结耀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年留夜,在試婚紗的時候發(fā)現(xiàn)自己被綠了匙铡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡碍粥,死狀恐怖鳖眼,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情嚼摩,我是刑警寧澤钦讳,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站枕面,受9級特大地震影響愿卒,放射性物質發(fā)生泄漏。R本人自食惡果不足惜潮秘,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一琼开、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枕荞,春花似錦柜候、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矗烛,卻和暖如春辅柴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背高诺。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工碌识, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碾篡,地道東北人虱而。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像开泽,于是被迫代替她去往敵國和親牡拇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理穆律,服務發(fā)現(xiàn)惠呼,斷路器,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 一.防火墻概念 (一)安全技術介紹 (1) 入侵檢測與管理系統(tǒng)(Intrusion Detection Syste...
    楠人幫閱讀 1,477評論 0 3
  • 1 基于LVS-NAT的設計:實現(xiàn)nat模式的lvs實驗 搭建環(huán)境:先將各主機的防火墻策略和selinux關閉,打...
    楠人幫閱讀 1,147評論 0 0
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評論 6 342
  • 這個好像是個面試題吧 順序是這樣的:viewDidLoad(控制器的View加載完)—》viewWillApper...
    凡塵一笑閱讀 330評論 0 0