【电信计费系统项目实战】基础篇---登录界面实现

这一篇很简单,登录界面无非就是账号密码框再加上一个验证码,这里我们主要了解生成验证码及验证的基本原理,可以参考我之前写的一篇ajax注册页面异步验证
这里写图片描述
登录界面代码:

<%@page pageEncoding="utf-8"%>
<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>达内-NetCTOSS</title>
        <link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
        <link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" /> 
         <script type="text/javascript" language="javascript">
             function change(imgObj) {
                 imgObj.src = "createImage?date=" + new Date().getTime();
             }
         </script>
    </head>
    <body class="index">
        <div class="login_box">

            <!-- method="post",保证中文不乱码 -->
            <form action="login" method="post">
                <table>
                    <tr>
                        <td class="login_info">账号:</td>
                        <td colspan="2"><input name="adminCode" type="text" value="<s:property value="adminCode"/>" class="width150" /></td>
                        <td class="login_error_info"><span class="required">30长度的字母、数字和下划线</span></td>
                    </tr>
                    <tr>
                        <td class="login_info">密码:</td>
                        <td colspan="2"><input name="password" type="password" value="<s:property value="password"/>" class="width150" /></td>
                        <td><span class="required">30长度的字母、数字和下划线</span></td>
                    </tr>
                    <tr>
                        <td class="login_info">验证码:</td>
                        <td class="width70"><input name="imageCode" type="text" class="width70" /></td>
                        <td><img src="createImage" onclick="change(this)" alt="验证码" title="点击更换" /></td>  
                        <td><span class="required"></span></td>              
                    </tr>            
                    <tr>
                        <td></td>
                        <td class="login_button" colspan="2">
                            <a href="javascript:document.forms[0].submit();"><img src="../images/login_btn.png" /></a>
                        </td>    
                        <td><span class="required"><s:property value="errorMsg"/></span></td>                
                    </tr>
                </table>
            </form>
        </div>
    </body>
</html>

代码解释:验证码图片那一行代码,通过点击超链接的方式来变换验证码图片上的验证码:

function change(imgObj) {
                 imgObj.src = "createImage?date=" + new Date().getTime();
             }

显而易见,通过createImage请求来变换验证码的,接着看到底是哪个Action用来生成验证码的:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>

    <!-- 登录模块 -->
    <package name="login" namespace="/login"
        extends="struts-default">
        <!-- 
            跳转到登录页面Action。
            该Action不需要写业务代码,class可以省略。
            当class省略时,Struts2会自动调用ActionSupport,
            这个类中有默认的方法execute,返回success。
        -->
        <action name="toLogin">
            <result name="success">
                /WEB-INF/main/login.jsp
            </result>
        </action>
        <!-- 登录校验Action -->
        <action name="login" 
            class="com.tarena.action.login.LoginAction">
            <!-- 成功时跳转到首页 -->
            <result name="success">
                /WEB-INF/main/index.jsp
            </result>
            <!-- 失败时回登录页 -->
            <result name="fail">
                /WEB-INF/main/login.jsp
            </result>
        </action>
        <!-- 生成验证码Action -->
        <action name="createImage"
            class="com.tarena.action.login.CreateImageAction">
            <result name="success" type="stream">
                <!-- 
                    param是参数注入的标签,用于
                    给组件的属性注入值。这里相当于是给
                    stream类型的Result的inputName属性
                    设置值,其值为"imageStream".
                 -->
                <param name="inputName">
                    imageStream
                </param>
            </result>
        </action>
    </package>

</struts>

以上是登录模块的struts配置,我们可以看到CreateImageAction类生成验证码操作

<!-- 生成验证码Action -->
        <action name="createImage"
            class="com.tarena.action.login.CreateImageAction">
            <result name="success" type="stream">
                <!-- 
                    param是参数注入的标签,用于
                    给组件的属性注入值。这里相当于是给
                    stream类型的Result的inputName属性
                    设置值,其值为"imageStream".
                 -->
                <param name="inputName">
                    imageStream
                </param>
            </result>
        </action>

CreateImageAction完成的功能步骤:

  1. 生成图片
  2. 读取出验证码,并放入session
  3. 3.读取出图片
package com.tarena.action.login;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import com.tarena.action.BaseAction;
import com.tarena.util.ImageUtil;

public class CreateImageAction extends BaseAction {

    //output
    private InputStream imageStream;

    public String execute() {
        //1.生成图片
        Map<String, BufferedImage> map = 
            ImageUtil.createImage();
        //2.读取出验证码,并放入session
        String code = map.keySet().iterator().next();
        session.put("imageCode", code);
        //3.读取出图片
        BufferedImage image = map.get(code);
        try {
            imageStream = ImageUtil.getInputStream(image);
        } catch (IOException e) {
            e.printStackTrace();
            return "error";
        }

        return "success";
    }

    public InputStream getImageStream() {
        return imageStream;
    }

    public void setImageStream(InputStream imageStream) {
        this.imageStream = imageStream;
    }

}

(map的keySet()方法返回值是Map中key值的集合)
由此可以看出,具体完成验证码的是工具类ImageUtil,只不过CreateImageAction 调用它而已,它完成的功能有:

 1. 用于生成一个图片,图片中带有验证码。
 2. Map的key存的是验证码字符串
 3. Map的value存的是图片
