天天看點

Java單體應用 - 常用架構 - 07.Spring MVC - 項目重構(iot-admin3)項目重構(iot-admin3)

原文位址: http://www.work100.net/training/monolithic-frameworks-spring-mvc-iot-admin3.html 更多教程: 光束雲 - 免費課程

項目重構(iot-admin3)

請參照如上

章節導航

進行閱讀

1.概述

我們繼續以上一章節

Spring Web

中的案例項目

iot-admin2

為基礎,複制一份重命名為

iot-admin3

,修改

pom.xml

<artifactId>iot-admin3</artifactId>

接下來我們使用

Spring MVC

重構

iot-admin3

項目。

2.配置和結構重構

2.1.修改POM

spring-web

的依賴改為對

spring-webmvc

的依賴,同時删除對

spring-context

的依賴:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>           

spring-webmvc

中已經依賴了

spring-web

spring-context

完整的

pom.xml

代碼如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.work100.training.stage2</groupId>
    <artifactId>iot-admin3</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <spring.version>5.2.3.RELEASE</spring.version>
        <javax.servlet-api.version>4.0.1</javax.servlet-api.version>
        <javax.jstl.version>1.2</javax.jstl.version>
        <junit.version>4.12</junit.version>
        <slf4j.version>1.7.25</slf4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${javax.servlet-api.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${javax.jstl.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>
</project>           

2.2.配置 web.xml

CharacterEncodingFilter

配置字元集過濾器,用于解決中文編碼問題

<filter>
    <filter-name>encodingFilter</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>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>           

DispatcherServlet

配置 Spring 的

Servlet

分發器處理所有 HTTP 的

請求

響應

<servlet>
    <servlet-name>springServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/spring-mvc*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>           

load-on-startup

标記容器是否在啟動的時候就加載這個servlet,當值為0或者大于0時,表示容器在應用啟動時就加載這個servlet;當是一個負數時或者沒有指定時,則訓示容器在該servlet被選擇時才加載;當為正數時,其值越小,啟動該servlet的優先級越高。

完整

web.xml

<?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_4_0.xsd"
         version="4.0">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <filter>
        <filter-name>encodingFilter</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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>springServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:/spring-mvc*.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>           

2.3.配置 spring-mvc.xml

在目錄

src/main/resources

下建立檔案

spring-mvc.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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">

    <description>Spring MVC Configuration</description>

    <!-- 加載配置屬性檔案 -->
    <context:property-placeholder ignore-unresolvable="true" location="classpath:iot-admin.properties"/>

    <!-- 使用 Annotation 自動注冊 Bean,隻掃描 @Controller -->
    <context:component-scan base-package="net.work100.training.stage2.iot.admin" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 預設的注解映射的支援 -->
    <mvc:annotation-driven />

    <!-- 定義視圖檔案解析 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="${web.view.prefix}"/>
        <property name="suffix" value="${web.view.suffix}"/>
    </bean>

    <!-- 靜态資源映射 -->
    <mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>
</beans>           

相關配置說明:

  • context:property-placeholder

    :動态加載屬性配置檔案以變量的方式引用需要的值
  • context:component-scan

    :目前配置檔案為

    MVC

    相關,故隻需要掃描包含

    @Controller

    的注解即可,由于

    spring-context.xml

    配置檔案中也配置了包掃描,是以還需要排除

    @Controller

    的注解掃描。
  • InternalResourceViewResolver

    :視圖檔案解析器的一種,用于配置視圖資源的路徑和需要解釋的視圖資源檔案類型,這裡有兩個需要配置的屬性

    prefix

    (字首)以及

    suffix

    (字尾)。
    • prefix

      :配置視圖資源路徑,如:

      /WEB-INF/views/

    • suffix

      :配置視圖資源類型,如:

      .jsp

  • mvc:resources

    :靜态資源映射,主要用于配置靜态資源檔案存放路徑,如:

    JS

    CSS

    Image

2.4.配置及結構完善

配置 iot-admin.properties

spring-mvc.xml

中,我們配置了

<context:property-placeholder ignore-unresolvable="true" location="classpath:iot-admin.properties"/>

用于動态加載屬性配置檔案,實際開發中我們會将系統所需的一些配置資訊封裝到

.properties

配置檔案中便于統一的管理。

src/main/resources

下建立一個名為

iot-admin.properties

的配置檔案,内容如下:

#============================#
#==== Framework settings ====#
#============================#

# views path
web.view.prefix=/WEB-INF/views/
web.view.suffix=.jsp           

重構項目結構

WEB-INF

下建立目錄

views

,然後将

.jsp

檔案移動到

views

下。

webapp

static

assets

檔案夾及其所屬檔案移動到

static

目錄結構如下圖:

Java單體應用 - 常用架構 - 07.Spring MVC - 項目重構(iot-admin3)項目重構(iot-admin3)

2.5.修改 spring-context.xml

由于

spring-mvc.xml

中已經配置了

@Controller

注解的掃描,而

spring-context.xml

中配置的是掃描全部注解,故在這裡需要将

@Controller

注解的掃描配置排除。

修改

spring-context.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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <!-- 使用 Annotation 自動注冊 Bean,在主容器中不掃描 @Controller 注解,在 SpringMVC 中隻掃描 @Controller 注解。-->
    <context:component-scan base-package="net.work100.training.stage2.iot.admin">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>           

3.Controller控制器重構

3.1.修改注解方式

UserDaoImpl 類

UserDaoImpl

類的注解方式,代碼如下:

package net.work100.training.stage2.iot.admin.dao.impl;

import net.work100.training.stage2.iot.admin.dao.UserDao;
import net.work100.training.stage2.iot.admin.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

/**
 * <p>Title: UserDaoImpl</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-frameworks-spring-mvc.html</p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:23
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始建立
 * -----------------------------------------------
 */
@Repository
public class UserDaoImpl implements UserDao {

    private static final Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);

    public User getUser(String loginId, String loginPwd) {
        logger.debug("調用方法 getUser(loginId:{}, loginPwd:{})", loginId, loginPwd);

        // 根據 loginId 查詢出使用者資訊
        User user = getUserByLoginId(loginId);
        if (user != null) {
            // 驗證 loginPwd 是否正确(區分大小寫)
            if (user.getLoginPwd().equals(loginPwd)) {
                return user;
            }
        }
        return null;
    }


    /**
     * 擷取模拟的使用者資料
     *
     * @param loginId 登入ID
     * @return
     */
    private User getUserByLoginId(String loginId) {
        // 模拟 DB 存在的使用者資料
        User dbUser = new User();
        dbUser.setUserName("Xiaojun");
        dbUser.setLoginId("admin");
        dbUser.setLoginPwd("admin");

        // 判斷是否存在 loginId 的使用者(忽略大小寫)
        if (dbUser.getLoginId().equalsIgnoreCase(loginId)) {
            logger.info("比對上使用者:{}", dbUser);
            return dbUser;
        }
        logger.warn("未比對任何使用者,将傳回 null");
        return null;
    }
}           

UserServiceImpl 類

UserServiceImpl

package net.work100.training.stage2.iot.admin.service.impl;

import net.work100.training.stage2.iot.admin.dao.UserDao;
import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * <p>Title: UserServiceImpl</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-frameworks-spring-mvc.html</p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:26
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始建立
 * -----------------------------------------------
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    public User login(String loginId, String loginPwd) {
        return userDao.getUser(loginId, loginPwd);
    }
}           

