login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>用户登录</title>
<meta name="description" content="particles.js is a lightweight JavaScript library for creating particles.">
<meta name="author" content="Vincent Garreau" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" media="screen" href="static/css/style.css">
<link rel="stylesheet" type="text/css" href="static/css/reset.css"/>
<link rel="stylesheet" type="text/css" href="static/layui/css/layui.css"/>
</head>
<body>
<div id="particles-js">
<form class="login layui-form">
<div class="login-top">
登录
</div>
<div class="login-center clearfix">
<!--隐藏的属性 ,默认值是 登录-->
<input type="hidden" name="service" value="login" />
<div class="login-center-img"><img src="static/img/name.png"/></div>
<div class="login-center-input">
<input type="text" value="abc" name="user_name" placeholder="用户名" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的用户名'"/>
<div class="login-center-input-text">用户名</div>
</div>
</div>
<div class="login-center clearfix">
<div class="login-center-img"><img src="static/img/password.png"/></div>
<div class="login-center-input">
<input type="password" value="abc" name="password" placeholder="用户密码" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的密码'"/>
<div class="login-center-input-text">密码</div>
</div>
</div>
<div class="login-center clearfix">
<div class="login-center-img"><img src="static/img/password.png"/></div>
<div class="login-center-input">
<input type="text" name="checkCode" placeholder="验证码" style="width: 130px"/>
<div class="login-center-input-text">验证码</div>
<img id="checkCode" alt="验证码" src="checkCode" style="width: 70px;margin-left: 20px">
</div>
</div>
<div class="login-button" lay-submit lay-filter="loginBtnFilter">
登录
</div>
</form>
<div class="sk-rotating-plane"></div>
</div>
<div style="text-align:center;">
</div>
<!-- scripts -->
<script src="static/layui/layui.js"></script>
<!--引入登录页 "星空粒子" js-->
<script src="static/js/particles.min.js"></script>
<!--登录页调整星空粒子间隔,坐标...-->
<script src="static/js/app.js"></script>
<script type="text/javascript">
//登录页面用到的 layui组件,有表单,弹层,jquery
layui.use(['form','layer','jquery'],function () {
var form = layui.form; //获取表单对象
var layer = layui.layer;//获取弹出层对象
var $ = layui.jquery;//获取layui内置的jquery对象
//提交登陆表单
form.on('submit(loginBtnFilter)',function (d) {
// d.field 等于 {key:value,key:value...}
$.post('user',d.field,function (rs) { //jquery的异步提交
if(rs.code==200){ //如果响应成功,则进入主页面
location.href='page?page=main';//PageServlet 负责管理页面跳转
return false;//终止执行
}
//弹出层的提示信息
layer.msg(rs.msg);
//如果验证码输入错误 再次刷新验证码 根据时间进行提交 防止上一次的验证码缓存
$("#checkCode").prop("src","checkCode"+"?"+new Date());
},"json");
return false; //组织表单名默认提交
});
//点击验证码进行切换
$("#checkCode").click(function(){
// 给 img对象的 src属性 ,重新赋值checkCode , 时间防止缓存
$(this).attr("src","checkCode?"+new Date());
});
});
</script>
</body>
</html>
CheckCodeServlet:
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//拿到 验证码工具类对象
CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(110, 40, 4, 6);
String code = circleCaptcha.getCode();//取出 4个字符
//将图片写出去
//将code 存入session
req.getSession().setAttribute("code",code);
circleCaptcha.write(resp.getOutputStream());
//resp.getWriter().print(image);
}
}
UserServlet:
@WebServlet("/user")
public class UserServlet extends HttpServlet {
UserService userService=new UserServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String service = req.getParameter("service");
try {
this.getClass().getDeclaredMethod(service,HttpServletRequest.class,HttpServletResponse.class).invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 登录
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取参数
String user_name = req.getParameter("user_name");
String password = req.getParameter("password");
String checkCode = req.getParameter("checkCode");
String str = (String) req.getSession().getAttribute("code");
//判断前台输入的checkCode是否和session里面的str一样
if(!StrUtil.equalsIgnoreCase(checkCode,str)){
JsonData jsonData = JsonData.buildError("验证码错误");
PrintJsonData.print(resp,jsonData);
return ;
}
//调取业务层,执行登陆
JsonData jsonData=userService.login(user_name,password);
if (jsonData.getData()!=null){
User user= (User) jsonData.getData();
req.getSession().setAttribute("user",user);
}
//将数据返回到页面
PrintJsonData.print(resp,jsonData);
}
业务层:
public class UserServiceImpl implements UserService {
UserDao userDao = new UserDaoImpl();
public JsonData login(String user_name, String password) {
User user = userDao.login(user_name, password);
if (user == null) {
return JsonData.buildError("用户名或密码有误");
}
if (user.getIs_del() == 2) {
return JsonData.buildError("当前用户不可用");
}
return JsonData.buildSuc(user);
}
}
持久层:
public class UserDaoImpl extends BaseDao implements UserDao {
public User login(String user_name, String password) {
String sql="select * from t_user where user_name=? and password=?";
return super.findOne(sql,User.class,user_name,password);
}
}
BaseDao:
/**
* 父类 封装jdbc
* 泛型: 第一种写到类名后面 比如: BaseDao<T>
* 第2中写到方法名中 public <T> T test(){}
*/
public class BaseDao {
/**
* 通过结果集 rs 给 clz对象 中的属性赋值
* @param rs
* @param clz
* @param <T>
* @return
*/
private <T> T rsToBean(ResultSet rs, Class<T> clz) {
try {
T t = clz.newInstance(); //通过反射拿到一个 类的实例 ,当前类可能是User ,或者是别的类
// 从rs 取值 ,赋值到 t中的 成员变量
ResultSetMetaData metaData = rs.getMetaData(); //获取当前表的 元数据 (表的结构信息)
int columnCount = metaData.getColumnCount(); //拿到列的总数量
for (int i = 0; i < columnCount; i++) {
String columnLabel = metaData.getColumnLabel(i + 1);//拿到 表中 列的名称 ,比如: id user_name/ password/ create_time.....
//user.setId(rs.getInt("id")); rs.getInt("id")===rs.getObject(columnLabel)
Object value = rs.getObject(columnLabel); //取出列名 对应的值
// getDeclaredField() 拿到当前类所有属性
Field field = clz.getDeclaredField(columnLabel); //根据 列名 拿到 类对应的 属性名 ,比如:id user_name/ password/ create_time
field.setAccessible(true); //提高 反射 效率
//赋值
field.set(t,value); //
}
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 查询单个对象
* @param sql
* @param clz
* @param param
* @param <T>
* @return
*/
public <T> T findOne(String sql,Class<T> clz,Object...param){
List<T> list = findList(sql, clz, param);
if(list!=null&&list.size()==1){
return list.get(0);
}
return null;
}
DBHelper:
public class DBHelper {
//1. 拿到 druid 的数据源
static DruidDataSource dataSource;
//2. 读取配置文件 ,初始化数据源
static {
Properties properties = new Properties();
InputStream is = DBHelper.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
properties.load(is);
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//3. 拿到数据库连接对象
public static Connection getConnection(){
try {
DruidPooledConnection conn = dataSource.getConnection();
return conn;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//4. 资源释放 (适用于增删改)
public static void close(Connection conn, PreparedStatement ps){
try {
if(conn!=null){
conn.close();
}
if(ps!=null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
try {
if(rs!=null){
rs.close();
}
close(conn,ps);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println(getConnection());
}
}
JsonData:
/**
* 封装 , 返回json的数据样式
*/
public class JsonData {
private Integer code; //响应码
private String msg; //描述信息
private Object data; //响应的数据
public JsonData(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static JsonData buildSuc(String msg, Object data){
return new JsonData(200,msg,data);
}
public static JsonData buildSuc(Object data){
return new JsonData(200,null,data);
}
public static JsonData buildSuc(String msg){
return new JsonData(200,msg,null);
}
public static JsonData buildError(String msg){
return new JsonData(50000,msg,null);
}
public static JsonData buildSuc() {
return new JsonData(200,null,null);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
PrintJsonData:
public class PrintJsonData {
public static void print(HttpServletResponse resp,JsonData jsonData){
resp.setContentType("text/html;charset=UTF-8");
String json = JSON.toJSONString(jsonData);
PrintWriter pw = null;
try {
pw = resp.getWriter();
pw.print(json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
效果展示:

本文介绍了一种使用Maven构建的Java Web应用中,通过Servlet实现登录页面(login.jsp)与验证码功能的方法。包括CheckCodeServlet用于生成验证码,UserServlet处理用户登录请求,业务层和持久层实现数据交互,BaseDao和DBHelper提供数据库操作支持,JsonData和PrintJsonData用于返回JSON数据,展示登录验证的整个流程和最终效果。
1232





