springboot2 以验证码为例添加 servlet 三大组件

1. 结构布局

在这里插入图片描述

1.1 前端代码

html 代码

<img class="imgObj" th:alt="#{login.input_verifyCode}" th:src="@{/verifyCode}" onclick="changeImg()" />

js 代码

/* Refresh Pictures */
function changeImg() {
	var imgSrc = $(".imgObj");
	var src = imgSrc.attr("src");
	imgSrc.attr("src", changeUrl(src));
}
/* In order to make each generated image inconsistent, that is, not to let the browser read the cache, so you need to add a timestamp */
function changeUrl(url) {
	var timestamp = (new Date()).valueOf();
	var index = url.indexOf("?", url);
	if(index > 0) {
		url = url.substring(0, url.indexOf(url, "?"));
	}
	if((url.indexOf("&") >= 0)) {
		url = url + "×tamp=" + timestamp;
	} else {
		url = url + "?timestamp=" + timestamp;
	}
	return "verifyCode?" + url;
}

1.2 ServletConfig.java

package com.ykenan.ykenan.config;

import com.ykenan.ykenan.util.VerifyCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
 * Configuration: set Configuration
 */
@Configuration
public class ServletConfig {

    private static final Logger logger = LoggerFactory.getLogger(ListenerConfig.class);

    /**
     * Set the servlet path to take effect.
     * @return new ServletRegistrationBean<T extends servlet>(servlet.class, urlMapping)
     */
    @Bean
    public ServletRegistrationBean<VerifyCode> servletRegistrationBean() {
        logger.info("ADD Bean ServletRegistrationBean ---> new VerifyCode(), /verifyCode");
        return new ServletRegistrationBean<>(new VerifyCode(), "/verifyCode");
    }

    /**
     * set filter
     * @return new FilterRegistrationBean<T filter>()
     */
    @Bean
    public FilterRegistrationBean<FilterConfig> filterRegistrationBean() {
        logger.info("ADD Bean FilterRegistrationBean ---> new FilterConfig(), Arrays.asList(\"/\", \"/verifyCode\")");
        FilterRegistrationBean<FilterConfig> filterFilterRegistrationBean = new FilterRegistrationBean<>();
        filterFilterRegistrationBean.setFilter(new FilterConfig());
        filterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/", "/verifyCode"));
        return filterFilterRegistrationBean;
    }

    /**
     * set listener
     * @return new ServletListenerRegistrationBean<>(T listener)
     */
    @Bean
    public ServletListenerRegistrationBean<ListenerConfig> servletListenerRegistrationBean() {
        logger.info("ADD Bean ServletListenerRegistrationBean ---> new ListenerConfig()");
        return new ServletListenerRegistrationBean<>(new ListenerConfig());
    }

}

1.3 VerifyCode.java

package com.ykenan.ykenan.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * verifyCode
 */
public class VerifyCode extends HttpServlet {

    private static final Logger logger = LoggerFactory.getLogger(VerifyCode.class);

    private static final long serialVersionUID = 1L;

    /**
     * private static final attributes
     */
    /* The width of the picture. */
    private static final int WIDTH = 100;
    /* The height of the picture. */
    private static final int HEIGHT = 40;
    /* Number of Validation Code Characters. */
    private static final int CODE_COUNT = 4;
    /* Number of interference lines of verification code. */
    private static final int LINE_COUNT = 150;

    /* response header */
    private static final String RESPONSE_CONTENT_TYPE = "image/jpeg";
    /* response header */
    private static final String RESPONSE_HEADER_KEY_PRAGMA = "Pragma";
    /* response header */
    private static final String RESPONSE_HEADER_KEY_CACHE_CONTROL = "No-cache";
    /* response header */
    private static final String RESPONSE_HEADER_VALUE = "Cache-Control";
    /* response header */
    private static final String RESPONSE_DATE_HEADER_NAME = "no-cache";

    /* set font family */
    private static final String SET_FONT_FAMILY = "Times New Roman";
    /* set font size */
    private static final Integer SET_FONT_SIZE = 30;

    /* Where 0 is used. */
    private static final int NUMBER_ZERO = 0;

    /* random next int */
    private static final int RANDOM_NEXT_INT_12 = 12;


    /* image */
    private static final int IMAGE_RED = 50;
    /* image */
    private static final int IMAGE_GREEN = 20;
    /* image */
    private static final int IMAGE_BLUE = 30;
    /* image */
    private static final int IMAGE_RANDOM_NEXT_INT = 110;

    /* rand color */
    private static final int RAND_COLOR_160 = 160;
    /* rand color */
    private static final int RAND_COLOR_200 = 200;
    /* rand color */
    private static final int RAND_COLOR_255 = 255;

    /* draw string */
    private static final int TEXT_SPACING = 18;
    /* draw string */
    private static final int LEFT_MARGIN_SPACING = 13;
    /* draw string */
    private static final int UPPER_MARGIN_SPACING = 27;

    /* code in SESSION */
    private static final String CODE_IN_SESSION = "code";

    /* output image to page */
    private static final String IMAGE_IO_WRITE_FORMAT_NAME = "JPEG";