注解說明

  • @Repository :不需要指定名稱,因為隻有一個實作類
  • @Service : 不需要指定名稱,因為隻有一個實作類
  • @Autowired :自動注入,Spring 自動尋找實作類來執行個體化對象

3.2.重構 Controller 代碼

修改 LoginController

LoginController

類,代碼如下:

package net.work100.training.stage2.iot.admin.web.controller;

import net.work100.training.stage2.iot.admin.entity.User;
import net.work100.training.stage2.iot.admin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * <p>Title: LoginController</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-frameworks-spring-mvc.html</p>
 *
 * @author liuxiaojun
 * @date 2020-02-13 13:28
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-13   liuxiaojun     初始建立
 * -----------------------------------------------
 */
@Controller
public class LoginController {

    @Autowired
    private UserService userService;

    /**
     * 登入頁面
     *
     * @return
     */
    @RequestMapping(value = {"", "login"}, method = RequestMethod.GET)
    public String login() {
        return "login";
    }

    /**
     * 登入邏輯
     *
     * @param loginId  登入ID
     * @param loginPwd 登入密碼
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    public String login(@RequestParam(required = true) String loginId, @RequestParam(required = true) String loginPwd) {

        User user = userService.login(loginId, loginPwd);

        // 登入成功
        if (user != null) {
            return "redirect:main";
        }
        // 登入失敗
        else {
            return login();
        }
    }

}           

建立 MainController

建立

MainController

package net.work100.training.stage2.iot.admin.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * <p>Title: MainController</p>
 * <p>Description: </p>
 *
 * @author liuxiaojun
 * @date 2020-02-20 15:19
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-20   liuxiaojun     初始建立
 * -----------------------------------------------
 */
@Controller
public class MainController {

