以增量的方式适应变化
在看Spring Security开发安全的REST服务.的视频的是时候,有一小结感觉讲的很好,就是以增量的方式来适应变化 ,特此记录。
原始逻辑
Controller中的图形验证码的生成逻辑
@RestController
public class ValidateCodeController {
public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";
private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
@GetMapping("/code/image")
public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
ImageCode imageCode = generator(new ServletWebRequest(request));
//存储图形验证码的生成数字
sessionStrategy.setAttribute(new ServletWebRequest(request), SESSION_KEY, imageCode);
//将验证码图片写回网页
ImageIO.write(imageCode.getImage(), "JPEG", response.getOutputStream());
}
private ImageCode generator() {
//生成图形验证码
}
}
在生成图形验证码的过程中,逻辑都是全部写在Controller中的,在实际的开发过程中Controller中不应该放过多的东西,应该只需要调用服务即可,在这段代码中,生成验证码的的逻辑和请求的处理严重耦合在了一起,如果我们要开发不同的验证码,便只能改写这段中验证码的生成逻辑,有没有办法能不改动代码中的原始逻辑,用我们自定义的验证码来替代呢。这就要用到一个思想就是以增量的方式适应变化
重构
在这段代码中,需要做的就是然后定义一个接口,将生成验证码的逻辑抽取出来,实现这个接口。
定义接口
public interface ValidateCodeGenerator {
ImageCode generate(ServletWebRequest request);
}
实现接口
public class ImageCodeGenerator implements ValidateCodeGenerator {
@Override
public ImageCode generate(ServletWebRequest request) {
//生成验证码
}
}
抽取之后,如何在Controller中引用这个实现类呢,普遍的想法是在ImageCodeGenerator
中添加@component
注解,但是如何这样做的话便没有办法替换掉ImageCodeGenerator
使用我们自己的验证码生成逻辑了,因此我们还需要再写一个配置类ValidateCodeBeanConfig
生成配置类
@Configuration
public class ValidateCodeBeanConfig {
@Bean
@ConditionalOnMissingBean(name = "imageCodeGenerator")
/*imageCodeGenerator这个注解的作用就是如果容器中存在imageCodeGenerator这个bean,
就使用它,否则便使用我们下面配置的bean
*/
public ValidateCodeGenerator imageCodeGenerator() {
ImageCodeGenerator codeGenerator = new ImageCodeGenerator();
return codeGenerator;
}
}
ConditionalOnMissingBean
这个注解就是最为关键的注解,只要我们配置了imageCodeGenerator
这个bean,便会取代掉原始的bean,使用我们自己配置的bean
使用自己配置的bean
@Component("imageCodeGenerator")
public class DemoImageCodeGenerator implements ValidateCodeGenerator{
@Override
public ImageCode generate(ServletWebRequest request) {
System.out.println("更高级的验证码");
return null;
}
}
最终,容器便会使用我们自定义的验证码生成逻辑