Day 21 - Spring Boot & Filter

若在开发时想要在请求到达Controller 前或回应离开Controller 後执行一些业务逻辑,比如进入Controller 前判断是否已经登入或是是否有请求路径的访问权限等功能,可以使用过滤器或拦截器两个方法进行处理。

Filter 过滤器

Filter 是Web Server 的一部份,不是Spring 框架自带的,所以我们可以HTTP 请求到达Servlet 前或在HTTP 回应回传给Client 端前进行拦截,拦截成功就可以实作一些自定义的业务逻辑或对回应资料进行修改,而Spring Security 就是一个很好的Filter 实作方法,可以透过Spring Security 配置进行授权与认证等功能。

常用注释

  1. @Order : 表示过滤顺序,其值越小越优先执行。
  2. @WebFilter : 宣告这是一个过滤器类别,Spring 会根据其属性配置过滤器,主要属性如下。
    1. filterName : 指定Filter 名称。
    2. value : 指定拦截路径,与urlPatterns 择一使用。
    3. urlPatterns : 指定拦截路径,与value 择一使用。
    4. servletNames : 设定Filter 过滤哪些Servlet 的请求。
    5. dispatcherTypes : 设定Filter 过滤哪种请求方式,属性有ASYNC、ERROR、FORWARD、INCLUDE、REQUEST,预设为全选。
    6. initParams : 设定Filter 初始化参数。
    7. asyncSupported : 设定Filter 是否支援异步模式,预设为false。
    8. description : 描述Filter 用途。
    9. displayName : 指定Filter 显示名称。

实作

建立一个LoginFilter

要建立一个Filter 有两种常见的方法,一种是实作javax.servlet.Filter 介面,另一种则是继承org.springframework.web.filter.OncePerRequestFilter 类别,使用方法上基本差不多,这边就仅展示实作javax.servlet.Filter 介面的方法。

package com.example.iThomeIronMan.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.example.iThomeIronMan.model.Member;

@Component
@WebFilter(filterName = "", urlPatterns = {"/*"})
@Order(value = 1)
public class LoginFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub

		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		HttpSession session = req.getSession();
		Member member = (Member) session.getAttribute("MemberSession");

		String uri = new String(req.getRequestURI());

		// 放行所有静态档案
		if(uri.contains("/css") || uri.contains("/images") || uri.contains("/js")) {
			chain.doFilter(request, response);
			return ;
		}

		// 已登入
		if(member != null) {
			System.err.println("Been Login");
			if(uri.contains("/login") || uri.contains("/register")) {
				res.sendRedirect("/information");
			}
			else {
				chain.doFilter(request, response);
			}
		}
		// 未登入
		else {
			System.err.println("No Login");
			if(uri.contains("/login") || uri.contains("/register")) {
				chain.doFilter(request, response);
			}
			else {
				res.sendRedirect("/login");
			}
		}
	}

}

启动类别新增@ServletComponentScan 注释

注意使用@WebServlet、@WebFilter、@WebListener 等Servlet 注释时需要在Spring Boot 的启动类别上添加@ServletComponentScan 注释,否则不会生效。

package com.example.iThomeIronMan;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class IThomeIronManApplication {

	public static void main(String[] args) {
		SpringApplication.run(IThomeIronManApplication.class, args);
	}

}

参考网站

spring-boot实现增加自定义filter(新)
SpringBoot基於注解方式配置Filter
SpringBoot中使用Filter丶Java教程网-IT开发者们的技术天堂


<<:  D 30 Python x Django 学习心得

>>:  AI & machine learning 组别

Day 13:为自己的 Hexo 部落格增加 Disqus 留言功能(使用 Next 布景主题)

Hexo 虽然是静态网页产生器,因此不会像 WordPress 那样本身就内建内容储存在资料库的文章...

Day 17 UItableView的练习 (1/3)

上次做过调色盘的练习,对基本的东西有一些认识之後我们开始继续往下练习~ 其实TableViewy我们...

Day 07 关键字分析工具介绍

我们前面几章提到关键字的规划原则,我们都很有共识,关键字是要依据潜在消费者的搜寻需求所拟定出来的。 ...

Day-30 资讯安全宣导

资讯安全宣导 tags: IT铁人 何谓资讯安全 随着资讯科技进步,资讯安全的重要程度日渐提升,以杰...

Day6 Redis组态档设定-SNAPSHOT

Redis.config SNAPSHOT save Redis Server 依照需求将资料存在硬...