Eclipse integrates tomcat, without any framework, encapsulates native servlet and jdbc by itself to realize small web projects

Introduce

In fact, this originated from the experimental work of the course of software architecture, to experience the B/S architecture style. The original experiment required us to implement a simple registration and login function. However, the school's curriculum system structure is very fascinating. Technical courses such as php and java web are all electives, and the java web courses of this semester skip the servlet and teach SSM directly.

So the teacher of the experiment class gave the php and java code, but the code is relatively simple and does not consider function expansion. I still choose to write it myself. . .

Integrate tomcat on Eclipse EE, encapsulate native servlet and jdbc, and realize login demo. At the same time, such encapsulation can support the realization of a small web project without any java framework.

Effect picture

Integrate tomcat on Eclipse EE

1. Add a Server

2. Add the jar package related to servlet

Tomcat is a web application server written in java that supports servlet and jsp. The jar packages related to servlet and jsp are not built in jdk, but come from tomcat's class library (lib directory under the installation directory). We need to add tomcat runtime class library to the newly created web project, otherwise there is no way to use servlet and jsp in the project.

   

   

3. Set the port number and context-path

   

Dao layer encapsulates jdbc to simplify database operations

1. Import the corresponding version of the driver jar package

2. Write a custom configuration file for database connection

JDBC.properties

# 中心仓库:https://mvnrepository.com/

# mysql驱动jar包
# 8.0.16:https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.16
# 5.1.47:https://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.47

# 数据库连接的基本配置
user=root
password=ysqJYKL2010
# 不设置useSSL会有警告
url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&useSSL=true
driver=com.mysql.jdbc.Driver

3. Write a class for obtaining database connections

DbConnector.java

package dao;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import utils.CloseUtil;

/**
 * 数据库连接类 初始化数据库连接配置,获取数据库连接
 * 
 * @author passerbyYSQ
 * @date 2020-9-29 14:19:37
 */
public class DbConnector {

	/**
	 * 连接数据库的基本配置,从配置文件读入。
	 */
	private static String user;
	private static String password;
	// 数据库连接协议的url
	private static String url;
	// 数据库驱动包的类路径
	private static String driver;

	// 存储配置文件的数据结构Properties
	private static Properties configProp = new Properties();

	static {
		InputStream inputStream = null;
		try {
			ClassLoader classLoader = DbConnector.class.getClassLoader();
			// 在src目录下获取JDBC.properties的输入流
			inputStream = classLoader.getResourceAsStream("JDBC.properties");

			if (inputStream == null) {
				throw new RuntimeException("配置文件不存在");
			}

			// 将配置文件加载到configProp
			configProp.load(inputStream);

			user = configProp.getProperty("user");
			password = configProp.getProperty("password");
			url = configProp.getProperty("url");
			driver = configProp.getProperty("driver");

			// 注册数据库驱动包
			Class.forName(driver);
//			System.out.println("注册数据库驱动包成功!");

		} catch (IOException | ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			CloseUtil.close(inputStream);
		}
	}

