フィルター (Filter) とインターセプター (Interceptor) は、Web 開発で一般的に使用される 2 つの概念であり、HTTP リクエストと応答を処理および制御するために使用されます。これらは通常、認証、ロギング、セキュリティチェックなどのいくつかの一般的な機能を実装するために使用されます。
1. 2 つの違い:
フィルターはサーブレットベースのアプリケーションに適しており、インターセプターは Spring MVC を使用するプロジェクトに適しています。
- フィルターはサーブレット仕様によって提供されるメカニズムであり、主に HTTP リクエストと応答の処理中にインターセプトおよび処理するために使用されます。フィルターはリクエストとレスポンスを変更したり、一部の属性やヘッダー情報などを追加または削除したりできます。これらは、サーブレットに入る前のリクエストの前処理や、クライアントに返される前のレスポンスの後処理など、グローバル プロセスで使用できます。
- インターセプターは、Spring MVC フレームワークで HTTP リクエストをインターセプトして処理するために Spring フレームワークによって提供されるメカニズムです。インターセプターは、コントローラーに入る前または後にいくつかの操作を実行するなど、よりきめ細かい方法でリクエストの処理フローを制御できます。
2、フィルター
使用手順:
1) フィルターの定義: クラスを定義し、フィルター インターフェイスを実装し、そのすべてのメソッドをオーバーライドします。
ログイン検証機能の実装例を次に示します。
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 将通用的 ServletRequest 转换为 HttpServletRequest
HttpServletRequest req = (HttpServletRequest) servletRequest;
// 将通用的 ServletResponse 转换为 HttpServletResponse
HttpServletResponse resp = (HttpServletResponse) servletResponse;
// 1、获取请求url
String url = req.getRequestURI().toString();
// 2、判断请求url中是否包含login,如果包含,说明是登录操作,放行。
if (url.contains("login")){
//放行操作
filterChain.doFilter(servletRequest,servletResponse);
return;
}
// 3、获取请求头中的令牌(token)。
String jwt = req.getHeader("token");
// 4、判断令牌是否存在,如果不存在,返回错误结果(未登录)。
if (!StringUtils.hasLength(jwt)){
Result error = Result.error("NOT LOGIN");
//手动转换,将对象转换为json格式 <-----阿里巴巴fastjson
String notLogin = JSONObject.toJSONString(error);
//将该字符串响应给前端
resp.getWriter().write(notLogin);
return;
}
// 5、解析token,如果解析失败,返回错误结果(未登录)。
try {
JwtUtils.parseJWT(jwt);
}catch (Exception e){//解析失败
e.printStackTrace();
Result error = Result.error("NOT LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
// 6、放行。
filterChain.doFilter(servletRequest,servletResponse);
}
}
まず、フィルターにメソッドを実装する場合、通常は、より多くのサーブレット API 機能を使用できるように、受信リクエスト ( ) とレスポンス ( )doFilter
で型変換を実行する必要があります。したがって、ここでのコードの最初の 2 行は、汎用のとをに変換して、HTTP リクエストと応答のより豊富な機能にアクセスできるようにします。ServletRequest
ServletResponse
ServletRequest
ServletResponse
HttpServletRequest
HttpServletResponse
次に、ログイン認証の 5 つの手順に従います: 1. リクエスト URL を取得します; 2. リクエスト URL にログインが含まれているかどうかを確認します。含まれている場合は、ログイン操作であることを意味し、そのままにしておきます; 3. トークンを取得します。リクエストヘッダー (ここでの私の仕様) トークンはトークンと呼ばれます); 4. トークンが存在するかどうかを確認します。存在しない場合は、エラー結果を返します (ログインしていません); 5. トークンを解析します。解析が失敗した場合は、リターンします。エラー結果 (ログインしていません)。
このうちJwtUtilsは、前回の記事で書いたjwtの生成とデコードを実現するためのツールクラスです。
2) フィルターを構成します。
@WebFilter アノテーションを Filter クラスに追加して、リソースをインターセプトするパスを構成します。@ServletComponentScan をブート クラスに追加して、サーブレット コンポーネントのサポートを有効にします。
@WebFilter アノテーションはフィルターの設定に使用されます。次の (urlPatterns = "/*") はインターセプトする URL パターンを指定し、「/*」はすべてインターセプトすることを意味します。
3、インターセプター
1) インターセプターの定義: クラスを定義し、インターセプター インターフェイスを実装し、その preHandle メソッドをオーバーライドします。
ログイン検証機能を実装する同じ例を見てみましょう。
@Component
public class LoginCheckinterceptor implements HandlerInterceptor {
//快捷键ctrl+o 对方法进行重写
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
//目标资源方法执行前执行,返回true:放行,返回false:不放行
// 1、获取请求url
String url = req.getRequestURI().toString();
// 2、判断请求url中是否包含login,如果包含,说明是登录操作,放行。
if (url.contains("login")){
//放行操作
return true;
}
// 3、获取请求头中的令牌(token)。
String jwt = req.getHeader("token");
// 4、判断令牌是否存在,如果不存在,返回错误结果(未登录)。
if (!StringUtils.hasLength(jwt)){
Result error = Result.error("NOT LOGIN");
//手动转换,将对象转换为json格式 <-----阿里巴巴fastjson
String notLogin = JSONObject.toJSONString(error);
//将该字符串响应给前端
resp.getWriter().write(notLogin);
return false;
}
// 5、解析token,如果解析失败,返回错误结果(未登录)。
try {
JwtUtils.parseJWT(jwt);
}catch (Exception e){//解析失败
e.printStackTrace();
Result error = Result.error("NOT LOGIN");
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
// 6、放行。
return true;
}
@Override//目标资源方法执行后执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
4. メソッドの書き換えに注意する
Java Web 開発では、フィルターとインターセプターはどちらもリクエストとレスポンスを処理するために使用されるミドルウェアですが、使用法と実装にはいくつかの違いがあります。
フィルター:
- Java サーブレット仕様では、フィルタはリクエストとレスポンスを処理する共通の方法を提供する標準インターフェイスです。
- フィルターは、との
javax.servlet.Filter
3 つの主要なメソッドを持つインターフェイスを実装する必要があります。init
doFilter
destroy
doFilter
フィルタリング ロジックを作成するにはメソッドを実装する必要があります。リクエストとレスポンスは変更または処理できます。- リクエスト チェーンの処理を続行するには、Filter メソッドを明示的に呼び出す必要があります
chain.doFilter(request, response)
。
インターセプター:
- Spring MVC では、インターセプターは、リクエストと応答を処理するために Spring フレームワークによって提供されるメカニズムです。
- インターセプターは、との
org.springframework.web.servlet.HandlerInterceptor
3 つのメソッドを持つインターフェイスを実装する必要があります。preHandle
postHandle
afterCompletion
- 前処理、後処理、および完了処理ロジックを実装するには、必要に応じてこれらのメソッドをオーバーライドする必要があります。
- インターセプター メソッドは、次のインターセプターまたは処理チェーンを明示的に呼び出す必要はありません。