责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它可以将请求沿着一个处理链依次传递,直到有一个处理者处理该请求为止。在责任链模式中,每个处理者都有一个后继处理者,如果当前处理者无法处理该请求,它就将请求传递给下一个处理者进行处理,直到请求被处理为止。

在Java中实现责任链模式,可以按照以下步骤进行:

  1. 定义一个处理器接口,其中包含一个处理请求的方法和一个设置后继处理器的方法:
public interface Handler {
    void handleRequest(Request request);
    void setSuccessor(Handler successor);
}
  1. 实现具体的处理器类,如下所示:
public class ConcreteHandlerA implements Handler {
    private Handler successor;

    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_A) {
            // 处理请求
        } else {
            // 将请求传递给后继处理器
            if (successor != null) {
                successor.handleRequest(request);
            }
        }
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
}

public class ConcreteHandlerB implements Handler {
    private Handler successor;

    public void handleRequest(Request request) {
        if (request.getType() == RequestType.TYPE_B) {
            // 处理请求
        } else {
            // 将请求传递给后继处理器
            if (successor != null) {
                successor.handleRequest(request);
            }
        }
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
}
  1. 创建一个请求类,其中包含请求类型和请求内容:
public class Request {
    private RequestType type;
    private String content;

    public Request(RequestType type, String content) {
        this.type = type;
        this.content = content;
    }

    public RequestType getType() {
        return type;
    }

    public String getContent() {
        return content;
    }
}
  1. 创建一个请求类型枚举类:
public enum RequestType {
    TYPE_A, TYPE_B
}
  1. 创建一个责任链对象,并将处理器按照顺序串联起来:
public class Chain {
    private Handler head;

    public void addHandler(Handler handler) {
        if (head == null) {
            head = handler;
            return;
        }

        Handler current = head;
        while (current.getSuccessor() != null) {
            current = current.getSuccessor();
        }
        current.setSuccessor(handler);
    }

    public void handleRequest(Request request) {
        if (head != null) {
            head.handleRequest(request);
        }
    }
}
  1. 在客户端代码中创建请求对象并将其传递给责任链处理器:
public class Client {
    public static void main(String[] args) {
        Chain chain = new Chain();
        chain.addHandler(new ConcreteHandlerA());
        chain.addHandler(new ConcreteHandlerB());

        Request request1 = new Request(RequestType.TYPE_A, "Request 1");
        Request request2 = new Request(RequestType.TYPE_B, "Request 2");

        chain.handleRequest(request1);
        chain.handleRequest(request2);
    }
}

在上述代码中,我们创建了一个责任链对象,并将两个具体处理器按照顺序加入到责任链中。然后创建了两个请求对象,并将它们分别传递给责任链处理器进行处理。

责任链模式可以很好地实现请求的处理和分发,同时也可以很好地支持动态添加和移除处理器。在实际应用中,责任链模式常常被用来处理复杂的请求处理逻辑。

 

Servlet Filter示例,演示了如何使用Filter实现过滤器链。

假设我们有一个Web应用程序,并且需要对每个请求进行登录验证、权限验证和性能监控。为了实现这些功能,我们可以创建三个Filter,分别用于处理登录验证、权限验证和性能监控。

下面是一个示例代码,展示了如何使用Filter实现过滤器链:

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 登录验证
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作
    }
}

public class AuthFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 权限验证
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作
    }
}

public class PerformanceFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 性能监控
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作
    }
}

在上述代码中,我们创建了三个Filter,分别用于实现登录验证、权限验证和性能监控。这三个Filter都实现了Filter接口,并且在doFilter方法中调用了chain.doFilter方法,将请求传递给下一个Filter。

现在,我们需要将这三个Filter组合成一个过滤器链,并注册到Servlet容器中。这可以通过在web.xml文件中配置Filter来实现:

<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.example.LoginFilter</filter-class>
</filter>

<filter>
    <filter-name>AuthFilter</filter-name>
    <filter-class>com.example.AuthFilter</filter-class>
</filter>

<filter>
    <filter-name>PerformanceFilter</filter-name>
    <filter-class>com.example.PerformanceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>AuthFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>PerformanceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在上述代码中,我们将三个Filter注册到了Servlet容器中,并指定了它们的执行顺序。当请求到达Servlet容器时,每个Filter都会按照配置的顺序执行,并将请求传递给下一个Filter,直到请求被传递到Web应用程序的Servlet或JSP页面为止。

通过以上示例,我们可以看到如何使用Filter实现过滤器链。每个Filter都可以处理请求,如果无法处理,则将请求传递给下一个Filter,直到请求被处理为止。这种设计模式非常灵活,能够很好地支持各种请求处理场景。

最新版本的Servlet API已经支持使用注解来代替XML配置文件,使Servlet Filter的配置更加简洁和优雅。

以下是一个使用注解配置Servlet Filter的示例代码:

@WebFilter(filterName = "LoginFilter", urlPatterns = "/*",order=1)
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 登录验证
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作
    }
}

@WebFilter(filterName = "AuthFilter", urlPatterns = "/*",order=2)
public class AuthFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 权限验证
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作
    }
}

@WebFilter(filterName = "PerformanceFilter", urlPatterns = "/*",order=3)
public class PerformanceFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 性能监控
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 清理操作
    }
}