	/**
	 * 获取一个数据库连接对象
	 * 
	 * @return
	 */
	public static Connection getConnection() {
		try {
			return DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 释放资源
	 * 
	 * @param stmt 执行sql语句的对象
	 * @param conn 数据库连接对象
	 */
	public static void close(Statement stmt, Connection conn) {
		close(null, stmt, conn);
	}

	/**
	 * 释放资源的重载形式
	 * 
	 * @param rs   结果集对象
	 * @param stmt 执行sql语句的对象
	 * @param conn 数据库连接对象
	 */
	public static void close(ResultSet rs, Statement stmt, Connection conn) {
		try {
			if (rs != null) {
				rs.close();
			}
			if (stmt != null) {
				stmt.close();
			}
			if (conn != null) {
				conn.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

4. Write basic database operation tools

DaoUtil.java

package dao;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Date;
 
/**
 * 基础的数据库操作工具类
 * 简化通用的基础的增删改查的操作,与具体业务逻辑无关
 * 
 * @author	passerbyYSQ
 * @date	2020-9-29 14:51:16
 */
public class DaoUtil {
	/**
	 * 通用的查询操作
	 * 
	 * @param <T>	查询返回的数据,基类中无法确定,需要通过泛型抛给子类
	 * @param sql	sql语句(里面有占位符)
	 * @param pack	一个接口,该接口有个抽象方法将ResultSet回调给子类,让子类来处理ResultSet中数据
	 * @param args	与占位符一一对应的参数值
	 * @return		封装后的查询结果
	 */
	public static <T> T select(String sql, PackResult<T> pack, Object... args) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet resultSet = null;
		T result = null;
		try {
			conn = DbConnector.getConnection();
			pstmt = conn.prepareStatement(sql);
			
			// 将参数设置到sql语句的占位符中
			setValue(pstmt, args);
			
			resultSet = pstmt.executeQuery();
 
			// 由于不同的表对应不同的实体类,在基类中无法实现将resultSet封装成对应的实体类返回
			// 故只能通过接口中的回调函数交给子类去实现
			result = pack.onResultReturn(resultSet);
			return result;
 
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			DbConnector.close(resultSet, pstmt, conn);
		}
	}
	
	/**
	 * 获取结果集数量
	 * @param from	from部分,传递时不需要带"from"。之所以传递from部分,而不是表名,是考虑到多表查询
	 * @param where	where部分,传递时不需要带"where",里面含有占位符
	 * @param args	代替占位符的参数值
	 * @return		记录数
	 */
	public static int getCount(String from, String where, Object... args) {
		String sql = "select count(*) from " + from + " where " + where;
 
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet resultSet = null;
		try {
			conn = DbConnector.getConnection();
			pstmt = conn.prepareStatement(sql);
			
			// 将参数设置到sql语句的占位符中
			setValue(pstmt, args);
			
			resultSet = pstmt.executeQuery();
			// 获取失败返回-1
			return resultSet.next() ? resultSet.getInt(1) : -1;
 
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		} finally {
			DbConnector.close(resultSet, pstmt, conn);
		}
 
	}
	
	/**
	 *  插入记录,比较适用于插入一条或几条数据。不适合插入一个集合的数据
	 * @param sql	sql语句(里面有占位符)
	 * @param args	与占位符一一对应的参数值
	 * @return		受影响的行数
	 */
	public static int insertOrUpdateOrDelete(String sql, Object... args) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		int count = 0;
		try {
			conn = DbConnector.getConnection();
			pstmt = conn.prepareStatement(sql);
			
			// 将参数设置到sql语句的占位符中
			setValue(pstmt, args);
			//System.out.println(pstmt.toString());
			
			// 受影响的行数
			count = pstmt.executeUpdate();
			return count;
			
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		} finally {
			DbConnector.close(pstmt, conn);
		}
	}
	
	/**
	 * 事务操作
	 * 如果实现类不使用回调的PreparedStatement和ResultSet的引用,
	 * 而是选择自己new新的实例,那么就需要自己负责资源关闭
	 * 
	 * @param sqlEntitys	
	 */
	public static void updateInTransaction(MoreUpdate moreUpdate) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DbConnector.getConnection();
			conn.setAutoCommit(false); // 开启事务(手动提交)
			
			moreUpdate.updateActions(conn, pstmt, rs);
			
			conn.commit(); // 提交事务
			
		} catch (SQLException e) {
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DbConnector.close(rs, pstmt, conn);
		}
	}
	
	/**
	 * 插入一条记录。如果主键是自增长的,返回该条记录的id
	 * 注意:主键必须是自增长的!!!
	 * @param sql
	 * @param args
	 * @return
	 */
	public static int insertReturnId(String sql, Object... args) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			conn = DbConnector.getConnection();
			pstmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
 
			// 将参数设置到sql语句的占位符中
			setValue(pstmt, args);
			//System.out.println(pstmt.toString());
 
			pstmt.executeUpdate();
			// 获取最后插入的记录的自增长id。修改是不会返回的
			rs = pstmt.getGeneratedKeys();
 
			return rs.next() ? rs.getInt(1) : 0;
 
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		} finally {
			DbConnector.close(rs, pstmt, conn);
		}
	}
 
 
	// 将参数设置到sql语句的占位符中
	public static void setValue(PreparedStatement pstmt, Object... args) throws SQLException {
		for (int i = 0; i < args.length; i++) {	
			if (args[i] instanceof String) { // 主要
				pstmt.setString(i + 1, (String) args[i]);
			} else  if (args[i] instanceof Integer) { // 主要
				int num = (Integer) args[i];
				pstmt.setInt(i + 1, num);
			} else  if (args[i] instanceof LocalDateTime) { // 主要
				pstmt.setTimestamp(i + 1, Timestamp.valueOf((LocalDateTime) args[i]));
			} else if (args[i] instanceof Date) { // 主要 ((Date) args[i]).getTime()
				pstmt.setTimestamp(i + 1, new Timestamp(((Date) args[i]).getTime()));
			} else if (args[i] instanceof BigDecimal) {
				pstmt.setBigDecimal(i + 1, (BigDecimal) args[i]);
			} else if (args[i] instanceof Double) {
				pstmt.setDouble(i + 1, (Double) args[i]);
			} else if (args[i] instanceof Float) {
				pstmt.setFloat(i + 1, (Float) args[i]);
			} else if (args[i] instanceof Boolean) {
				pstmt.setBoolean(i + 1, (boolean) args[i]);
			} else {
				throw new RuntimeException("DaoUtil类暂不支持set该数据类型");
			}
		}
	}
	
