责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它可以将请求沿着一个处理链依次传递,直到有一个处理者处理该请求为止。在责任链模式中,每个处理者都有一个后继处理者,如果当前处理者无法处理该请求,它就将请求传递给下一个处理者进行处理,直到请求被处理为止。
在Java中实现责任链模式,可以按照以下步骤进行:
- 定义一个处理器接口,其中包含一个处理请求的方法和一个设置后继处理器的方法:
public interface Handler {
void handleRequest(Request request);
void setSuccessor(Handler successor);
}
- 实现具体的处理器类,如下所示:
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;
}
}
- 创建一个请求类,其中包含请求类型和请求内容:
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;
}
}
- 创建一个请求类型枚举类:
public enum RequestType {
TYPE_A, TYPE_B
}
- 创建一个责任链对象,并将处理器按照顺序串联起来:
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);
}
}
}
- 在客户端代码中创建请求对象并将其传递给责任链处理器:
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 条评论