此处灵活的运用map这个容器,非常方便的存取值。ImageUtil里都是java里最基本的知识,没什么好讲的,看看就行了:
package com.tarena.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public final class ImageUtil {

    private static final char[] chars = { '0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' };
    private static final int SIZE = 4;
    private static final int LINES = 5;
    private static final int WIDTH = 80;
    private static final int HEIGHT = 35;
    private static final int FONT_SIZE = 30;

    /**
     * 用于生成一个图片,图片中带有验证码。
     * Map的key存的是验证码字符串,
     * Map的value存的是图片。
     */
    public static Map<String, BufferedImage> createImage() {
        StringBuffer sb = new StringBuffer();
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT,
                BufferedImage.TYPE_INT_RGB);
        Graphics graphic = image.getGraphics();
        graphic.setColor(Color.LIGHT_GRAY);
        graphic.fillRect(0, 0, WIDTH, HEIGHT);
        Random ran = new Random();
        // 画随机字符
        for (int i = 1; i <= SIZE; i++) {
            int r = ran.nextInt(chars.length);
            graphic.setColor(getRandomColor());
            graphic.setFont(new Font(null, Font.BOLD + Font.ITALIC, FONT_SIZE));
            graphic.drawString(chars[r] + "", (i - 1) * WIDTH / SIZE,
                    2*HEIGHT/3);
            sb.append(chars[r]);// 将字符保存,存入Session
        }
        // 画干扰线
        for (int i = 1; i <= LINES; i++) {
            graphic.setColor(getRandomColor());
            graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT),
                    ran.nextInt(WIDTH), ran.nextInt(HEIGHT));
        }
        Map<String, BufferedImage> map = new HashMap<String, BufferedImage>();
        map.put(sb.toString(), image);
        return map;
    }

    public static Color getRandomColor() {
        Random ran = new Random();
        Color color = new Color(ran.nextInt(256), ran.nextInt(256),
                ran.nextInt(256));
        return color;
    }

    public static InputStream getInputStream(BufferedImage image)
            throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
        encoder.encode(image);
        byte[] imageBts = bos.toByteArray();
        InputStream in = new ByteArrayInputStream(imageBts);
        return in;
    }

}

然后就是登陆验证了,也没什么好讲的(代码如下),其他内容后面的章节会讲到。

package com.tarena.action.login;

import org.omg.CORBA.Request;

import com.tarena.action.BaseAction;
import com.tarena.dao.DAOException;
import com.tarena.dao.DAOFactory;
import com.tarena.dao.login.ILoginDAO;
import com.tarena.entity.Admin;

public class LoginAction extends BaseAction {

    //input
    private String adminCode;
    private String password;
    private String imageCode;
    //output
    private String errorMsg;

    public String execute() {
        //1.校验验证码
        String code = (String) session.get("imageCode");
        if(code == null ||
                !code.equalsIgnoreCase(imageCode)) {
            //验证码不匹配,校验失败
            errorMsg = "验证码错误!";
            return "fail";
        }

        //2.根据账号查询管理员
        ILoginDAO dao = DAOFactory.getLoginDAO();
        Admin admin = null;
        try {
            admin = dao.findByCode(adminCode);
        } catch (DAOException e) {
            e.printStackTrace();
            errorMsg = "查询管理员报错,请联系系统管理员!";
            return "fail"; //异常,返回登录页面
        }

        if(admin == null) {
            //3.如果没有对应的管理员,登录失败,账号不存在
            errorMsg = "账号不存在!";
            return "fail"; //验证失败,回登录页面
        } else {
            //4.如果有对应管理员,看密码,若密码错误,登录失败
            String pwd = admin.getPassword();
            if(!pwd.equals(password)) {
                errorMsg = "密码错误!";
                return "fail"; //验证失败,回登录页面
            }
        }
        //4.登录成功后,将登录信息记录到Session
        session.put("admin", adminCode);
        return "success"; //成功,去index.jsp
    }

    public String getAdminCode() {
        return adminCode;
    }

    public void setAdminCode(String adminCode) {
        this.adminCode = adminCode;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getImageCode() {
        return imageCode;
    }

    public void setImageCode(String imageCode) {
        this.imageCode = imageCode;
    }

}

很多网站都会加个验证码,比如百度贴吧啥的,验证码一般是防止有人利用机器人自动批量注册、对特定的注册用户用特定程序暴力破解方式进行不断的登陆、灌水。因为验证码是一个混合了数字或符号的图片,人眼看起来都费劲,机器识别起来就更困难。map可以很好的存取字符串和图片来实现验证码,所以这里主要了解map的用法就行啦!

  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
智能停车场车牌识别计费系统是基于Python3开发的一种应用程序。它利用车牌识别技术,能够自动识别进入停车场的车辆的车牌号码,并根据停车时长进行计费系统的主要功能包括车牌号码识别、进入/离开时间记录、计费和支付等。首先,通过摄像头获取车辆的图像,并将图像传送到车牌识别模块进行处理。通过使用Python中的图像处理库和机器学习算法,系统能够准确地识别车牌号码。 一旦车辆的车牌号码被识别成功,系统将自动记录该车辆的进入时间。当车辆离开停车场时,系统再次识别车辆的车牌号码,并记录离开时间。通过计算进入和离开时间之间的差值,系统可以自动计算出停车时长。 系统支持按照不同的计费策略进行计费,例如按分钟、小时或者一定时间段内的固定费用。系统会根据计费策略和停车时长计算出最终的停车费用,并提供给用户支付的选项。 该系统的开发主要使用Python3编程语言,结合了一些常用的图像处理和机器学习库,如OpenCV、TensorFlow等。此外,还需要使用数据库来存储识别到的车辆信息和计费记录。 总结来说,Python3开发的智能停车场车牌识别计费系统能够提高停车场管理效率,减少人工操作,提供便捷的支付方式,并能适应不同的计费策略。这个系统有着广阔的应用前景,可以在现实中的停车场中推广使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值