	public interface PackResult<T> {
		// 将ResultSet回调给子类,让调用者来处理ResultSet中的数据(转换成特定的pojo)
        T onResultReturn(ResultSet rs) throws Exception; 
	}
	
	public interface MoreUpdate {
		/**
		 * 多种update相关的操作
		 * 
		 * 如果实现类不使用回调的pstmt,而是选择自己new新的pstmt,那么
		 * 就需要自己负责pstmt的关闭操作。
		 * 
		 * @param conn
		 * @param pstmt		回调给实现类的是null
		 * @throws SQLException 
		 */
		void updateActions(Connection conn, PreparedStatement pstmt, ResultSet rs) throws SQLException;
	}
	
}

5. Write the entity class corresponding to the database table

There is only one tb_user table, corresponding to the User entity class

User.java

package entity;

import java.time.LocalDateTime;

/**
 * 用户实体类
 * 数据库表所对应的实体类
 * 
 * @author	passerbyYSQ
 * @date	2020-9-30 20:46:28
 */
public class User {
	
	private Integer userId;
	
	private String username;
	
	private String password;
	
	// 最后一次登录的时间
	private LocalDateTime lastLoginTime;
	
	public User(Integer userId, String username) {
		this.userId = userId;
		this.username = username;
	}

	public Integer getUserId() {
		return userId;
	}

	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public LocalDateTime getLastLoginTime() {
		return lastLoginTime;
	}

	public void setLastLoginTime(LocalDateTime lastLoginTime) {
		this.lastLoginTime = lastLoginTime;
	}
}

Write Servlet

1. The servlet that generates the verification code image

VerificationCodeServlet.java

package servlet;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 生成简单的验证码图片
 * 
 * @author	passerbyYSQ
 * @date	2020-9-30 20:24:02
 */
@WebServlet("/verification_code")
public class VerificationCodeServlet extends HttpServlet {
	private static final long serialVersionUID = 2523187418823246381L;
	
	private Integer width = 100;
	private Integer height = 40;
	private Integer charCnt = 4; // 验证码图片中字符的个数
	private Integer lineCnt = 8;

	private Random r = new Random(); // 用于生产随机数

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 创建图片对象
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

		Graphics g = image.getGraphics();
				
		// 填充背景色
		g.setColor(getBgColor());
		g.fillRect(0, 0, width, height);

		g.setFont(new Font("黑体", Font.BOLD, 30));
		// 写字符
		StringBuilder sbd = new StringBuilder();
		for (int i = 1; i <= charCnt; i++) {
			g.setColor(getCharColor());
			int x = width / (charCnt + 2) * i;
			int y = height * 2 / 3;
			char c = getRandomChar();
			sbd.append(c);
			g.drawString(c + "", x, y);
		}
		request.getSession().setAttribute("verification_code", sbd.toString());

