【造个轮子系列】之自定义验证码的 springboot starter

前言

springboot很好用的原因之一就是它本身封装了好多starter,拿来就可以用,不用像SSM那样配置好多。所以,我们也可以自定义一个starter,造个小轮子,自己用。我就以验证码为例子。

一、工厂模式

验证码的样式多种多样,有静态的PNG格式的,有动态的GIF格式的。还有它的高度、宽度,字符串的长度也都可以改变。所以我们可以使用java设计模式中的工厂模式来生成不同的验证码。

工厂模式参考:https://www.runoob.com/design-pattern/factory-pattern.html。看完这篇,你就发现,工厂模式就这么简单。?

二、定义验证码属性

为了让验证码的属性可以配置,我们就需要写一个配置类来封装一下这些乱七八糟的属性。

1、先来一个枚举,定义验证码是静态的还是动态的。

public enum CaptchaType {

	/**
	 *静态图片验证码 
	 */
	PNG,
	/**
	 *动态GIF格式的验证码 
	 */
	GIF;
}

2、再来一个枚举,定义验证码里字符串的类型

public enum CharTypeEnum {

	TYPE_DEFAULT(1,"数字和字母混合"),
	TYPE_ONLY_NUMBER(2,"纯数字"),
	TYPE_ONLY_CHAR(3,"纯字母"),
	TYPE_ONLY_UPPER(4,"纯大写字母"),
	TYPE_ONLY_LOWER(5,"纯小写字母"),
	TYPE_NUM_AND_UPPER(6,"数字和大写字母");
	
	private Integer code;
	
	private String charType;

	public Integer getCode() {
		return code;
	}

	public void setCode(Integer code) {
		this.code = code;
	}

	public String getCharType() {
		return charType;
	}

	public void setCharType(String charType) {
		this.charType = charType;
	}

	private CharTypeEnum(Integer code, String charType) {
		this.code = code;
		this.charType = charType;
	}
	
}

3、把这两个枚举放进配置类里就可以了。这些属性最好设置一下默认值,这样在使用的时候,不做任何配置也是可以正常使用的。

@ConfigurationProperties("java.captcha") 这个注解的意思就是定义application.properties里配置项的。

@ConfigurationProperties("java.captcha")
public class CaptchaProperties {
	
	//验证码图片的宽度
	private Integer width = 130;
	
	//验证码图片的高度
	private Integer height = 48;
	
	//验证码图片的位数
	private Integer length = 4;
	
	//验证码图片的字符类型
	private CharTypeEnum charType = CharTypeEnum.TYPE_DEFAULT;
	
	//生成的验证码图片类型
	private CaptchaType captchaType = CaptchaType.PNG;
	
	//缓存的名称
	private String captchaKey = "captcha";

	//验证码过期时间,默认为5分钟
	private int expireTimeInSeconds = 300;

	public Integer getWidth() {
		return width;
	}

	public void setWidth(Integer width) {
		this.width = width;
	}

	public Integer getHeight() {
		return height;
	}

	public void setHeight(Integer height) {
		this.height = height;
	}

	public Integer getLength() {
		return length;
	}

	public void setLength(Integer length) {
		this.length = length;
	}

	public CharTypeEnum getCharType() {
		return charType;
	}

	public void setCharType(CharTypeEnum charType) {
		this.charType = charType;
	}

	public CaptchaType getCaptchaType() {
		return captchaType;
	}

	public void setCaptchaType(CaptchaType captchaType) {
		this.captchaType = captchaType;
	}

	public String getCaptchaKey() {
		return captchaKey;
	}

	public void setCaptchaKey(String captchaKey) {
		this.captchaKey = captchaKey;
	}

	public int getExpireTimeInSeconds() {
		return expireTimeInSeconds;
	}

	public void setExpireTimeInSeconds(int expireTimeInSeconds) {
		this.expireTimeInSeconds = expireTimeInSeconds;
	}

}

三、验证码生成

1、定义一个工厂类,根据传入的不同的参数,生成不同的验证码。

为了更加通用性,我打算不仅可以通过 application.properties 来配置验证码的属性,而且又能通过传参来改变验证码的属性。这时,我们就需要ServletRequestUtils这个工具类,从HttpServletRequest来拿参数了,如果拿不到的话就用配置的属性。

public class CaptchaGenerateFactory {

