jsp+servlet实现一个简单的登陆功能(无数据库)
登陆功能加入了随机验证码,怎么生成随机验证码的链接点这里
首先给出项目整体图
有两个servlet,一个是LoginServlet (控制登陆,验证输入的验证码和用户名密码正确与否),还有一个是VarifyCodeServlet(生成验证码,响应到客户端)
LoginServlet
package cn.edou.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet {
/**
*
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//检查验证码是否正确
String sessionText = (String) request.getSession().getAttribute("sessionText");
String varifycode = request.getParameter("varifycode");
// request.setAttribute("code",sessionText);
if(varifycode.trim().equals("")){
request.setAttribute("fault", "请输入验证码");
request.getRequestDispatcher("/session2/login.jsp").forward(request, response);
return;
}
else{
if(!varifycode.equalsIgnoreCase(sessionText)){
request.setAttribute("fault", "验证码不正确");
request.getRequestDispatcher("/session2/login.jsp").forward(request, response);
return;
}
}
request.setCharacterEncoding("utf-8");
//获取表单中的账号和密码,如果账号和密码等于admin,admin则登陆成功
String username = request.getParameter("username");
String password = request.getParameter("password");
if("admin".equals(username)&&"admin".equals(password)){
//设置Cookie
Cookie userCookie = new Cookie("name",username);
userCookie.setMaxAge(60*60*24*7); //one week
response.addCookie(userCookie);
//获取session会话,存入账号
HttpSession session = request.getSession();
session = request.getSession();
session.setAttribute("sessionName", username);
//请求转发到成功页面
response.sendRedirect("/day11_3/session2/success.jsp");
}
else{
request.setAttribute("fault", "你的用户名或者密码错误");
request.getRequestDispatcher("/session2/login.jsp").forward(request, response);
}
}
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
doPost(request, response);
}
}
VarifyCodeServlet
package cn.edou.servlet;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.edou.image.VerifyCode;
/**
* Servlet implementation class VarifyCodeServlet
*/
public class VarifyCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response){
//这个功能是把验证码的文本值传到session域,并且返回一张图片
VerifyCode vc = new VerifyCode();
BufferedImage bi = vc.getImage();
String text = vc.getText();
request.getSession().setAttribute("sessionText",text);
try {
vc.outputStream(bi, response.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
然后是显示页面,有两个jsp页面,一个是login.jsp还有一个是success.jsp
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'login.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<!-- 首先得到会话中的错误信息 -->
<%
String fault="";
String sessionFault = (String)request.getAttribute("fault");
if(sessionFault!=null){
fault=sessionFault;
}
%>
<!-- 获取Cookie中的username -->
<%
String name="";
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for(Cookie c:cookies){
if("name".equals(c.getName())){
name=c.getValue();
}
}
}
%>
<body>
<form action = "/day11_3/LoginServlet" method="post">
<!--获取session域中的fault -->
<%--request.getAttribute("code") --%>
<font color="red"><%=fault%></font><br/>
用户名:<input type="text" name="username" size="20" value="<%=name%>"/><br/><br/>
密 码:<input type="password" size="20" name="password"/><br/></br>
验证码:<input type="text" name="varifycode" size="5"/>
<img id="code" src="/day11_3/VarifyCodeServlet" width="120px" height="30px"/>
<a href="/day11_3/session2/login.jsp" onclick="change()">换一张</a>
<br/><br/>
<input type="submit" value="登陆"/>
</form>
<script type="text/javascript">
function change(){
var img = document.getElementById("code");
img.src = "/day11_3/VarifyCodeServlet";
}
</script>
</body>
</html>
success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'success.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<%
String sessionName = (String)session.getAttribute("sessionName");
if(sessionName==null){
request.setAttribute("fault", "你还没有登陆,不能访问");
request.getRequestDispatcher("/session2/login.jsp").forward(request, response);
return;
}
%>
<body>
<h1>欢迎<%=sessionName %>,你已经登陆成功</h1>
</body>
</html>
最后给出VarifyCodeServlet引用的一个VarifyCode.java源代码,其实这个代码在本文最上面给出了,但是这个与哪个有点不同,在那个基础上改进了一下方法
VarifyCode.java
package cn.edou.image;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
public class VerifyCode {
//定义一些变量
private int x = 240;
private int y = 80;
private int fontSize = 70;
private StringBuilder sb = new StringBuilder();
private String text;
private Random random = new Random();
private Color bgColor = new Color(255,255,255);
private String[] fontsName = {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"};
private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ";
//获取随机的字体
private String getFont(){
int index = random.nextInt(fontsName.length);
String fontName = fontsName[index];
return fontName;
}
//获取字母
private String getChar(){
int index = random.nextInt(codes.length());
String ch = codes.charAt(index)+"";
return ch;
}
//获取颜色
private Color getColor(){
int red = random.nextInt(150);
int green = random.nextInt(150);
int blue = random.nextInt(150);
return new Color(red,green,blue);
}
//设置缓冲区
private BufferedImage getBufferedImage(){
BufferedImage bi = new BufferedImage(x,y,BufferedImage.TYPE_INT_RGB);
Graphics2D pen = (Graphics2D)bi.getGraphics();
pen.setColor(this.bgColor);
pen.fillRect(0,0,x,y);
return bi;
}
//给缓冲区添加字符串,添加干扰线
private BufferedImage addCharAndLine(){
BufferedImage bi = getBufferedImage();
Graphics2D pen = (Graphics2D)bi.getGraphics();
StringBuilder sb = new StringBuilder();
for(int i=0;i<4;i++){
String font = getFont();
int style = random.nextInt(4);
pen.setColor(getColor());
pen.setFont(new Font(font,style,fontSize));
String s = getChar();
sb.append(s);
pen.drawString(s, 10+i*50, 65);
}
this.text=sb.toString();
int lineNumber = 3;
pen.setColor(Color.BLUE);
// pen.setStroke(new BasicStroke(1.5F));
pen.setStroke(new BasicStroke(1.5F,BasicStroke.CAP_ROUND,BasicStroke.JOIN_MITER));
for(int i=0;i<lineNumber;i++){
int x1 = random.nextInt(x);
int y1 = random.nextInt(y);
int x2 = random.nextInt(x);
int y2 = random.nextInt(y);
pen.drawLine(x1, y1, x2, y2);
}
return bi;
}
//获取验证码的值
public String getText(){
return this.text;
}
// public String getText(BufferedImage bi){
// return sb.toString();
// }
//获取一张验证码图片
public BufferedImage getImage(){
return addCharAndLine();
}
//输出图片
public void outputImage(BufferedImage bi,String imageName){
String path = "D:\\JavaWebExercise\\day12\\"+imageName+".jpg";
try {
ImageIO.write(bi, "JPEG", new FileOutputStream(path));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//输出图片流
public void outputStream(BufferedImage bi,OutputStream os){
try {
ImageIO.write(bi, "JPEG", os);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我自己在敲代码的时候出现的几个问题,在这总结一下
- 路径的问题,重定向以及超链接中的目标路径都是带项目名的,也就是绝对路径,请求转发的路径若是相对路径,以/开头不用给出项目名。给出例子:超链接
<a href="/day11_3/session2/login.jsp" onclick="change()">换一张</a>img标签<img id="code" src="/day11_3/VarifyCodeServlet" width="120px" height="30px"/>重定向response.sendRedirect("/day11_3/session2/success.jsp");请求转发request.getRequestDispatcher("/session2/login.jsp").forward(request, response); - 参数存放的域对象是哪个?这里我们设置的参数种类有验证码的参数,以及错误信息的参数,错误信息的参数是在请求时候进行验证的,所以把它放在了request域对象,而在请求login.jsp的时候其实发出了两个请求,一个是请求login的页面,还有一个是请求VarifyCodeServlet,我们为了验证输入验证码的正确与否,需要把正确的验证码存放起来,如果把验证码存放在request域,那么在login页面点登陆,又是一个request,这时候存放在request域的验证码文本已经请求不到了,所以我们把验证码文本存放在了session域。
- 在login.jsp页面里面,其中
<a href="/day11_3/session2/login.jsp" onclick="change()">换一张</a>这里引用了js事件,change函数如下function change(){ var img = document.getElementById("code"); img.src = "/day11_3/VarifyCodeServlet"; }解释一下,用dom对象获得了id为code的节点(img节点),然后将img结点的src属性改为/day11_3/VarifyCodeServlet,其实这的作用就是在你每次点换一张的时候,可以重新调用VarifyCodeServlet,然后给出老师的代码<a href="javascript:_change()">换一张</a>老师这里用的是javascript伪协议
function _change() {
/*
1. 得到img元素
2. 修改其src为/day11_3/VerifyCodeServlet
*/
var imgEle = document.getElementById("img");
imgEle.src = "/day11_3/VerifyCodeServlet?a=" + new Date().getTime();
}