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