首先声明这个案例是我白嫖的,但是嫖到一半发现代码不全,所以就自己就完善了案例代码!希望后续的小狐伴们不要碰到这个坑!!!
话不多说先看效果图:
这是登录首页:(这个案例其实很简陋,但是为了和你们分享,首页我还是花了一段时间修改的!)
这是登录成功后的界面:
说实话真的很丑!!!但是别急,作为java后台人员我们不追求这个,我们追求的是技术,是可以买到面包和爱情的技术!来看下面的案例代码结构!!
上面是实现怎个案例的所有文件,本来应该按照MVC的框架放包的,但是怕和我一样的小白头晕,所以就简化了!不懂得可以私聊我哦!虽然我也不是很懂!接下来我们一个个分析上面的文件!我们先从视图层开始分享吧!(为什么不是说前端页面呢!因为最近了解到jsp实质还是java,请看下面我随便找到的一篇“高质量博客,博主也是这么认为的呢!)
index.jsp
<%-- Created by IntelliJ IDEA. --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Login</title>
<script>
/*分析:
点击超链接或者图片,需要换一张
1.给超链接和图片绑定单击事件
2.重新设置图片的src属性值
PS:生成的图片先要缓存在本地,每次请求是不会修改,所以验证码图片不会切换;
* 将图片路径后添加时间戳,通过错误的路径来欺骗服务器重新请求
*/
window.onload = function () {
//1.获取图片对象
var img = document.getElementById("checkCode");
//2.绑定图片单击事件
img.onclick = function () {
//加时间戳
var date = new Date().getTime();
//加时间戳,防止浏览器利用缓存
img.src = "/VerificationCode?" + date;
}
//绑定链接点击事件
var ahref = document.getElementById("change");
ahref.onclick = function () {
var date = new Date().getTime();
img.src = "/VerificationCode?" + date;
}
}
</script>
<style>
body {
/* 不重复 */
background: url("img/backgroundimg2.jpg") no-repeat;
/* 背景铺满 */
background-size: 100% auto;
}
div {
color: red;
}
#login-box {
width: 30%;
height: auto;
/* 居中 */
margin: 0 auto;
/* 中央位置 */
margin-top: 15%;
/* 内容居中 */
text-align: center;
background: #00000080;
padding: 20px 50px;
}
#login-box h1 {
color: #fff;
}
#login-box .form .item {
margin-top: 15px;
}
#login-box .form .item i {
font-size: 18px;
color: #fff;
}
/* input border */
#login-box .form .item input {
width: 180px;
font-size: 18px;
border: 0;
border-bottom: 2px solid #fff;
padding: 6px 10px;
background: #ffffff00;
color: #fff;
}
#login-box .button {
margin-top: 15px;
width: 180px;
height: 30px;
font-size: 20px;
font-weight: 700;
color: #fff;
background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
/* background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%); */
border: 0;
border-radius: 15px;
}
</style>
</head>
<body>
<form class="box" action="${pageContext.request.contextPath}/ServletLogin" method="POST">
<div id="login-box">
<h1>Login</h1>
<!-- 输入框 -->
<div class="form">
<div class="item">
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
<input type="text" name="username" placeholder="Username">
</div>
<div class="item">
<i class="fa fa-key" aria-hidden="true"></i>
<input type="password" name="password" placeholder="Password">
</div>
<div class="item">
<i class="fa fa-check-circle-o" aria-hidden="true"></i>
<input type="text" name="checkCode" placeholder="验证码">
</div>
<div><br>
<img id="checkCode" src="${pageContext.request.contextPath}/VerificationCode" alt="checkCode">
<a id="change" href="">看不清?换一张</a>
</div>
</div>
<input type="submit" class="button" value="Login">
</div>
</form>
<div ><%=request.getAttribute("CHECKCODE_Error")==null ? "" : request.getAttribute("CHECKCODE_Error")%></div>
<div><%=request.getAttribute("Login_Error")==null ? "" : request.getAttribute("Login_Error")%></div>
</body>
</html>
![](https://i-blog.csdnimg.cn/blog_migrate/c9f00eabc9baad7e76fd45cb1ab5af84.jpeg)
index视图层背景图
背景图我都给你准备好了,你看我就差拿着你的手敲代码了!
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style type="text/css">
body{
background: url("img/success.jpg") no-repeat;
background-size: 100% auto;
}
</style>
</head>
<body>
<h1>sucesss</h1>
</body>
</html>
这个成功视图层我不想写,就放了一张背景图,关于登录成功背景图似乎有点少,还很丑!真的丑。。。。
![](https://i-blog.csdnimg.cn/blog_migrate/f34d4e0d90a21bbbba52b86bbffe80f7.jpeg)
登陆成功背景图
背景图给你们了,总不要说我小气了吧!还有一个背景图好丑又模糊,我就不给你们了,反正也没什么用!
关于web.xml是没有任何代码配置的!对于新手的话我挺建议走web.xml依赖注入的!但是我这次没用,就下次用吧!
来看servlet代码类: ServletLogin.java
package com.dsw.varification;
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;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
/**
* @author Vere
*/
@WebServlet(name ="ServletLogin",urlPatterns = "/ServletLogin")
public class ServletLogin extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");
String verification = req.getParameter("checkCode");
//2.获取所有请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
User loginUser = new User(username,password);
//4.验证码处理
//4.1获取生成的验证码
HttpSession session = req.getSession();
String validation_code = (String) session.getAttribute("validation_code");
//删除session中存储的验证码,防止重复使用
session.removeAttribute("validation_code");
//4.2判断验证码是否正确
if (validation_code != null && validation_code.equalsIgnoreCase(verification)) {
//忽略大小写,比较字符串,验证码正确
User user = new User(username,password);
//判断用户名和密码是否一致
//5.调用UserDao的login方法
//6.判断user
if ("admin".equals(username)&&"root".equals(password)) {
//登陆成功,存储数据
req.setAttribute("user", user);
session.setAttribute("username", user.getName());
//转发
req.getRequestDispatcher("/successServlet").forward(req, resp);
}else {
//登录失败
req.getRequestDispatcher("/failServlet").forward(req, resp);
}
}else {
//验证码不一致
//存储提示信息到request
req.setAttribute("CHECKCODE_Error", "验证码错误");
//转发到登录页面
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
上课了,看黑板!关于下面这个注释能看懂吗?
@WebServlet(name ="ServletLogin",urlPatterns = "/ServletLogin")
不懂得看下面,能的也要看下面,你以为你很牛逼吗?
属性名 | 类型 | 描述 |
---|---|---|
name | String | 指定Servlet 的 name 属性,等价于 <servlet-name> 。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。 |
value | String[] | 该属性等价于 urlPatterns 属性。两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern> 标签。 |
loadOnStartup | int | 指定 Servlet 的加载顺序,等价于 <load-on-startup> 标签。 |
initParams | WebInitParam[] | 指定一组 Servlet 初始化参数,等价于<init-param> 标签。 |
asyncSupported | boolean | 声明 Servlet 是否支持异步操作模式,等价于<async-supported> 标签。 |
description | String | 该 Servlet 的描述信息,等价于 <description> 标签。 |
displayName | String | 该 Servlet 的显示名,通常配合工具使用,等价于 <display-name> 标签。 |
主要是看name和urlPatterns这两个属性!
在Servlet中,设置了@WebServlet注解,当请求该Servlet时,服务器就会自动读取当中的信息,如果注解@WebServlet("/ServletLogin"),则表示该Servlet默认的请求路径为…/ServletLogin,这里省略了urlPatterns属性名,完整的写法应该是:@WebServlet(urlPatterns = “/ServletLogin”),如果在@WebServlet中需要设置多个属性,必须给属性值加上属性名称,中间用逗号隔开,否则会报错.
若没有设置@WebServlet的name属性,默认值会是Servlet的类完整名称.在servlet3.0以后,web.xml中对Servlet配置,同样可以在@WebServlet注解中配置.
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");
如果你和我一样害怕页面乱码!请乖乖加上这个代码,好吗?不要动不动就说“哎呀!我的怎么乱码了?”呵呵哒!比我还菜,菜鸡......
//2.获取所有请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
你们谁敢说这个看不懂的?我,我看不懂,其实之前我也看不懂,不过我最近学了《葵花宝典》,我豁然开朗,竟然看懂了,
String getParameter(String name):根据参数名称获取参数值
例如例子中index.jsp中from标签传递的参数为“username”和“password”,所以最后在java程序中获得的也是username和password的值
下面是一些还没用到的方法也是关于String[] getParameterValues(String name);//根据参数名称获取参数值的数组 hobby=xx&hobby=game Enumeration getParameterNames();//获取所有请求的参数名称 Map<String,String[]> getParameterMap();//获取所有参数的map集合
本人不建议使用Map<String,String[]> getParameterMap():
然后就是关于session这个知识点了
HttpSession session = req.getSession();
String validation_code = (String) session.getAttribute("validation_code");
//删除session中存储的验证码,防止重复使用
session.removeAttribute("validation_code");
我很好奇你掌握了session?你个菜鸡,拽什么拽,反正我不会,这是我找的笔记:活不多说这是我白嫖的,写的挺好的,喜欢的可以点进去看原文Session原理
Web三大概念:cookie,session,application
Session:记录一系列状态
Session与cookie功能效果相同。Session与Cookie的区别在于Session是记录在服务端的,而Cookie是记录在客户端的。
解释session:当访问服务器否个网页的时候,会在服务器端的内存里开辟一块内存,这块内存就叫做session,而这个内存是跟浏览器关联在一起的。这个浏览器指的是浏览器窗口,或者是浏览器的子窗口,意思就是,只允许当前这个session对应的浏览器访问,就算是在同一个机器上新启的浏览器也是无法访问的。而另外一个浏览器也需要记录session的话,就会再启一个属于自己的session
原理:HTTP协议是非连接性的,取完当前浏览器的内容,然后关闭浏览器后,链接就断开了,而没有任何机制去记录取出后的信息。而当需要访问同一个网站的另外一个页面时(就好比如在第一个页面选择购买的商品后,跳转到第二个页面去进行付款)这个时候取出来的信息,就读不出来了。所以必须要有一种机制让页面知道原理页面的session内容。
session的两种实现方式(也就是传递方式):第一种通过cookies实现。第二种通过URL重写来实现
第一种方式的理解:就是把session的id 放在cookie里面(为什么是使用cookies存放呢,因为cookie有临时的,也有定时的,临时的就是当前浏览器什么时候关掉即消失,也就是说session本来就是当浏览器关闭即消失的,所以可以用临时的cookie存放。保存再cookie里的sessionID一定不会重复,因为是独一无二的。),当允许浏览器使用cookie的时候,session就会依赖于cookies,当浏览器不支持cookie后,就可以通过第二种方式获取session内存中的数据资源。
第二种方式的理解:在客户端不支持cookie的情况下使用。为了以防万一,也可以同时使用。
如果不支持cookie,必须自己编程使用URL重写的方式实现。
如何重写URL:通过response.encodeURL()方法
encodeURL()的两个作用
第一个作用:转码(说明:转中文的编码,或者一些其他特殊的编码。就好比如网页的链接中存在中文字符,就会转换成为一些百分号或者其他的符号代替。)
第二个作用:URL后面加入sessionID,当不支持cookie的时候,可以使用encodeURL()方法,encodeUTL()后面跟上sessionID,这样的话,在禁用cookie的浏览器中同时也可以使用session了。但是需要自己编程,只要链接支持,想用session就必须加上encodeURL()。
Session中的一些常用方法说明
isNew():是否是新的Session,一般在第一次访问的时候出现
getid():拿到session,获取ID
getCreationTime():当前session创建的时间
getLastAccessedTime():最近的一次访问这个session的时间。
getRrquestedSessionid: 跟随上个网页cookies或者URL传过来的session
isRequestedSessionIdFromCookie():是否通过Cookies传过来的
isRequestedSessionIdFromURL():是否通过重写URL传过来的
isRequestedSessionIdValid():是不是有效的sessionID
session有期限:
当一个网站的第一个窗口关掉了,而没有继续接着访问第二个页面,就没有使用到session。那么session会在中断程序后立刻关闭session吗?这个时候session就需要给它保留的时间,当最近一次访问的时候开始计时,每刷新一次重写开始计时。当隔了这么久的时间,没有访问这个session后,对不起,要关闭这个session了。session有过期时间,session什么时候过期,要看配置,
session能干什么:
session就是服务器里面的一块内存,内存里面能放任何东西,只要是名值对就可以了。
session里面的名字永远都是String类型
这个代码还有一个知识点就是
req.getRequestDispatcher("/successServlet").forward(req, resp);
可是我不想讲了,太累了,怕你们嫌弃我啰嗦......
请求转发和重定向的区别
转发:
![](https://i-blog.csdnimg.cn/blog_migrate/30af77c1a80ba00e927f0909cdbb564f.png)
重定向:
![](https://i-blog.csdnimg.cn/blog_migrate/c50ad2139ea0092a3b9af674394b61fa.png)
User.java
package com.dsw.varification;
/**
* @author Vere
*/
public class User {
private String name;
private String password;
public User() {
}
public User(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
这个没有讲头了!下一个
SuccessServlet.java
package com.dsw.varification;
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 java.io.IOException;
/**
* @author Vere
*/
@WebServlet(name = "SuccessServlet",urlPatterns = "/successServlet")
public class SuccessServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//页面设置编码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=UTF-8");
//获取request域中共享的user对象
User user= (User)req.getAttribute("user");
if(user != null) {
//重定向到success.jsp
resp.sendRedirect(req.getContextPath() + "/success.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
下一个
FailServlet.java
package com.dsw.varification;
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 java.io.IOException;
/**
* @author Vere
*/
@WebServlet(name = "FailServlet" ,urlPatterns = "/failServlet")
public class FailServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//页面设置编码
resp.setContentType("text/html;charset=UTF-8");
req.setAttribute("Login_Error", "用户名或密码错误");
//输出
resp.getWriter().write("登陆失败...用户名或密码错误");
req.getRequestDispatcher("/index.jsp").forward(req, resp);
}
}
注意!!!注意!!!这个要考的,快拿出笔记本出来:
VerificationCode.java
package com.dsw.varification;
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.io.OutputStream;
import java.util.Random;
/**
* @author Vere
*/
@WebServlet(name = "VerificationCode",urlPatterns = {"/VerificationCode"})
public class VerificationCode extends HttpServlet {
private static final String codeChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获得验证码集合的长度
int charsLength = codeChars.length();
// 下面3条记录是关闭客户端浏览器的缓冲区
// 这3条语句都可以关闭浏览器的缓冲区,但是由于浏览器的版本不同,对这3条语句的支持也不同
// 因此,为了保险起见,同时使用这3条语句来关闭浏览器的缓冲区
resp.setHeader("ragma", "No-cache");
resp.setHeader("Cache-Control", "no-cache");
resp.setDateHeader("Expires", 0);
// 设置图形验证码的长和宽
int width = 100, height = 30;
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
Random random = new Random();
g.setColor(getRandomColor(180, 250));
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman", Font.ITALIC, height));
g.setColor(getRandomColor(120, 180));
// 用户保存最后随机生成的验证码
StringBuffer validationCode = new StringBuffer();
// 验证码的随机字体
String[] fontNames = { "Times New Roman", "Book antiqua", "Arial" };
// 随机生成4个验证码
for (int i = 0; i < 5; i++) {
// 随机设置当前验证码的字符的字体
g.setFont(new Font(fontNames[random.nextInt(3)], Font.ITALIC,
height));
// 随机获得当前验证码的字符
char codeChar = codeChars.charAt(random.nextInt(charsLength));
validationCode.append(codeChar);
// 随机设置当前验证码字符的颜色
g.setColor(getRandomColor(10, 100));
// 在图形上输出验证码字符,x和y都是随机生成的
g.drawString(String.valueOf(codeChar), 16 * i + random.nextInt(7),
height - random.nextInt(6));
}
// 获得HttpSession对象
HttpSession session = req.getSession();
// 设置session对象5分钟失效
session.setMaxInactiveInterval(5 * 60);
// 将验证码保存在session对象中,key为validation_code
session.setAttribute("validation_code", validationCode.toString());
//关闭Graphics对象
g.dispose();
OutputStream outS = resp.getOutputStream();
ImageIO.write(image, "JPEG", outS);
}
private Color getRandomColor(int minColor, int maxColor) {
Random random = new Random();
if(minColor > 255){
minColor = 255;
}
if(maxColor > 255){
maxColor = 255;
}
//获得r的随机颜色值
int red = minColor+random.nextInt(maxColor-minColor);
int green = minColor + random.nextInt(maxColor-minColor);
int blue = minColor + random.nextInt(maxColor-minColor);
return new Color(red,green,blue);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
好了,讲完了!关于源码