大家好,我是 ??
一个正在努力学习的小博主,期待你的关注
作业侠系列最新文章??
SpringBoot实战系列??
SpringBoot实战系列之图形验证码开发并池化Redis6缓存
一起刷算法与数据结构最新文章??
环境搭建大集合
在本栏中,我们之前已经完成了:
SpringBoot实战系列之发送短信验证码
SpringBoot实战系列之从Async组件应用实战到ThreadPoolTaskExecutor?定义线程池
内容速览:
1.Kaptcha 框架介绍与配置类开发
2.池化思想应?-Redis6.X配置连接池实战连接池好处
3.实战图形验证码接口编写
4.结果测试
Kaptcha 框架介绍 歌开源的个可度配置的实验证码成具
验证码的字体//颜
验证码内容的范围(数字,字,中汉字!)
验证码图的,边框,边框粗细,边框颜
验证码的扰线
验证码的样式(眼样式、3D、普通模糊)
聚合程依赖添加(使国内baomidou次封装的springboot整合starter)
com.baomidou
kaptcha-spring-bootstarter
1.1.0
配置类
@Configuration
public class CaptchaConfig {
@Bean
@Qualifier("captchaProducer")
public DefaultKaptcha kaptcha() {
DefaultKaptcha kaptcha = new DefaultKaptcha();
Properties properties = new Properties();
//
properties.setProperty(Constants.KAPTCHA_BORDER, "yes");
//
properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "220,220,220");
//
//properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "38,29,12");
//
properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "147");
//
properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "34");
//
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "25");
//
//properties.setProperty(Constants.KAPTCHA_SESSION_KEY, "code");
//验证码个数
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
//
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Courier");
//字体间隔
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"8");
//?扰线颜?
//
properties.setProperty(Constants.KAPTCHA_NOISE_COLOR, "white");
//?扰实现类
properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
//图?样式
properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.WaterRipple");
//?字来源
properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789");
Config config = new Config(properties);
kaptcha.setConfig(config);
return kaptcha;
}
}
池化思想应-Redis6.X配置连接池实战连接池好处
使连接池不每次都三次握、每次都关闭Jedis相对于直连,使相对麻烦,在资源管理上需要很多参数来保证,规划不合理也会出现问题
如果pool已经分配了maxActive个jedis实例,则此时pool的状态就成exhausted了
Maven
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
org.apache.commons
commons-pool2
配置Redis连接
redis:
client-type: jedis
host: 127.0.0.1
password: 123456
port: 6379
jedis:
pool:
# 连接池最?连接数(使?负值表示没有限制)
max-active: 100
# 连接池中的最?空闲连接
max-idle: 100
# 连接池中的最?空闲连接
min-idle: 100
# 连接池最?阻塞等待时间(使?负值表示没有限制)
max-wait: 60000
注意将配置里的host和password改为你自己的
序列化配置
@Configuration
public class RedisTemplateConfiguration {
@Bean
public RedisTemplate
实战图形验证码接口编写:
@RestController
@RequestMapping("/api/v1/notify")
@Slf4j
public class NotifyController {
public static final int CAPTCHA_CODE_EXPIRED = 60 * 1000 * 10;
@Autowired
private Producer captchaProduce;
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 图形验证码生成流程
* 1.用captcha创建文本 String captchaText = captchaProduce.createText();
* 2.生成文本图像 BufferedImage bufferedImage = captchaProduce.createImage(captchaText);
* 3.用流写出 try(ServletOutputStream outputStream = response.getOutputStream();) {
* ImageIO.write(bufferedImage,"jpg",outputStream);
* outputStream.flush();
* @param request
* @param response
*/
@GetMapping("captcha")
public void getCaptcha(HttpServletRequest request, HttpServletResponse response){
String captchaText = captchaProduce.createText();
log.info("验证码内容{}",captchaText);
redisTemplate.opsForValue().set(getCaptchaKey(request),captchaText,CAPTCHA_CODE_EXPIRED, TimeUnit.SECONDS);
BufferedImage bufferedImage = captchaProduce.createImage(captchaText);
try(ServletOutputStream outputStream = response.getOutputStream();) {
ImageIO.write(bufferedImage,"jpg",outputStream);
outputStream.flush();
}catch (Exception e){
log.info("图形验证码异常");
}
}
/**
使用用户ip加user-agent并用md5进行加密
**/
private String getCaptchaKey(HttpServletRequest request){
String ip = CommonUtil.getIpAddr(request);
String userAgent = request.getHeader("User-Agent");
String key = "account-service:captcha:"+CommonUtil.MD5(ip+userAgent);
log.info("key{}",key);
return key;
}
}
CommonUtil工具类,直接cv即可,在工作中也是这样:
@Slf4j
public class CommonUtil {
/**
* 获取ip
*
* @param request
* @return
*/
public static String
getIpAddr(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null ||
ipAddress.length() == 0 ||
"unknown".equalsIgnoreCase(ipAddress)) {
ipAddress =
request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null ||
ipAddress.length() == 0 ||
"unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null ||
ipAddress.length() == 0 ||
"unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据?卡取本机配置的IP
InetAddress inet = null;
try {
inet =
InetAddress.getLocalHost();
} catch (UnknownHostException e)
{
log.warn("[]",e);
}
ipAddress =
inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第?个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null &&
ipAddress.length() > 15) {
// "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
/**
* 获取全部请求头
* @param request
* @return
*/
public static Map
getAllRequestHeader(HttpServletRequest request){
Enumeration headerNames = request.getHeaderNames();
Map map = new HashMap<>();
while (headerNames.hasMoreElements()) {
String key = (String)headerNames.nextElement();
//根据名称获取请求头的值
String value = request.getHeader(key);
map.put(key,value);
}
return map;
}
/**
* MD5加密
*
* @param data
* @return
*/
public static String MD5(String data) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
} catch (Exception exception) {
}
return null;
}
/**
* 获取验证码随机数
*
* @param length
* @return
*/
public static String getRandomCode(int length) {
String sources = "0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int j = 0; j < length; j++) {
sb.append(sources.charAt(random.nextInt(9)));
}
return sb.toString();
}
/**
* 获取当前时间戳
*
* @return
*/
public static long getCurrentTimestamp() {
return System.currentTimeMillis();
}
/**
* ?成uuid
*
* @return
*/
public static String generateUUID() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
/**
* 获取随机?度的串
*
* @param length
* @return
*/
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static String getStringNumRandom(int length) {
//?成随机数字和字?,
Random random = new Random();
StringBuilder saltString = new
StringBuilder(length);
for (int i = 1; i <= length; ++i) {
saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
}
return saltString.toString();
}
/**
* 响应json数据给前端
*
* @param response
* @param obj
*/
public static void
sendJsonMessage(HttpServletResponse response, Object obj) {
response.setContentType("application/json;charset=utf-8");
try (PrintWriter writer =
response.getWriter()) {
writer.print(JsonUtil.obj2Json(obj));
response.flushBuffer();
} catch (IOException e) {
log.warn("响应json数据给前端异常:{}",e);
}
}
}
浏览器访问结果如下:
同时控制台打印:
redis可视化工具查看:
本篇完!
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