    /* Random Generation of 4-bit Verification Code */
    private static final char[] CODES = {'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

    /* logger info */
    private static final String LOGGER_INFO = "Verification Code Added Successfully.";

    /**
     * Forming verification codes
     *
     * @param request  request
     * @param response response
     * @throws IOException void
     */
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType(RESPONSE_CONTENT_TYPE);
        // Setting Pages Not Cached
        response.setHeader(RESPONSE_HEADER_KEY_PRAGMA, RESPONSE_HEADER_VALUE);
        response.setHeader(RESPONSE_HEADER_KEY_CACHE_CONTROL, RESPONSE_HEADER_VALUE);
        response.setDateHeader(RESPONSE_DATE_HEADER_NAME, NUMBER_ZERO);
        // Create images in memory
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        // Getting Graphic Context
        Graphics g = image.getGraphics();
        // Random class
        Random random = new Random();
        // Setting Background
        g.setColor(getRandColor(RAND_COLOR_200, RAND_COLOR_255));
        g.fillRect(NUMBER_ZERO, NUMBER_ZERO, WIDTH, HEIGHT);
        // set font
        g.setFont(new Font(SET_FONT_FAMILY, Font.PLAIN, SET_FONT_SIZE));
        // Random generation of interference lines
        g.setColor(getRandColor(RAND_COLOR_160, RAND_COLOR_200));
        for (int i = NUMBER_ZERO; i < LINE_COUNT; i++) {
            int x = random.nextInt(WIDTH);
            int y = random.nextInt(HEIGHT);
            int xl = random.nextInt(RANDOM_NEXT_INT_12);
            int yl = random.nextInt(RANDOM_NEXT_INT_12);
            g.drawLine(x, y, x + xl, y + yl);
        }
        // create a code container
        String code = "";
        for (int i = NUMBER_ZERO; i < CODE_COUNT; i++) {
            char c = CODES[random.nextInt(CODES.length)];
            // StringBuilder: String splicing is the fastest
            StringBuilder stringBuilder = new StringBuilder(code);
            stringBuilder.append(c);
            code = stringBuilder.toString();
            System.out.println(stringBuilder);
            // Display the authentication code in the image
            g.setColor(new Color(IMAGE_RED + random.nextInt(IMAGE_RANDOM_NEXT_INT), IMAGE_GREEN + random.nextInt(IMAGE_RANDOM_NEXT_INT), IMAGE_BLUE + random.nextInt(IMAGE_RANDOM_NEXT_INT)));
            // The call function produces the same color, probably because the seeds are too close to each other, so it can only be generated directly.
            g.drawString(String.valueOf(c), TEXT_SPACING * i + LEFT_MARGIN_SPACING, UPPER_MARGIN_SPACING); // Text spacing * i + distance left margin, upper margin
        }
        HttpSession session = request.getSession();
        // Store authentication code in SESSION
        session.setAttribute(CODE_IN_SESSION, code);
        // Image Effectiveness
        g.dispose();
        // Output image to page
        ImageIO.write(image, IMAGE_IO_WRITE_FORMAT_NAME, response.getOutputStream());
        // With the following code, java. lang. IllegalStateException: getOutputStream () has not occurred at runtime
        // already been called ..........Iso anomaly
        response.getOutputStream().flush();
        response.getOutputStream().close();
        response.flushBuffer();
        logger.info(LOGGER_INFO);
    }

    /**
     * bc > fc
     *
     * @param fc fc
     * @param bc bc
     * @return new Color(r, g, b)
     */
    private Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > RAND_COLOR_255)
            fc = RAND_COLOR_255;
        if (bc > RAND_COLOR_255)
            bc = RAND_COLOR_255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

}

1.4 FilterConfig.java

package com.ykenan.ykenan.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import java.io.IOException;

/**
 * Filter
 */
public class FilterConfig implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(FilterConfig.class);

    /**
     * Filter init
     * @param filterConfig filterConfig
     */
    @Override
    public void init(javax.servlet.FilterConfig filterConfig) {
        logger.info("filterConfig init...");
        System.out.println("init...");
    }

    /**
     * Filter doFilter
     * @param servletRequest servletRequest
     * @param servletResponse servletResponse
     * @param filterChain filterChain
     * @throws IOException IOException
     * @throws ServletException ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        logger.info("filterConfig doFilter...");
        System.out.println("doFilter...");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    /**
     * Filter destroy
     */
    @Override
    public void destroy() {
        logger.info("filterConfig destroy...");
        System.out.println("destroy...");
    }

}

1.5 ListenerConfig.java

package com.ykenan.ykenan.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * Listener
 */
public class ListenerConfig implements ServletContextListener {

    private static final Logger logger = LoggerFactory.getLogger(ListenerConfig.class);

    /**
     * Listener contextInitialized
     * @param sce sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        logger.info("ListenerConfig Web contextInitialized...");
        System.out.println("Web contextInitialized...");
    }

    /**
     * Listener contextDestroyed
     * @param sce sce
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        logger.info("ListenerConfig Web contextDestroyed...");
        System.out.println("Web contextDestroyed...");
    }
}

1.6 application.properties

# server
server.port=8081
server.servlet.context-path=/
server.tomcat.uri-encoding=UTF-8

# logger
logging.path=D:/install/IDEA/IDEALog
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ---> [%15.15t] %-40.40logger{39} : %m%n%wEx
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ---> [%15.15t] %-40.40logger{39} : %m%n%wEx

# spring
spring.mvc.favicon.enabled=false
spring.mvc.servlet.path=/
# spring static files
spring.resources.static-locations=classpath:/static/, classpath:/public/
# spring thymeleaf
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
# spring Internationalized Page Value i18n
spring.messages.basename=i18n.login, i18n.language

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值