		for (int i = 1; i < lineCnt; i++) {
			int x1 = r.nextInt(width);
			int y1 = r.nextInt(height);

			int x2 = r.nextInt(width);
			int y2 = r.nextInt(height);

			g.setColor(getLineColor());
			g.drawLine(x1, y1, x2, y2);
		}

		// 输出图片
		ImageIO.write(image, "jpg", response.getOutputStream());
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	/**
	 * 生成一个在区间[low, high]的随机整数
	 * 
	 * @param low
	 * @param high
	 * @return
	 */
	private int getInt(int low, int high) {
		return (low + r.nextInt(high - low + 1));
	}

	/**
	 * 生成一种背景色(相对字符颜色来说较浅)
	 * 
	 * @return
	 */
	private Color getBgColor() {
		int red = getInt(170, 255);
		int green = getInt(170, 255);
		int blue = getInt(170, 255);
		return new Color(red, green, blue);
	}

	/**
	 * 生成一种干扰线的颜色
	 * 
	 * @return
	 */
	private Color getLineColor() {
		int red = getInt(85, 169);
		int green = getInt(85, 169);
		int blue = getInt(85, 169);
		return new Color(red, green, blue);
	}

	/**
	 * 生成一种字符颜色(相对字体颜色较深)
	 * 
	 * @return
	 */
	private Color getCharColor() {
		int red = getInt(0, 84);
		int green = getInt(0, 84);
		int blue = getInt(0, 84);
		return new Color(red, green, blue);
	}

	/**
	 * 生成一个随机字符
	 * 
	 * @return
	 */
	private char getRandomChar() {
		final String chs = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
		return chs.charAt(r.nextInt(chs.length()));
	}

}

2. Login servlet

LoginServlet.java

package servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import entity.User;
import service.AccountService;
import service.impl.AccountServiceImpl;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1821754212240924673L;
	
	private AccountService accountService = new AccountServiceImpl();

	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		// 获取username
		String username = request.getParameter("username");
		// 获取密码
		String password = request.getParameter("password");
		// 简单的参数判断
		if (username == null || "".equals(username)) {
			request.setAttribute("login_error", "用户名不能为空");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}
		if (password == null || "".equals(password)) {
			request.setAttribute("login_error", "密码不能为空");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}
		
		// 获取用户输入的验证码
		String codeByUser = request.getParameter("verification_code");
		HttpSession session = request.getSession();
		// 取出正确的验证码
		String correctCode = (String) session.getAttribute("verification_code");
		// 验证码是一次性的,取出后失效
		session.removeAttribute("verification_code");
		
		if (codeByUser == null || "".equals(codeByUser)
				|| !codeByUser.equalsIgnoreCase(correctCode)) {
			request.setAttribute("login_error", "验证码错误");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}
		
		User user = accountService.login(username, password);
		if (user == null) {
			request.setAttribute("login_error", "用户名或者密码错误");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
		}
		
		// 登录成功
		session.setAttribute("username", user.getUsername()); 
		response.sendRedirect(request.getContextPath() + "/index.jsp");
	}
}

3. Log out of the servlet

LogoutServlet.java

package servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    
	private static final long serialVersionUID = 5967081510030254471L;
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		String username = (String) session.getAttribute("username");
		
		if (username != null) {
			session.removeAttribute("username");
		}
		response.sendRedirect(request.getContextPath() + "/login.jsp");
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

Write the Service layer

AccountServiceImpl.java

package service.impl;

import java.sql.ResultSet;
import java.time.LocalDateTime;

import dao.DaoUtil;
import entity.User;
import service.AccountService;

/**
 * @author	passerbyYSQ
 * @date	2020-9-30 20:50:33
 */
public class AccountServiceImpl implements AccountService {

