项目创建
1. 创建一个动态web项目
2.创建三层架构模式及常用类包
3.导入相关的jar包
4.我们导入静态页面
5.编写Druid工具包
1.编写DruidUtil工具类
package com.ty.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.junit.Test;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DruidUtil {
private static DataSource ds = null;
private Connection connection = null;
static {
Properties properties = new Properties();
// FileInputStream is = new FileInputStream("src/druid.properties");
InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
try {
properties.load(is);
ds = DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 从连接池中获取连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放连接的使用权,把连接交回池中
* @param rs
* @param stmt
* @param conn
*/
public static void disResource(ResultSet rs ,Statement stmt,Connection conn) {
try {
if(rs!=null) {
rs.close();
}
if(stmt!=null) {
stmt.close();
}
if(conn!=null) {
conn.close();
}
}catch(Exception e) {
e.printStackTrace();
}
}
/**
* 返回数据源
* @return
*/
public static DataSource getDataSource() {
return ds;
}
@Test
public void test() throws SQLException {
System.out.println(getConnection());
}
}
2.编写druid.properties配置文件
该文件必须放在根目录下(src目录下)
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/data_base?serverTimezone=GMT%2B8
username=root
password=123456
initialSize=5
maxActive=10
maxWait=5000
6.注意事项
1.在每个jsp页面中,我们要有一个basePath变量,它主要是获取项目路径
<% String basePath = request.getContextPath(); %>
7.创建一个统一设置post请求乱码解决的过滤器
package com.ty.filter;
import java.io.IOException;
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;
/**
* Servlet Filter implementation class CharacterEncodingFilter
*/
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//对request进行增强
request.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
数据库的创建
创建用户表
CREATE TABLE `shop_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`password` varchar(80) DEFAULT NULL,
`status` int(1) DEFAULT '0' COMMENT '用户状态0:激活,1:锁定',
`real_name` varchar(50) DEFAULT NULL,
`sex` int(1) DEFAULT '0' COMMENT '性别:0:男1:女',
`idcard` varchar(18) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
添加一条测试数据
insert into shop_user value (null,'ty','skdfjskldjf0',0,'涛',1,'142000000000000');
创建用户表对应的实体类
package com.ty.entity;
public class ShopUser {
private Integer id;
private String username;
private String password;
private String realName;
private Integer sex;
private Integer status;
private String idcard;
//getter/setter方法
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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 String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getIdcard() {
return idcard;
}
public void setIdcard(String idcard) {
this.idcard = idcard;
}
}
实现用户登录功能
1.创建登录页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String basePath = request.getContextPath();
%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="static/h-ui/css/H-ui.min.css" rel="stylesheet" type="text/css" />
<link href="static/h-ui.admin/css/H-ui.login.css" rel="stylesheet" type="text/css" />
<link href="static/h-ui.admin/css/style.css" rel="stylesheet" type="text/css" />
<link href="lib/Hui-iconfont/1.0.8/iconfont.css" rel="stylesheet" type="text/css" />
<title>后台管理登录页面</title>
</head>
<body>
<input type="hidden" id="TenantId" name="TenantId" value="" />
<div class="header"></div>
<div class="loginWraper">
<div id="loginform" class="loginBox">
<form class="form form-horizontal" action="/login" method="post">
<div class="row cl">
<label class="form-label col-xs-3"><i class="Hui-iconfont"></i></label>
<div class="formControls col-xs-8">
<input id="" name="username" type="text" placeholder="账户" class="input-text size-L" value="${map.username}">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-3"><i class="Hui-iconfont"></i></label>
<div class="formControls col-xs-8">
<input id="" name="password" type="password" placeholder="密码" class="input-text size-L">
</div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<input name="validateCode" class="input-text size-L" type="text" placeholder="验证码" onblur="if(this.value==''){this.value='验证码:'}" onclick="if(this.value=='验证码:'){this.value='';}" value="验证码:" style="width:150px;">
<img src="<%=basePath %>/generateCodeImage" id="codeImage"> <a id="kanbuq" href="javascript:;">看不清,换一张</a> </div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<label for="online">
<input type="checkbox" name="online" id="online" value="">
使我保持登录状态</label>
</div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<input name="" type="submit" class="btn btn-success radius size-L" value=" 登 录 ">
<input name="" type="reset" class="btn btn-default radius size-L" value=" 取 消 ">
</div>
</div>
</form>
<!--新增-->
<div style="width:300px;height:50px;line-height:50px;margin: auto;color:red">
<c:if test="${not empty map&& map.flag==1}">
${map.msg }
</c:if>
</div>
</div>
</div>
<div class="footer">Copyright 2020后台</div>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$("#kanbuq").click(function(){
var temp = "<%=basePath %>/generateCodeImage?"+Math.random();
$("#codeImage").attr("src",temp);
})
</script>
</body>
</html>
2.创建生成验证码的工具类
package com.ty.util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
public class ImageCodeGeneratorUtil {
//验证码
public static final String VERTIFICATION_CODE ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/**
*
* @param size
* @param sourceCode
* @return
*/
public static String generateCode(int size,String sourceCode) {
Random random = new Random(System.currentTimeMillis());
char[] codes= new char[size];
for(int i=0;i<size;i++) {
codes[i]=sourceCode.charAt(random.nextInt(sourceCode.length()-1));
}
return String.valueOf(codes);
}
public static void generateCodeImage(OutputStream os,String vertifyCode,int width,int height) {
int verifySize = vertifyCode.length();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
// 生成随机类
Random random = new Random();
// 设定背景色
g.setColor(getRandColor(230, 255));
g.fillRect(0, 0, width, height);
// 设定字体
g.setFont(new Font("Arial", Font.CENTER_BASELINE | Font.ITALIC, 23));
// 产生0条干扰线,
g.drawLine(0, 0, 0, 0);
// 取随机产生的认证码(4位数字)
String sRand = "";
for (int i = 0; i < verifySize; i++) {
// 将认证码显示到图象中
g.setColor(getRandColor(100, 150));// 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(String.valueOf(vertifyCode.charAt(i)), i * (width/verifySize) +5, 30);
}
//画干扰线
for(int i=0;i<(random.nextInt(50)+5);i++){
g.setColor(new Color(random.nextInt(255)+1,random.nextInt(255)+1,random.nextInt(255)+1));
g.drawLine(random.nextInt(width),random.nextInt(height),random.nextInt(width)+5,random.nextInt(height)+5);
}
// 图象生效
g.dispose();
// 输出图象到页面
try {
ImageIO.write(image, "JPEG", os);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println(generateCode(6, VERTIFICATION_CODE));
}
private static Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 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);
}
}
3.创建生成验证码的Servlet
package com.ty.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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 com.fubo.util.ImageCodeGeneratorUtil;
@WebServlet("/generateCodeImage")
public class GenerateCodeServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String code = ImageCodeGeneratorUtil.generateCode(4, ImageCodeGeneratorUtil.VERTIFICATION_CODE);
ServletOutputStream outputStream = resp.getOutputStream();
ImageCodeGeneratorUtil.generateCodeImage(outputStream, code, 100, 40);
HttpSession session = req.getSession();
session.setAttribute("code", code);
}
}
4.修改登录页面,加入验证码
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<input class="input-text size-L" type="text" placeholder="验证码" onblur="if(this.value==''){this.value='验证码:'}" onclick="if(this.value=='验证码:'){this.value='';}" value="验证码:" style="width:150px;">
<img src="<%=basePath %>/generateCodeImage" id="codeImage"> <a id="kanbuq" href="javascript:;">看不清,换一张</a>
</div>
</div>
<script type="text/javascript" src="<%=basePath %>/js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$("#kanbuq").click(function(){
var temp = "<%=basePath %>/generateCodeImage?"+Math.random();
$("#codeImage").attr("src",temp);
})
</script>
5.编写登录功能后台代码
1.控制层实现
package com.ty.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 com.ty.service.ShopUserService;
import com.ty.util.MD5Util;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
ShopUserService shopUserService = new ShopUserService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String,Object> map = new HashMap<String, Object>();
int flag = 0;
String msg = "";
String username = req.getParameter("username");
String password = req.getParameter("password");
String validateCode = req.getParameter("validateCode");
if((username==null||username.equals(""))
||(password==null||password.equals(""))
||(validateCode==null||validateCode.equals(""))) {
flag = 1;
msg="用户名和密码不能为空!";
map.put("flag", flag);
map.put("msg", msg);
req.getSession().setAttribute("map", map);
//再次请求转发到登录页面
req.getRequestDispatcher("login.jsp").forward(req, resp);
return;
}
//session域中获取生成的验证码
Object attribute = req.getSession().getAttribute("code");
String sessionCode = null;
if(attribute!=null) {
sessionCode = String.valueOf(attribute);
}
//验证码的判断
if(!sessionCode.equalsIgnoreCase(validateCode)) {
flag = 1;
msg="验证码不正确!";
map.put("flag", flag);
map.put("msg", msg);
req.getSession().setAttribute("map", map);
//再次请求转发到登录页面
req.getRequestDispatcher("login.jsp").forward(req, resp);
return;
}
//调用业务层判断用户名和密码
Map<String, Object> returnMap = shopUserService.login(username,MD5Util.MD5(password));
Object object = returnMap.get("flag");//Object类型转String
if(String.valueOf(object).equals("0")) {
//验证正确后保存用户信息到session并重定向到主页
req.getSession().setAttribute("user", returnMap.get("user"));
resp.sendRedirect("index.jsp");
}else {
//如果密码错误时,应当把用户名保存
Object object2 = returnMap.get("msg");
if(String.valueOf(object2).equals("密码错误!")) {
returnMap.put("username", username);
}
//flag=1时继续跳到登录页面
req.getSession().setAttribute("map", returnMap);
//再次请求转发到登录页面
req.getRequestDispatcher("login.jsp").forward(req, resp);
return;
}
}
}
2.业务逻辑层
package com.ty.service;
import java.util.HashMap;
import java.util.Map;
import com.ty.dao.ShopUserDao;
import com.ty.entity.ShopUser;
public class ShopUserService {
ShopUserDao shopUserDao = new ShopUserDao();
public Map<String, Object> login(String username, String password) {
Map<String, Object> returnMap = new HashMap<String, Object>();
int flag = 0;
String msg = "";
//调用持久层查询用户信息
ShopUser user = shopUserDao.findUserByName(username);
//判断用户名
if(user!=null) {
//判断密码
if(user.getPassword().equals(password)) {
returnMap.put("user", user);
}else {
flag = 1;
msg = "密码错误!";
}
}else {
msg = "用户名不存在!";
flag = 1;
}
returnMap.put("flag", flag);
returnMap.put("msg",msg);
return returnMap;
}
}
3.持久层实现
package com.ty.dao;
import java.util.List;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import com.ty.entity.ShopUser;
import com.ty.util.DruidUtil;
public class ShopUserDao {
JdbcTemplate jdbcTemplate = new JdbcTemplate(DruidUtil.getDataSource());
public ShopUser findUserByName(String username) {
String sql = "select * from shop_user where username = ?";
List<ShopUser> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<ShopUser>(ShopUser.class),username);
ShopUser user = null;
if(users.size()>0) {
user = users.get(0);
}
return user;
}
}
login.jsp页面修改
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String basePath = request.getContextPath();
%>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link href="static/h-ui/css/H-ui.min.css" rel="stylesheet" type="text/css" />
<link href="static/h-ui.admin/css/H-ui.login.css" rel="stylesheet" type="text/css" />
<link href="static/h-ui.admin/css/style.css" rel="stylesheet" type="text/css" />
<link href="lib/Hui-iconfont/1.0.8/iconfont.css" rel="stylesheet" type="text/css" />
<title>后台管理登录页面</title>
</head>
<body>
<input type="hidden" id="TenantId" name="TenantId" value="" />
<div class="header"></div>
<div class="loginWraper">
<div id="loginform" class="loginBox">
<form class="form form-horizontal" action="/login" method="post">
<div class="row cl">
<label class="form-label col-xs-3"><i class="Hui-iconfont"></i></label>
<div class="formControls col-xs-8">
<input id="" name="username" type="text" placeholder="账户" class="input-text size-L" value="${map.username}">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-3"><i class="Hui-iconfont"></i></label>
<div class="formControls col-xs-8">
<input id="" name="password" type="password" placeholder="密码" class="input-text size-L">
</div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<input name="validateCode" class="input-text size-L" type="text" placeholder="验证码" onblur="if(this.value==''){this.value='验证码:'}" onclick="if(this.value=='验证码:'){this.value='';}" value="验证码:" style="width:150px;">
<img src="<%=basePath %>/generateCodeImage" id="codeImage"> <a id="kanbuq" href="javascript:;">看不清,换一张</a> </div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<label for="online">
<input type="checkbox" name="online" id="online" value="">
使我保持登录状态</label>
</div>
</div>
<div class="row cl">
<div class="formControls col-xs-8 col-xs-offset-3">
<input name="" type="submit" class="btn btn-success radius size-L" value=" 登 录 ">
<input name="" type="reset" class="btn btn-default radius size-L" value=" 取 消 ">
</div>
</div>
</form>
<!--新增-->
<div style="width:300px;height:50px;line-height:50px;margin: auto;color:red">
<c:if test="${not empty map&& map.flag==1}">
${map.msg }
</c:if>
</div>
</div>
</div>
<div class="footer">Copyright 2020后台</div>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$("#kanbuq").click(function(){
var temp = "<%=basePath %>/generateCodeImage?"+Math.random();
$("#codeImage").attr("src",temp);
})
</script>
</body>
</html>
实现后台用户验证功能
创建一个ValidateUserFilter
package com.ty.filter;
import java.io.IOException;
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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Servlet Filter implementation class ValidateUserFilter
*/
@WebFilter("/*")
public class ValidateUserFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//进行request对象转换
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();
if(uri.contains("login.jsp")||uri.contains("/login")||uri.contains("/generateCodeImage")||uri.contains("/js/")
||uri.contains("/lib/")||uri.contains("/temp/")||uri.contains("/static/")||uri.contains("/css/")||uri.contains("/images/")) {
chain.doFilter(request, response);
}else {
HttpSession session = req.getSession();
Object userObj = session.getAttribute("user");
if(userObj!=null) {
chain.doFilter(request, response);
}else {
HttpServletResponse resp = (HttpServletResponse) response;
resp.sendRedirect("login.jsp");
}
}
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
加入MD5Util工具类
使用该工具类对密码进行加密
package com.ty.util;
import java.security.MessageDigest;
public class MD5Util {
public static String MD5(String key) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try {
byte[] btInput = key.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
public static void main(String[] args) {
System.out.println(MD5("456123"));
}
}