    /**
     * 首頁
     *
     * @return
     */
    @RequestMapping(value = "main", method = RequestMethod.GET)
    public String main() {
        return "main";
    }
}           

運作

重新啟動

Tomcat

驗證效果。

  • @Controller

Spring MVC

中,控制器

Controller

負責處理由

DispatcherServlet

分發的請求,它把使用者請求的資料經過業務處理層處理之後封裝成一個

Model

,然後再把該

Model

傳回給對應的

View

進行展示。

Spring MVC

中提供了一個非常簡便的定義

Controller

的方法,你無需繼承特定的類或實作特定的接口,隻需使用

@Controller

标記一個類是

Controller

,然後使用

@RequestMapping

@RequestParam

等一些注解用以定義

URL 請求

Controller 方法

之間的映射,這樣的 Controller 就能被外界通路到。

此外

Controller

不會直接依賴于

HttpServletRequest

HttpServletResponse

HttpServlet

對象,它們可以通過

Controller

的方法參數靈活的擷取到。

@Controller

用于标記在一個類上,使用它标記的類就是一個

Spring MVC Controller

對象。

分發處理器将會掃描使用了該注解的類的方法,并檢測該方法是否使用了

@RequestMapping

注解。

@Controller

隻是定義了一個控制器類,而使用

@RequestMapping

注解的方法才是真正處理請求的處理器。

  • @RequestMapping

RequestMapping

是一個用來處理請求位址映射的注解,可用于類或方法上。用于類上,表示類中的所有響應請求的方法都是以該位址作為父路徑。

RequestMapping

注解有六個屬性:

  • value

    method

    • value

      :指定請求的實際位址,指定的位址可以是 URI Template 模式
    • method

      :指定請求的method類型,

      GET

      POST

      PUT

      DELETE

  • consumes

    produces

    • consumes

      :指定處理請求的送出内容類型(

      Content-Type

      ),例如

      application/json

      ,

      text/html

    • produces

      : 指定傳回的内容類型,僅當 request 請求頭中的(

      Accept

      )類型中包含該指定類型才傳回
  • params

    headers

    • params

      :指定 request 中必須包含某些參數值是,才讓該方法處理
    • headers

      :指定 request 中必須包含某些指定的

      header

      值,才能讓該方法處理請求

4.使用攔截器

4.1.簡介

Spring Web MVC 的處理器攔截器,類似于 Servlet 開發中的過濾器 Filter,用于對處理器進行預處理和後處理。

4.2.應用場景