	@Override
	public User login(String username, String password) {
		String sql = "select * from tb_user where username=? and password=?";
		User user = DaoUtil.select(sql, new DaoUtil.PackResult<User>() {
			@Override
			public User onResultReturn(ResultSet rs) throws Exception {
				if (!rs.next()) {
					return null;
				}
				int userId = rs.getInt("id");
				String username = rs.getString("username");
				// 密码不需要取出
				return new User(userId, username);
			}
		}, username, password);
		
		// 登录成功,更新最后一次登录的时间
		if (user != null) {
			sql = "update tb_user set last_login_time=? where id=?";
			DaoUtil.insertOrUpdateOrDelete(sql, LocalDateTime.now(), user.getUserId());
		}
		
		return user;
	}

}

Write a login filter

Non-login users cannot access the homepage, and logged-in users cannot access the login page

LoginFilter.java 

package filter;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * 拦截器,用于验证是否已经登录
 * 
 * @author	passerbyYSQ
 * @date	2020-10-1 16:28:20
 */
@WebFilter(
		filterName = "loginFilter",
		// 实际上可以把需要拦截的页面分类到某个目录下,某些api也分类,
		// 这样拦截的针对性更强,需要排除的也更少
		urlPatterns = "/*", // 拦截所有url
		initParams = {
			// 不拦截某些页面、api、静态资源
			@WebInitParam(name = LoginFilter.EXECUDED_PAGE, value="login.jsp"),
			@WebInitParam(name = LoginFilter.EXECUDED_API, 
				value="login;logout;verification_code"),
			@WebInitParam(name = LoginFilter.EXECUDED_RESOURCE, 
				value=".jpg;.png;.jpeg;.css;.js"),
			@WebInitParam(name = "encoding", value = "utf-8"), // 编码
		}		
)
public class LoginFilter implements Filter {
	// 页面
	public static final String EXECUDED_PAGE = "EXECUDED_PAGE";
	// API
	public static final String EXECUDED_API = "EXECUDED_API";
	// 静态资源
	public static final String EXECUDED_RESOURCE = "EXECUDED_RESOURCE";
	
	private FilterConfig filterConfig;
	private Set<String> execudedUrl = new HashSet<>();

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;
		processInitParamArray(EXECUDED_PAGE);
		processInitParamArray(EXECUDED_API);
		processInitParamArray(EXECUDED_RESOURCE);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;
	
		// 设置字符集,防止post表单乱码
		String encoding = filterConfig.getInitParameter("encoding");
		if (encoding == null) {
			encoding = "utf-8";
		}
		httpRequest.setCharacterEncoding(encoding);
		
		// 判断是否需要拦截。默认需要拦截
		boolean isNeedFilter = true;
		String uri = httpRequest.getRequestURI();
		for (String str : execudedUrl) {
			if (uri.endsWith(str)) { // 注意用endsWith
				// 不需要拦截
				isNeedFilter = false;
				break;
			}
		}
		
		HttpSession session = httpRequest.getSession();
		String username = (String) session.getAttribute("username");
		
		// 不需要拦截,放行
		if (!isNeedFilter) {
			if ((uri.endsWith("login") || uri.endsWith("login.jsp")) && username != null) {
				// 已登录,不能访问登录页面
				httpResponse.sendRedirect(httpRequest.getContextPath() + "/index.jsp");
			} else {
				chain.doFilter(httpRequest, httpResponse);
			}
		} else {
			if (username != null) {
				// 已登录,放行
				chain.doFilter(httpRequest, httpResponse);
			} else {
				// 未登录。重定向到登录界面
				httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
			}
		}
	}

	@Override
	public void destroy() {
		filterConfig = null;
		execudedUrl.clear();
	}
	
	private void processInitParamArray(String key) {
		String param = filterConfig.getInitParameter(key);
		if (param != null) {
			String[] split = param.split(";");
			for (String str : split) {
				// 静态资源
				if (!"".equals(str)) {
					execudedUrl.add(str);
				}
			}
		}
	}

}

Okay, it's over! ! !

The front page is relatively simple, so I won’t post it. Some people may ask, isn’t it just a login function that needs so much to write? Note that our focus is to encapsulate native servlet and jdbc, which can be extended to support the development of small web projects. It's just that we use the login function as a demo. This has great reference significance for students who have studied java web but have not been exposed to the java framework.

Guess you like

Origin blog.csdn.net/qq_43290318/article/details/108904161