在生活中,我们登陆一个网站的时候经常会碰到需要登陆的界面,而这种界面的通常会有一个输入框,后面跟着一个图片,叫你在输入框中输入图片中的数字和字母,完成登录校验。
页面如下图所示:
而这种验证码是怎么实现的呢?
下面就来写一个小项目,来试一下这个登录界面上加上一个验证码:(本项目使用spring+mybatis+servlet实现)
系统的基本流程就是:用户通过前台表单提交信息给servlet,servlet将前台传过来的信息和后台传过来的信息进行比较并跳转页面,而验证码的信息时存在session中的。
首先,我们建一个表:(实现登录的校验)
然后在eclipse中建立一个动态web工程(包结构如下)
在这里插入图片描述](https://img-blog.csdnimg.cn/20191027164436209.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3NzQ1NjM2,size_16,color_FFFFFF,t_30)
按照如图所示建好包结构:
导包:
我们先建好实体类:Users.java (和数据库中的字段对应好)
package com.zmx.pojo;
public class Users {
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer 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;
}
}
第二步,编写UsersMapper.java接口 (用来查询用户名和密码是否和数据库中匹配,这里采用的是注解方式)
package com.zmx.mapper;
import org.apache.ibatis.annotations.Select;
import com.zmx.pojo.Users;
public interface UsersMapper {
@Select("select * from users where username=#{username} and password=#{password}")
Users selByUsersPwd(Users users);
}
第三步:编写UsersService接口(用来执行业务逻辑)
package com.zmx.service;
import com.zmx.pojo.Users;
public interface UsersService {
Users login(Users users);
}
第四步:编写UsersService接口的实现类UsersServiceImpl(业务逻辑实现类)
package com.zmx.service.impl;
import com.zmx.mapper.UsersMapper;
import com.zmx.pojo.Users;
import com.zmx.service.UsersService;
public class UsersServiceImpl implements UsersService {
private UsersMapper usersMapper;
public UsersMapper getUsersMapper() {
return usersMapper;
}
public void setUsersMapper(UsersMapper usersMapper) {
this.usersMapper = usersMapper;
}
public Users login(Users users) {
return usersMapper.selByUsersPwd(users);
}
}
这里引入了UsersMapper,并实现了get/set方法,目的就是将UsersMapper注入UsersServiceImpl中,从而可以调用UsersMapper中的方法。
第五步:编写Servlet(LoginServlet和ValidCodeServlet)
其中UsersServlet是用来进行数据校验的,而ValidCodeServlet是用来创建一个验证码
首先,我们先来创建ValidCodeServlet:
package com.zmx.servlet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;
@WebServlet("/validcode")
public class ValidCodeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建一张图片
BufferedImage image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_RGB);
//透明玻璃
Graphics2D gra = image.createGraphics();
//设置画笔颜色
gra.setColor(Color.white);
//从哪个坐标开始填充,后两个参数,矩阵区域
gra.fillRect(0, 0, 200, 100);
//产生4个一位数的随机数
List<Integer> randList = new ArrayList<Integer>();
Random rand = new Random();
for(int i=0; i < 4; i++) {
randList.add(rand.nextInt(10));
}
//设置画笔的颜色及样式
gra.setColor(Color.BLACK);
gra.setFont(new Font("宋体",Font.BOLD|Font.ITALIC,40));
Color[] colors = new Color[] {Color.RED,Color.YELLOW,Color.BLUE,Color.GREEN,Color.PINK,Color.GRAY};
//将rand产生的4个随机数画在透明玻璃上
for(int i=0; i < randList.size(); i++) {
gra.setColor(colors[rand.nextInt(colors.length)]);
gra.drawString(randList.get(i)+"", i*40, 70+(rand.nextInt(21)-10));
}
//在验证码图片上随机画上2条线
for(int i = 0; i < 2; i++) {
gra.setColor(colors[rand.nextInt(colors.length)]);
//画横线
gra.drawLine(0, rand.nextInt(101), 200, rand.nextInt(101));
}
//设置图片的格式,并输出到页面上
ServletOutputStream outputStream = resp.getOutputStream();
ImageIO.write(image, "jpg", outputStream);
//将验证码中的4位数字转换成字符保存在session中
HttpSession session = req.getSession();
session.setAttribute("code", ""+randList.get(0)+randList.get(1)+randList.get(2)+randList.get(3));
}
}
LoginServlet:
package com.zmx.servlet;
import java.io.IOException;
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 org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.zmx.pojo.Users;
import com.zmx.service.UsersService;
import com.zmx.service.impl.UsersServiceImpl;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private UsersService usersService;
@Override
public void init() throws ServletException {
ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
usersService = ac.getBean("usersService",UsersServiceImpl.class);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String code = req.getParameter("code");
HttpSession session = req.getSession();
String codeSession = session.getAttribute("code").toString();
if(codeSession.equals(code)) {
String username = req.getParameter("username");
String password = req.getParameter("password");
Users users = new Users();
users.setUsername(username);
users.setPassword(password);
Users user = usersService.login(users);
if(user != null) {
resp.sendRedirect("main.jsp");
} else {
req.setAttribute("error", "用户名或密码不正确");
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
} else {
req.setAttribute("error", "验证码不正确");
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
}
}
spring的核心配置文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="jdbc:mysql:///heima" />
<property name="username" value="root" />
<property name="password" value="123" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zmx.mapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="usersService" class="com.zmx.service.impl.UsersServiceImpl">
<property name="usersMapper" ref="usersMapper"></property>
</bean>
</beans>
log4j.properties
log4j.rootCategory=INFO, CONSOLE ,LOGFILE
log4j.logger.com.zmx.mapper=DEBUG
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{YYYY-MM-dd hh:mm:ss} %m %n
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n
在web.xml中配置:在tomcat启动的时候就去加载spring核心配置文件
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
index.jsp中使用了js代码,而点击看不清的时候向ValidCodeServlet传入一个时间戳的目的是,如果写传的话,因为浏览器的缓存机制,页面不会进行跳转。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function(){
$("a").click(function(){
$("img").attr("src","validcode?date="+new Date());
return false;
})
})
</script>
</head>
<body>
${error }
<form action="login" 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" size="10" name="code" /><img src="validcode" width="80" height="40" /><a href="">看不清</a></td>
</tr>
<tr>
<td><input type="submit" value="登录"></td>
<td><input type="reset" value="重置"></td>
</tr>
</table>
</form>
</body>
</html>
main.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
成功跳转
</body>
</html>
至此,这个小项目就算是完成了,
项目源码附下:
https://pan.baidu.com/s/1A7uxTSIy_6C0Ppq9YXf19g