  • 日志記錄:記錄請求資訊的日志,以便進行資訊監控、資訊統計、計算 PV(Page View)等
  • 權限檢查:如登入檢測,進入處理器檢測檢測是否登入,如果沒有直接傳回到登入頁面
  • 性能監控:有時候系統在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完後記錄結束時間,進而得到該請求的處理時間
  • 通用行為:讀取 Cookie 得到使用者資訊并将使用者對象放入請求,進而友善後續流程使用,還有如提取 Locale、Theme 資訊等,隻要是多個處理器都需要的即可使用攔截器實作

4.3.如何使用攔截器

  • Spring MVC 攔截器需要實作

    HandlerInterceptor

    接口,該接口定義了

    3

    個方法,分别為:
    • preHandle()

    • postHandle()

    • afterCompletion()

通過重寫這 3 個方法來對使用者的請求進行攔截處理的。

  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)

該方法在請求處理之前進行調用。Spring MVC 中的 Interceptor 是鍊式調用的,在一個應用中或者說是在一個請求中可以同時存在多個 Interceptor 。

每個 Interceptor 的調用會依據它的聲明順序依次執行,而且最先執行的都是 Interceptor 中的

preHandle

方法,是以可以在這個方法中進行一些前置初始化操作或者是對目前請求做一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。

該方法的傳回值是布爾值

Boolean

類型的,當它傳回為

false

時,表示請求結束,後續的 Interceptor 和 Controller 都不會再執行;當傳回值為

true

時,就會繼續調用下一個 Interceptor 的

preHandle

方法,如果已經是最後一個 Interceptor 的時候,就會是調用目前請求的 Controller 中的方法。

  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)

通過

preHandle

方法的解釋咱們知道這個方法包括後面要說到的

afterCompletion

方法都隻能在目前所屬的 Interceptor 的

preHandle

方法的傳回值為

true

的時候,才能被調用。

postHandle

方法在目前請求進行處理之後,也就是在 Controller 中的方法調用之後執行,但是它會在 DispatcherServlet 進行視圖傳回渲染之前被調用,是以咱們可以在這個方法中對 Controller 處理之後的 ModelAndView 對象進行操作。

postHandle

方法被調用的方向跟

preHandle

是相反的,也就是說,先聲明的 Interceptor 的

postHandle

方法反而會後執行。

  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)

也是需要目前對應的 Interceptor 的 preHandle 方法的傳回值為

true

時才會執行。

是以,該方法将在整個請求結束之後,也就是在 DispatcherServlet 渲染了對應的視圖之後執行,這個方法的主要作用是用于進行資源清理的工作。

4.4.建立登入攔截器

我們知道對系統的相關操作是需要登入後才可以使用的,當未登入時是無法直接通路需要登入權限的操作的,為了做到這個效果,我們使用登入攔截器來判斷使用者是否登入,如果使用者已登入則放行讓使用者繼續操作,否則就将其跳轉到登入頁。

net.work100.training.stage2.iot.admin.web

包下建立一個包

interceptor

,然後在

interceptor

包下定義一個名為

LoginInterceptor

的攔截器,代碼如下:

package net.work100.training.stage2.iot.admin.web.interceptor;

import net.work100.training.stage2.iot.admin.entity.User;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * <p>Title: LoginInterceptor</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-frameworks-spring-mvc.html</p>
 *
 * @author liuxiaojun
 * @date 2020-02-20 16:22
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-20   liuxiaojun     初始建立
 * -----------------------------------------------
 */
public class LoginInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("LoginInterceptor");

        User user = (User) request.getSession().getAttribute("user");

        // 未登入
        if (user == null) {
            response.sendRedirect("/login");
        }

        // 為 true 時放行,進入 postHandle
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}           

LoginInterceptor

攔截器的主要功能是檢測使用者是否登入,如果未登入則跳轉至登入頁(/login)

