《Java 拦截过滤器模式,你了解多少?》

229 阅读3分钟

嘿,各位掘友们!今天咱继续深挖 Java 里超有意思的拦截过滤器模式,上次只是浅聊了个大概,这次来点 “硬货”—— 代码示例,让你彻底搞懂它的玩法。

还是那个比喻,你的 Java 应用程序是个超级大派对现场,各种请求(也就是想来派对撒欢的客人)纷至沓来。过滤器呢,就是站在门口严格把关的 “小卫士”。

先瞅瞅 Servlet 过滤器咋写,比如说咱搞个简单的 “字符编码过滤器”,防止乱码这个 “捣蛋鬼” 来搅局。代码如下:

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*") // 表示这个过滤器对所有请求都生效,就像派对每个入口都安排了它的眼线
public class CharacterEncodingFilter implements Filter {
    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        encoding = filterConfig.getInitParameter("encoding");
        if (encoding == null) {
            encoding = "UTF-8"; // 默认编码设为 UTF-8,要是没特别配置,就按这个来
        }
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encoding); // 给请求设置编码,让它乖乖听话
        response.setCharacterEncoding(encoding);
        chain.doFilter(request, response); // 放行,让请求接着往后走,去见其他“把关人”或者进入派对核心区(业务处理)
    }
    @Override
    public void destroy() {
        // 这里可以做一些清理工作,不过这个简单例子没啥可清理的,先空着
    }
}

看到没,这个过滤器就像个贴心小管家,把字符编码问题处理得妥妥当当。在 web.xml 里配置(要是用注解配置就像上面代码里 @WebFilter 那样),就相当于给它指明站岗的地方。

再说说拦截器,在 Spring 框架里,它可是 “神通广大” 的存在。就拿之前提到的 “库存检查拦截器” 为例,假设咱有个电商项目:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class InventoryCheckInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 假设从请求里能拿到商品 ID,这里简单模拟一下
        String productId = request.getParameter("productId"); 
        if (productId!= null) {
            // 再假设咱有个 InventoryService 能查库存,这里也简单模拟返回值
            boolean hasStock = checkInventory(productId); 
            if (!hasStock) {
                response.getWriter().write("亲,这宝贝没货啦,等补货再约哦");
                return false; // 库存不足,中断请求,不让它往后跑了
            }
        }
        return true; // 有库存,放行,让请求继续畅游后续流程
    }
    private boolean checkInventory(String productId) {
        // 真实项目里这里会去数据库或者缓存查库存,咱这儿简单返回个值模拟
        return "123".equals(productId)? true : false; 
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 请求处理完,但视图还没渲染时,这里可以干点事儿,比如记录点日志啥的,先空着
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 整个请求处理完,视图也渲染完,做最后的清理工作,也先空着
    }
}

然后在 Spring 的配置文件里(或者用注解配置方式)把这个拦截器安排上,就像给订单处理流程请了个专业 “质检员”,严格把控库存关。

使用这种拦截过滤器模式,代码复用性超高,不同模块想用同样的过滤、拦截逻辑,直接复制粘贴稍加修改就行,不用吭哧吭哧重新写。维护也轻松,要是发现身份验证规则得改改,就直奔对应的过滤器或者拦截器代码块,改完拍拍手,其他地方正常运行不受影响。

总的来说,Java 的拦截过滤器模式就是让咱的程序稳如泰山,既安全又高效,像一场组织有序的狂欢派对,每个客人(请求)都按规矩玩耍。下次写代码,赶紧给你的项目配上这些 “把关小能手” 吧!

好啦,今天的分享就到这儿,要是觉得有用,点赞、评论、收藏三连走一波,咱们下期再见咯!