	public static Captcha getCaptcha(CaptchaProperties properties,ServletWebRequest request){
		
		boolean isGif = ServletRequestUtils.getBooleanParameter(request.getRequest(),"gif",false);
		Integer width = ServletRequestUtils.getIntParameter(request.getRequest(), "width",properties.getWidth());
		Integer height = ServletRequestUtils.getIntParameter(request.getRequest(), "height",properties.getHeight());
		Integer length = ServletRequestUtils.getIntParameter(request.getRequest(), "length",properties.getLength());
		
		if (isGif) {
			return new GifCaptcha(width,height,length);
		}else{
			if (Objects.equals(properties.getCaptchaType(), CaptchaType.PNG)) {
				return new SpecCaptcha(width,height,length);
			}
			if (Objects.equals(properties.getCaptchaType(),CaptchaType.GIF)) {
				return new GifCaptcha(width,height,length);
			}
		}
		return null;
	}
	
}

2、生成验证码

先定义一个接口,这个接口很简单,就一个生成方法。Captcha 我使用了一个别人写的工具类,依赖如下。我没用谷歌的,主要是它直接扔session里了,最主要的是太丑了!!!

public interface CaptchaService {

	Captcha generate(ServletWebRequest request);
	
}
<dependency>
    <groupId>com.github.whvcse</groupId>
    <artifactId>EasyCaptcha</artifactId>
    <version>1.5.0</version>
</dependency>

然后实现这个接口,注入上面的配置类,调用工厂类来生成验证码。生成验证码的功能基本就实现了。但是你有没有发现这个实现类没有@Service注解,这个再下一步会讲到。

public class CaptchaServiceImpl implements CaptchaService{
	
	@Autowired
	private CaptchaProperties properties;

	/**
	 * 生成图形验证码
	 * @return
	 */
	public Captcha generate(ServletWebRequest request){
		Captcha captcha = CaptchaGenerateFactory.getCaptcha(properties,request);
		//设置类型
		captcha.setCharType(properties.getCharType().getCode());
		return captcha;
	}
	
}

四、starter配置

功能已经实现了,但是这些还不够,直接引入的话,是不起作用的。还需要一些配置,就是告诉springboot一声:“喂,我写了个starter,你得加载!”。

@Configuration这个注解常见,表明这是个配置类,spring来管理。

@EnableConfigurationProperties这个注解就是启用我们写好的配置类。

@Bean注解和@Service的结果是一样的,都是告诉spring你来管理这个类吧。

@ConditionalOnMissingBean这个注解大概意思就是你要是引用这个starter了,要是没实现CaptchaService这个接口,那就用我的实现CaptchaServiceImpl,要是你实现了CaptchaService这个接口,那就用你的!spring也不会管理CaptchaServiceImpl这这个类了。

@Configuration
@EnableConfigurationProperties({CaptchaProperties.class})
public class CaptchaAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(CaptchaService.class)  
	public CaptchaService captchaService(){
		return new CaptchaServiceImpl();
	}
}

做完这些,还是不行。你就这么想,spring实在是太笨了,就算你配置好了,但是,它找不到啊!!!所以,我们还得给它做个目录之类的,指引它找到。

在src/main/resources目录下新建META-INF文件夹,文件夹里新建spring.factories文件,然后写点东西告诉这个笨笨的spring去哪路找我们写好的配置。第一行最后的 \ 的意思就是换行的意思。第二行就是上面那个类的包位置。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
work.waynelee.captcha.CaptchaAutoConfiguration

五、使用

都写完了,该怎么用呢??使用也是非常简单的。这些为啥不在starter里写呢?既然拿到验证码里的字符串了,你爱存哪里存哪里呗。再说了,也不是谁的业务逻辑都一样,剩下的,想怎么搞怎么搞呗,像是验证码失效的什么的就自己解决呗。

	@Autowired
	private CaptchaService captchaService;
	@Autowired
	private CaptchaProperties properties;
	
	public void getCaptcha(HttpServletRequest request,HttpServletResponse response) throws IOException{
		
		CaptchaUtil.setHeader(response);
		Captcha captcha = captchaService.generate(new ServletWebRequest(request));
		String text = captcha.text().toLowerCase();
		
		request.getSession().setAttribute(properties.getCaptchaKey(),text);
		
		captcha.out(response.getOutputStream());
	}

然后你也可以在application.properties里配置你想改变的属性,就像下面这样

java.captcha.captcha-type=png

你要不想配置也没啥事,请求的时候传参数就可以了。默认的就是这样的。

想变成GIF格式的?简单啊,加个参数就是了。

想变长?没问题!

就这样。

写在最后的话

感觉没啥可说的,要想直接使用的话,参考我的GitHub吧:https://github.com/WayneLee5991/captcha-spring-boot-starter/tree/master

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值