看完视频学完cookie和session后来总结完成一个小案例,还是有点小难度的.
案例说明
1.访问带有验证码的登录页面login.jsp
2.用户输入用户名,密码以及验证码
2.1 如果用户名和密码输入有问题,跳转登录页面,提示用户名或密码错误
2.2 如果验证码输入有误,跳转登录页面,提示:验证码错误
2.3 如果全部输入正确,则跳转页面success.jsp,显示:用户名,欢
总结一下:用户在login.jsp页面上输入信息,得到这些信息后,判断信息是否正确,信息正确则拿着用户信息重定向success.jsp页面,失败则重新跳转登录登录页面并提示错误信息.
提前的准备
我们需要导入jar包,分别是JDBC的包,mysql连接的包,druid的包Beanutils的包,将jar包下载后放在web下的WEB_INF文件中
jar包下载链接 还需要部署Tomcat服务器 相关步骤
记得设置tomcat的虚拟目录为项目的名字
总体的目录展示
登录页面
创建完web项目后再web文件下建立我们的登录页面login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script>
//给验证码附上点击的属性,使得可以刷新替换
window.onload=function (){
document.getElementById("img").onclick=function () {
//在地址上加上时间戳能保证每一次的刷新不重复
this.src = "/Texthh/CheckServlet?time" + new Date().getTime();
}
}
</script>
<style>
div{
color: chartreuse;
}
</style>
</head>
<body>
<form action="/Texthh/loginServlet" method="post">
<table align="center">
<tr>
<td><font color="#7fffd4">用户名</font></td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td><font color="#d2691e">密 码</font></td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>验证码</td>
<td><input type="text" name="checkcode"></td>
</tr>
<tr align="center">
<%--验证码的图片来源为CheckServlet--%>
<td colspan="2"><img id="img" src="/Texthh/CheckServlet"></td>
</tr>
<tr align="center">
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
<%--提示信息我们之后再说,大概就是在请求中设值后,再取出--%>
<div align="center"><font size="80"><%=request.getAttribute("check_error")==null?"":request.getAttribute("check_error")%></font></div>
<div align="center"><font size="80" ><%=request.getAttribute("login_error")==null?"":request.getAttribute("login_error")%></font></div>
</body>
</html>
一个简单的小页面就建立好了
之后是成功后的success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1 align="center"><%=request.getSession().getAttribute("user")%>,欢迎您</h1>
</body>
</html>
展示页面就完成了
验证码的生成
我们展示页面中的验证码是随机生成的,我们需要一个servlet来实现它,在src.cn.servlet文件下建立CheckServlet的servlet文件
详细的注释写在代码里面了,应该是比较好懂的,之后还可以在这基础上升级验证码比如旋转,随机颜色都是可以的,这里就做一个比较简单的.
package cn.itcast.servlet;
import javax.imageio.ImageIO;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet(name = "CheckServlet", value = "/CheckServlet")
public class CheckServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置验证码的长度和宽度
int height=50;
int width=100;
//建立img输入流
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//建立画笔对象
Graphics2D g = image.createGraphics();
//设置底部颜色
g.setColor(Color.PINK);
g.fillRect(0,0,width,height);
//设置边框颜色
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1);
//绘画验证码的码,通过设置随机数从中抽取索引来实现随机组合形成验证码
g.setColor(Color.green);
String str="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm123456789";
Random ran=new Random();
//设置字体格式Font中的参数分别为字体格式,字体风格,字体大小
Font f =new Font("楷体",Font.PLAIN,40);
g.setFont(f);
//设置字符串流来存储随机验证码用来以后的验证
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 4; i++) {
int index =ran.nextInt(str.length());
char ch=str.charAt(index);
sb.append(ch);
g.drawString(ch+"",width/5*i-10,height/2+10);
}
String check_session=sb.toString();
//在请求中存储验证码数据
request.getSession().setAttribute("check_session",check_session);
//画几条干扰线
g.setColor(Color.GRAY);
for (int i = 1; i <=5 ; i++) {
int x1= ran.nextInt(width);
int x2=ran.nextInt(width);
int y1=ran.nextInt(height);
int y2=ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//将图片形成,放在response中以备后续使用,在此servlet中就形成了一张图片
//其他的页面就可以通过设置图片路径为当前servlet就可以使用该验证码
ImageIO.write(image,"jpg",response.getOutputStream());
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
数据库连接操作
我们存储用户信息在MySql数据库中,所以我们要连接数据库来查找用户在页面上输入的信息我们数据库是否拥有这样的信息.
首先在MySql中建立denglv的库然后在上面建立User的表
CREATE DATABASE denglv;
USE denglv;
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) UNIQUE NOT NULL,
PASSWORD VARCHAR(20) NOT NULL
);
在表中加入你想要的信息
回到我们idea中,我们在src.cn.itcast.domain下建立和数据库相同的数据生成对应的Getter和Setter方法还有toString方法
package cn.itcast.domain;
import javax.jws.soap.SOAPBinding;
public class User {
//数据库中用户属性
private int id;
private String username;
private String password;
public User(){
}
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int 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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
之后建立src.cn.itcast.util创建JDBCUtils的java类用来创建使用数据库连接池,配置文件用来连接所需要的库,将配置信息存放在druid.properties中
druid.properties配置如下
//注册驱动
driverClassName=com.mysql.cj.jdbc.Driver
//获取数据库连接的库
url=jdbc:mysql:///denglv?serverTimezone=CTT
//MYSQL登录账号和密码
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
JDBCUtils的java类
package cn.itcast.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtils {
//建立数据对象
private static DataSource ds;
//设置静态代码块在创建时就调用
static {
try {
//新建配置文件类
Properties pro = new Properties();
//获取properties文件的输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//DruidDataSourceFactory.createDataSource为获取数据库连接池对象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库的连接对象DataSource
public static DataSource getDataSource(){ return ds; }
//获取连接对象
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
最后就可以建立操作数据库的java类了在src.cn.itcast.Dao下建立UserDao类用来操作数据库
package cn.itcast.Dao;
import cn.itcast.domain.User;
import cn.itcast.util.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* 操作数据库的类
*/
public class UserDao {
//new JdbcTemplate(dataSource)创建连接池对象;
private JdbcTemplate template =new JdbcTemplate(JDBCUtils.getDataSource());
//返回在数据库查询到的User对象
public User login(User loginUser){
try{
String sql="select * from user where username=? and password=?";
//template.queryForObject():查询结果,并将结果封装为Object对象
//queryForObject的参数分别为sql语句,需要封装的类对象,形成的类对象设置的初值设立
User user =template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class)
,loginUser.getUsername(),loginUser.getPassword());
return user;
}catch (DataAccessException e){
e.printStackTrace();
return null;
}
}
}
这样关于数据库的方面就建立好了
登录信息的获取和相应操作
详细说明都在代码里,都有注释.
在验证信息时,我们首要验证的是验证码是否正确,再认证用户名和密码.
package cn.itcast.servlet;
import cn.itcast.Dao.UserDao;
import cn.itcast.domain.User;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
@WebServlet(name = "loginServlet", value = "/loginServlet")
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置页面显示的编码,使得汉字能够显示
request.setCharacterEncoding("utf-8");
//获取用户提交的信息
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkcode = request.getParameter("checkcode");
//先验证验证码正确信息,采用session获取在页面上设置的验证码值
HttpSession session = request.getSession();
//获取提前设置好的键值,读取的值为String类
String check_session = (String) session.getAttribute("check_session");
//读取后删除值,防止页面退后时没有刷新
session.removeAttribute("check_session");
//开始判断验证码是否正确
//正确时
if(check_session!=null&&checkcode.equalsIgnoreCase(check_session)){
//如果输入的用户名和密码在数据库中则正确
Map<String, String[]> map = request.getParameterMap();
User loginUser = new User();
try {
//BeanUtils.populate(Object obj ,Map map): 将map集合中的键值对信息,封装到对应的JavaBean对象中
BeanUtils.populate(loginUser,map);
}
//抓populate的异常
catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
UserDao dao = new UserDao();
User user=dao.login(loginUser);
if(user!=null){
//成功了就保存用户名,用来接下来的跳转
session.setAttribute("user",username);
//重定向转到成功界面
response.sendRedirect(request.getContextPath()+"/success.jsp");
}else{
request.setAttribute("login_error","用户名或密码错误");
//转发,使用前后一个request
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}else{
request.setAttribute("check_error","验证码错误");
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
实现效果
输入正确的:
输入错误的验证码
用户名错误
OK完成,一个小总结吧,和之前的联系也比较大,还是有点难度的