整合rabbitmq+redis发送验证码消息
生活随笔
收集整理的這篇文章主要介紹了
整合rabbitmq+redis发送验证码消息
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 配置:
- 驗證碼工具類
- 處理發送驗證碼的消息
- controller層
- 驗證驗證碼是否正確
配置:
server:port: 8084 #郵件相關配置 spring:application:name: subtlechat-mailservermail:host: smtp.qq.comprotocol: smtpdefault-encoding: UTF-8#郵箱名username: #申請的授權碼password: port: 587properties.mail.stmp.socketFactory.class: javax.net.ssl.SSLSocketFactoryproperties.mail.debug: true#RabbitMQ的配置rabbitmq:host: localhostport: 5672username: guestpassword: guestvirtual-host: /subtlechat# 如果rabbitmq中沒有創建這個名字的虛擬主機會報錯#開啟手動確認是否消息消費成功listener:simple:acknowledge-mode: manualprefetch: 100#Redis的配置redis:database: 0password: redishost: port: 6379rabbitmq配置:
/*** @author Hai* @date 2020/10/1 - 18:32*/ @Configuration public class RabbitMQConfig {@Value("${mail.exchange:mail-exchange}")private String mailExchange;@Value("${mail.queue.verifyCode:mail-queue-verifyCode}")private String mailQueueVerifyCode;@Value("${mail.route.verifyCode:mail-route-verifyCode}")private String mailRouteVerifyCode;@Value("${mail.queue.feedback:mail-queue-feedback}")private String mailQueueFeedback;@Value("${mail.route.feedback:mail-route-feedback}")private String mailRouteFeedback;@BeanDirectExchange mailExchange(){return new DirectExchange(mailExchange,true,false);}/*** 驗證碼消息隊列* @return*/@BeanQueue mailQueueVerifyCode(){return new Queue(mailQueueVerifyCode,true);}@BeanBinding mailQueueVerifyCodeBinding(){return BindingBuilder.bind(mailQueueVerifyCode()).to(mailExchange()).with(mailRouteVerifyCode);}}}自定義rabbitmqtemplate:
/*** 自定義消息發送RabbitTemplate* @author Hai* @date 2020/10/2 - 14:35*/ @Configuration public class RabbitMQConfig {public static final Logger LOGGER= LoggerFactory.getLogger(RabbitMQConfig.class);@AutowiredCachingConnectionFactory cachingConnectionFactory;@AutowiredMailSendLogService mailSendLogService;@Beanpublic RabbitTemplate rabbitTemplate(){RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);//成功投遞消息到Broker交換機站點的回調函數rabbitTemplate.setConfirmCallback((data,ack,cause)->{String msgId = data.getId();if(ack){LOGGER.info(msgId+"消息發送成功");//修改數據庫中的記錄,消息發送成功,將status設為1mailSendLogService.updateMailSendLogStatus(msgId, MailConstants.SUCCESS);}else{LOGGER.error(msgId+"消息發送失敗!");}});//消息投遞到Queue隊列失敗的回調函數rabbitTemplate.setReturnCallback((msg,repCode,repText,exchange,routingKey)->{LOGGER.error(msg.getBody()+"----消息從交換機投遞到隊列失敗!\n錯誤原因:"+repText);LOGGER.error("發送錯誤的交換機:"+exchange+",發生錯誤的路由key:"+routingKey);});return rabbitTemplate;} }驗證碼工具類
/*** 生成驗證碼的工具類*/ public class VerificationCode {private int width = 100;// 生成驗證碼圖片的寬度private int height = 30;// 生成驗證碼圖片的高度private String[] fontNames = { "宋體", "楷體", "隸書", "微軟雅黑" };private Color bgColor = new Color(255, 255, 255);// 定義驗證碼圖片的背景顏色為白色private Random random = new Random();private String codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";private String text;// 記錄隨機字符串/*** 獲取一個隨意顏色** @return*/private Color randomColor() {int red = random.nextInt(150);int green = random.nextInt(150);int blue = random.nextInt(150);return new Color(red, green, blue);}/*** 獲取一個隨機字體** @return*/private Font randomFont() {String name = fontNames[random.nextInt(fontNames.length)];int style = random.nextInt(4);int size = random.nextInt(5) + 24;return new Font(name, style, size);}/*** 獲取一個隨機字符** @return*/private char randomChar() {return codes.charAt(random.nextInt(codes.length()));}/*** 創建一個空白的BufferedImage對象** @return*/private BufferedImage createImage() {BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) image.getGraphics();g2.setColor(bgColor);// 設置驗證碼圖片的背景顏色g2.fillRect(0, 0, width, height);return image;}public BufferedImage getImage() {BufferedImage image = createImage();Graphics2D g2 = (Graphics2D) image.getGraphics();StringBuffer sb = new StringBuffer();for (int i = 0; i < 4; i++) {String s = randomChar() + "";sb.append(s);g2.setColor(randomColor());g2.setFont(randomFont());float x = i * width * 1.0f / 4;g2.drawString(s, x, height - 8);}this.text = sb.toString();drawLine(image);return image;}/*** 繪制干擾線** @param image*/private void drawLine(BufferedImage image) {Graphics2D g2 = (Graphics2D) image.getGraphics();int num = 5;for (int i = 0; i < num; i++) {int x1 = random.nextInt(width);int y1 = random.nextInt(height);int x2 = random.nextInt(width);int y2 = random.nextInt(height);g2.setColor(randomColor());g2.setStroke(new BasicStroke(1.5f));g2.drawLine(x1, y1, x2, y2);}}public String getText() {return text;}public static void output(BufferedImage image, OutputStream out) throws IOException {ImageIO.write(image, "JPEG", out);} }處理發送驗證碼的消息
package top.javahai.subtlechat.mail.receiver;import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.impl.AMQImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.support.AmqpHeaders; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.stereotype.Component;import java.io.IOException; import java.util.Date;/*** 處理發送驗證碼的消息,保證消息不會重復消費* @author Hai* @date 2020/10/2 - 23:25*/ @Component public class VerifyCodeReceiver {@AutowiredJavaMailSender javaMailSender;@AutowiredStringRedisTemplate redisTemplate;private static final Logger LOGGER= LoggerFactory.getLogger(VerifyCodeReceiver.class);@RabbitListener(queues = "${mail.queue.verifyCode:mail-queue-verifyCode}")public void getMessage(Message message, Channel channel) throws IOException {//獲取消息內容String code = message.getPayload().toString();//獲取消息頭,消息標志tagMessageHeaders headers = message.getHeaders();Long tag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);//獲取消息IDString msgId = (String) headers.get("spring_returned_message_correlation");LOGGER.info("【"+msgId+"】-正在處理的消息");//查看消息是否已消費if (redisTemplate.opsForHash().entries("mail_log").containsKey(msgId)){//手動確認消息已消費channel.basicAck(tag,false);LOGGER.info("【"+msgId+"】消息出現重復消費");return;}//否則進行消息消費try{SimpleMailMessage msg = new SimpleMailMessage();msg.setSubject("-驗證碼驗證");msg.setText("本次登錄的驗證碼:"+code);msg.setFrom("發送者的郵箱地址");msg.setSentDate(new Date());msg.setTo("接受者的郵箱地址");javaMailSender.send(msg);//消息發送成功,將id放到redis中,不能這樣put//redisTemplate.opsForHash().entries("mail_log").put(msgId,code);redisTemplate.opsForHash().put("mail_log",msgId,code);//確認消息消費成功channel.basicAck(tag,false);}catch (Exception e){//不批量處理,將消息重新放回到隊列中channel.basicNack(tag,false,true);LOGGER.info("【"+msgId+"】消息重新放回到了隊列中");e.printStackTrace();}} }controller層
@RestController public class LoginController {/*** 獲取驗證碼圖片寫到響應的輸出流中,保存驗證碼到session* @param response* @param session* @throws IOException*/@GetMapping("/verifyCode")public void getVerifyCode(HttpServletResponse response, HttpSession session) throws IOException {VerificationCode code = new VerificationCode();BufferedImage image = code.getImage();String text = code.getText();session.setAttribute("verify_code",text);VerificationCode.output(image,response.getOutputStream());}@AutowiredVerifyCodeService verifyCodeService;/*** 獲取郵箱驗證碼,并保存到本次會話* @param session*/@GetMapping("/admin/mailVerifyCode")public RespBean getMailVerifyCode(HttpSession session){String code = verifyCodeService.getVerifyCode();//保存驗證碼到本次會話session.setAttribute("mail_verify_code",code);verifyCodeService.sendVerifyCodeMail(code);return RespBean.ok("驗證碼已發送到郵箱,請注意查看!");}}}其中sendVerifyCodeMail方法:
@Overridepublic void sendVerifyCodeMail(String code) {//添加消息記錄String msgId = UUID.randomUUID().toString();MailSendLog mailSendLog = new MailSendLog();mailSendLog.setMsgId(msgId);mailSendLog.setContent(code);mailSendLog.setContentType(MailConstants.VERIFY_CODE_TYPE);mailSendLog.setCount(1);mailSendLog.setCreateTime(new Date());mailSendLog.setTryTime(new Date(System.currentTimeMillis()+1000*10*MailConstants.MEG_TIMEOUT));mailSendLog.setUpdateTime(new Date());mailSendLog.setExchange(mailExchange);mailSendLog.setRouteKey(mailRouteVerifyCode);mailSendLog.setStatus(MailConstants.DELIVERING);mailSendLogService.insert(mailSendLog);rabbitTemplate.convertAndSend(mailExchange,mailRouteVerifyCode,code,new CorrelationData(msgId));}驗證驗證碼是否正確
/*** 攔截登錄請求,驗證輸入的驗證碼是否正確* @author Hai* @date 2020/5/28 - 17:31*/ @Component public class VerificationCodeFilter extends GenericFilter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;//如果是登錄請求則攔截if ("POST".equals(request.getMethod())&&"/doLogin".equals(request.getServletPath())){//TODO 不啟動驗證碼filterChain.doFilter(request,response);//用戶輸入的驗證碼String code = request.getParameter("code");//session中保存的驗證碼String verify_code = (String) request.getSession().getAttribute("verify_code");response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();//驗證session中保存是否存在try {//驗證是否相同if (!code.toLowerCase().equals(verify_code.toLowerCase())){//輸出jsonwriter.write(new ObjectMapper().writeValueAsString( RespBean.error("驗證碼錯誤!")));return;}else {filterChain.doFilter(request,response);}}catch (NullPointerException e){writer.write(new ObjectMapper().writeValueAsString(RespBean.error("請求異常,請重新請求!")));}finally {writer.flush();writer.close();}}else {filterChain.doFilter(request,response);}} }總結
以上是生活随笔為你收集整理的整合rabbitmq+redis发送验证码消息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ftp+线程池批量上传文件
- 下一篇: thumbnailator压缩图片并存至