4.5.在 spring-mvc.xml 中配置攔截器

攔截器定義後還需要在

spring-mvc.xml

中配置攔截器,代碼如下:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/login"/>
        <mvc:exclude-mapping path="/static/**"/>
        <bean class="net.work100.training.stage2.iot.admin.web.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>           
  • mvc:interceptor

    :定義一個攔截器
    • mvc:mapping

      :映射路徑,需要攔截的請求路徑
    • mvc:exclude-mapping

      :需要排除的請求路徑,比如登入頁本身是不需要攔截的,這裡還包括了靜态資源路徑也是不需要攔截的
    • bean class

      :配置指定的攔截器對象

4.6.完善使用場景

我們實際的使用場景中還應該有個判斷邏輯:當使用者已經登入了,通路

/login

時,需要将請求跳轉至

/main

建立攔截器 PermissionInterceptor

這時我們需要再建立一個攔截器

PermissionInterceptor

package net.work100.training.stage2.iot.admin.web.interceptor;

import net.work100.training.stage2.iot.admin.entity.User;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * <p>Title: PermissionInterceptor</p>
 * <p>Description: </p>
 * <p>Url: http://www.work100.net/training/monolithic-frameworks-spring-mvc.html</p>
 *
 * @author liuxiaojun
 * @date 2020-02-20 21:16
 * ------------------- History -------------------
 * <date>      <author>       <desc>
 * 2020-02-20   liuxiaojun     初始建立
 * -----------------------------------------------
 */
public class PermissionInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("PermissionInterceptor");

        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if ("login".equals(modelAndView.getViewName())) {
            User user = (User) request.getSession().getAttribute("user");
            if (user != null) {
                response.sendRedirect("/main");
            }
        }
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}           

修改 spring-mvc.xml 配置

增加

PermissionInterceptor

攔截器的配置,代碼如下:

<!-- 攔截器配置(攔截器的執行順序為:從下往上) -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/login"/>
        <mvc:exclude-mapping path="/static/**"/>
        <bean class="net.work100.training.stage2.iot.admin.web.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="net.work100.training.stage2.iot.admin.web.interceptor.PermissionInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>           
攔截器的執行順序為:從下往上,即先定義的後執行

spring-mvc.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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">

    <description>Spring MVC Configuration</description>

    <!-- 加載配置屬性檔案 -->
    <context:property-placeholder ignore-unresolvable="true" location="classpath:iot-admin.properties"/>

    <!-- 使用 Annotation 自動注冊 Bean,隻掃描 @Controller -->
    <context:component-scan base-package="net.work100.training.stage2.iot.admin" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 預設的注解映射的支援 -->
    <mvc:annotation-driven/>

    <!-- 定義視圖檔案解析 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="${web.view.prefix}"/>
        <property name="suffix" value="${web.view.suffix}"/>
    </bean>

    <!-- 靜态資源映射 -->
    <mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>

    <!-- 攔截器配置(攔截器的執行順序為:從下往上) -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login"/>
            <mvc:exclude-mapping path="/static/**"/>
            <bean class="net.work100.training.stage2.iot.admin.web.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="net.work100.training.stage2.iot.admin.web.interceptor.PermissionInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>
</beans>           

4.7.運作驗證

重新開機

Tomcat

,分别驗證

LoginInterceptor

PermissionInterceptor

攔截器是否生效。

5.執行個體源碼

執行個體源碼已經托管到如下位址:

上一篇:

簡介

下一篇:

Maven 子產品化開發
如果對課程内容感興趣,可以掃碼關注我們的

公衆号

QQ群

,及時關注我們的課程更新
Java單體應用 - 常用架構 - 07.Spring MVC - 項目重構(iot-admin3)項目重構(iot-admin3)
Java單體應用 - 常用架構 - 07.Spring MVC - 項目重構(iot-admin3)項目重構(iot-admin3)