学习资料黑马java。
Cookie,主要用于用户无登入情况下的身份识别。
package cn.web.Cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
在服务器中的Servlet判断是否有一个名为lastTime的cookie
1. 有:不是第一次访问
1. 响应数据:欢迎回来,您上次访问时间为:2018年6月10日11:50:20
2. 写回Cookie:lastTime=2018年6月10日11:50:01
2. 没有:是第一次访问
1. 响应数据:您好,欢迎您首次访问
2. 写回Cookie:lastTime=2018年6月10日11:50:01
*/
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("test/html;charset=utf-8");
//1.获取cookie
Cookie[] cookies = request.getCookies();
//2.遍历cookie数组
if (cookies != null && cookies.length > 0)
{
//输入iter则弹出快捷键
for (Cookie cookie : cookies) {
//3.获取cookie名称
String name = cookie.getName();
if("lastname".equals(name)) //有该数据,不是第一次访问
{
//获取当前时间,并更新cookie
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
String format = simpleDateFormat.format(date);//把date按格式排好
cookie.setValue(format); //传入cookie中,覆盖掉原来的值
//设置cookie存活时间
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
//响应数据,获取数据value值
String value = cookie.getValue();
response.getWriter().write("欢迎回来,您上次访问的时间是:"+value);
break;
}
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
案例:带验证码的登入界面
文件结构:
核心逻辑简述:
1.通过验证码生成Servlet生成一个验证码,并把正确的文本存在session中。
2.用户输入三个值,账号,密码,和验证码。
3.从request中get到这三个参数,并先用用户的验证码和session中存放的正确结果做对比。
3.1如果不对,则转发一个“验证码不对”的String到前端。
3.2如果正确,则开始判断用户名和密码。
4.把用户名和密码拿出来,通过连接池去数据库中查询。
5.如果找到了,则封装起来用户名和密码。如果没找到,则返回一个Null。
6.进行相应的跳转。
Login.jsp – 登入界面首页
有个小技巧 div中,如果想空的时候不显示,可以用三元运算符:
<div> <%=request.getAttribute("cc_error") == null? "":request.getAttribute("cc_error")%></div>
此外,关于jsp中写java <%= xxxxx %>是不能有分号的,这就是一个单行的表达式。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login</title>
<script>
//当窗口加载完,触发事件。
window.onload = function () {
//当id为img(就是下方的绑定的image)被点击,触发事件
document.getElementById("img").onclick = function () {
var date = new Date(); //加入时间戳 这样每次点击就是一次新访问了checkcode
this.src="/day16/checkCodeServlet?time=" + date.getTime();
}
}
</script>
<style>
div{
color:red;
}
</style>
</head>
<body>
<form action="/day16/loginServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name = "username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name = "password"></td>
</tr>
<tr>
<td>验证码</td>
<td><input type="text" name = "checkcode"></td>
</tr>
<tr>
<td colspan="2"><img id="img" src="/day16/checkCodeServlet"></td>
</tr>
<tr>
<td>用户名</td>
<td><input type="submit" value = "登入"></td>
</tr>
</table>
</form>
<div> <%=request.getAttribute("cc_error") == null? "":request.getAttribute("cc_error")%></div>
<div> <%=request.getAttribute("up_error")==null?"":request.getAttribute("cc_error")%></div>
</body>
</html>
CheckCodeServlet 用来生成img验证码
存储了随机生成的值在session中
package cn.web.Servlet;
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;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 200;
int height = 100;
//1创建一个对象,在内存中是图片(验证码图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics();
g.setColor(Color.pink);
g.fillRect(0,0,width,height); //G.填充框
//2.2画边框
g.setColor(Color.black);
g.drawRect(0,0,width-1,height-1);
//2.3 写验证码
//可能出现的字符库
String ready = "QWERTYUIOPASDFGHJKZXCVBNMqwertyuiopasdfghjkzxcvbnm1234567890";
//生成随机脚标
Random ran = new Random();
g.setColor(Color.blue);
StringBuilder sb = new StringBuilder();
for(int i = 0;i < 4;++i)
{
int index = ran.nextInt(ready.length());
char ch = ready.charAt(index);
sb.append(ch);
g.drawString(ch+"",width / 5 *i,height/2);
}
HttpSession session = request.getSession(); //把这次生成的验证码存入session中,供登入请求比对
session.setAttribute("checkcode",sb.toString());
//2.4 划干扰线
int TheNumeberOfLine = 10;
g.setColor(Color.green);
for(int i = 0;i < TheNumeberOfLine;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);
}
//3.将图片输出到页面上 参数:待输出图片,格式,输出位置
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
success.jsp 成功跳转页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>SuccessLogin</title>
</head>
<body>
<h1> <%=request.getSession().getAttribute("user")%></h1>
</body>
</html>
LoginServlet --登入页面的核心逻辑
要注意以下几点:
1.一般来说都是先判断验证码再判断密码对不对。因为验证码是生成的,不和数据库相连,所以没有数据库开销。
2.转发和重定向的区别。主要是数据位于的域的不同,还有请求次数的不同。
3.经过测试发现,本案例中的两个跳转转发可以转成重定向,但逆向是不可以的。
4.想输出某段文本,可以把这段话起一个总结性的英文key值,这样就可以在jsp前端中很好的体现了。
package cn.web.Servlet;
import cn.web.Dao.UserDao;
import cn.web.Domain.User;
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 java.io.IOException;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置编码
request.setCharacterEncoding("utf-8");
//2.获取参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkcode = request.getParameter("checkcode");
//封装一下username和Password信息为loginUser
User loginUser = new User();
loginUser.setName(username);
loginUser.setPassword(password);
//3.获取生成的验证码 由于图片是一次请求,输入验证码后登入是另一次
// 所以用重定向来实现,即在session中拿数据
HttpSession session = request.getSession();
String checkcode_session = (String) session.getAttribute("checkcode");
//4.先判断验证码是否正确
if (checkcode_session.equalsIgnoreCase(checkcode))
{
//忽略大小写比较字符串
//验证码正确
//判断用户名和密码是否一致
UserDao dao = new UserDao();
User user = dao.Login(loginUser);
if(user == null) //没在数据库中找到,查找失败
{
//存储信息
request.setAttribute("up_error","用户名或密码错误");
//转发到登入页面
request.getRequestDispatcher("/Login.jsp").forward(request,response);
// session.setAttribute("up_error","用户名或密码错误");
// response.sendRedirect(request.getContextPath() + "/Login.jsp");
}
else {
//登入成功
//存储成功的信息
session.setAttribute("user",user); //user对象传输到session域
//重定向 (???为啥这里是重定向,上面却是转发???)(经测试,全是重定向也可以完成功能)
//绝对路径
response.sendRedirect(request.getContextPath() + "/success.jsp");
}
}
else
{
//验证码不一致
//存储信息到request域中供转发使用 (要输出是啥错了)
request.setAttribute("cc_error","验证码错误");
//转发到登入页面
request.getRequestDispatcher("/Login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
剩下的部分基本上和之前那个登入案例十分类似,这里逻辑就不在赘述了。
JDBCUtils工具类
package cn.web.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具类,使用Durid连接池
*/
public class JDBCUtils {
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
//使用ClassLoader加载配置文件获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化连接池对象 一开始报错了,因为lib没有加入到工作空间
//解决方法:右键lib->Add as Library ->module library
ds = DruidDataSourceFactory.createDataSource(pro);
}
catch (IOException e){
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接池对象
*/
public static DataSource getDateSource(){
return ds;
}
/**
* 获取连接connection对象
*/
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
}
Dao类(数据访问对象)
package cn.web.Dao;
import cn.web.Domain.User;
import cn.web.utils.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDao {
//声明JDBCTemplate 对象公用
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDateSource());
public User Login(User loginUser)
{
try {
String sql = "select * from user where username = ? AND password = ?";
//把loginUser输入的名字和密码写成spq去数据库里面找
User user = template.queryForObject(sql,new BeanPropertyRowMapper<>(User.class),
loginUser.getName(),loginUser.getPassword());
return user;
} catch (DataAccessException e) {
e.printStackTrace();
return null; //如果没找到返回一个控制住
}
}
}
自定义用户类
package cn.web.Domain;
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return username;
}
public void setName(String name) {
this.username = name;
}
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 + '\'' +
'}';
}
}