在上述代码中,我们使用了@WebFilter注解来标注每个Filter类,并指定了它们的名称和URL模式。与XML配置文件不同,这种方式更加直观和易于理解。

需要注意的是,要使用注解配置Servlet Filter,需要确保Servlet容器(如Tomcat)的版本支持Servlet 3.0及以上版本。如果Servlet容器的版本较低,则仍需要使用XML配置文件来配置Servlet Filter。order越小越先执行!

 

以下是一个更具体的Spring案例,展示了如何使用责任链模式来处理RESTful API请求。

在Spring MVC中,我们可以通过编写拦截器来处理HTTP请求。拦截器是一个非常典型的责任链模式的应用。每一个拦截器都可以处理请求,如果无法处理,则将请求传递给下一个拦截器,直到请求被处理为止。

下面是一个示例代码,其中定义了两个拦截器,分别用于检查请求参数和请求头:

@Component
public class ParameterInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 检查请求参数
        return true;
    }
}

@Component
public class HeaderInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 检查请求头
        return true;
    }
}

在上述代码中,ParameterInterceptor和HeaderInterceptor都实现了HandlerInterceptor接口,其中preHandle方法用于检查请求参数和请求头。如果检查通过,方法返回true,否则返回false。

接下来,我们需要将这两个拦截器注册到Spring MVC的拦截器链中。这可以通过配置一个拦截器注册表来实现:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ParameterInterceptor parameterInterceptor;

    @Autowired
    private HeaderInterceptor headerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(parameterInterceptor).addPathPatterns("/api/**");
        registry.addInterceptor(headerInterceptor).addPathPatterns("/api/**");
    }
}

在上述代码中,我们将ParameterInterceptor和HeaderInterceptor注册到拦截器注册表中,并指定了它们处理的URL路径。这样,当请求到达指定的URL路径时,这两个拦截器就会按照顺序依次执行,如果有一个拦截器返回false,则请求就会被拦截下来,不再继续传递给后续拦截器。

通过以上示例,我们可以看到Spring框架中如何使用责任链模式来处理RESTful API请求。在拦截器链中,每一个拦截器都可以处理请求,如果无法处理,则将请求传递给下一个拦截器,直到请求被处理为止。这种设计模式非常灵活,能够很好地支持各种请求处理场景。

 

Spring Security是一个基于Spring框架的安全框架,它提供了一系列的安全功能,包括身份验证、授权、密码管理等。Spring Security中的拦截器(Interceptor)也实现了责任链模式,用于在请求处理之前或之后执行安全验证操作。

以下是一个使用Spring Security的示例:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private CustomUserDetailsService userDetailsService;
  
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    
    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(logoutSuccessHandler)
                .permitAll();
    }
  
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

在此示例中,我们使用了@EnableWebSecurity注解启用Spring Security,并重写了configure(HttpSecurity http)方法来配置安全规则。

在配置中,我们使用了antMatchers()方法来指定哪些URL模式不需要进行安全验证,并使用authenticated()方法来限制需要进行身份验证的请求。

我们还重写了configure(AuthenticationManagerBuilder auth)方法来配置身份验证机制,使用了一个自定义的UserDetailsService来获取用户信息。

在上述代码中,我们使用了一些Handler来处理身份验证、登出等操作,这些Handler会在Spring Security的拦截器责任链中被调用。例如,当用户成功登录时,我们会调用AuthenticationSuccessHandler实现类的onAuthenticationSuccess()方法来处理成功登录后的操作。

总之,Spring Security的拦截器和Handler实现了责任链模式,使得安全验证操作能够进行灵活的组合和配置。

 

Shiro是一个开源的Java安全框架,它提供了身份验证、授权、会话管理、加密等安全功能。Shiro中的拦截器也实现了责任链模式,用于在请求处理之前或之后执行安全验证操作。

以下是一个使用Shiro的示例:

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/login");
        shiroFilter.setUnauthorizedUrl("/403");
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/public/**", "anon");
        filterChainDefinitionMap.put("/admin/**", "roles[admin]");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilter;
    }

    @Bean
    public SecurityManager securityManager(Realm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    @Bean
    public Realm realm() {
        CustomRealm realm = new CustomRealm();
        realm.setCredentialsMatcher(hashedCredentialsMatcher());
        return realm;
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("SHA-256");
        hashedCredentialsMatcher.setHashIterations(1024);
        return hashedCredentialsMatcher;
    }
}

在此示例中,我们使用了ShiroFilterFactoryBean来配置Shiro拦截器责任链,并使用SecurityManager来管理安全策略。

我们还重写了Realm接口来实现自定义的身份验证和授权逻辑,使用了HashedCredentialsMatcher来进行密码加密和比对。

在配置中,我们使用了filterChainDefinitionMap来指定哪些URL模式需要进行安全验证,并使用roles[admin]来限制需要具有admin角色的用户才能访问/admin/**路径下的资源。

总之,Shiro的拦截器和Realm实现了责任链模式,使得安全验证操作能够进行灵活的组合和配置。

 


0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

蜀ICP备16001794号
© 2014 - 2024 linpxing.cn All right reserved.