CRM第六天:客户拜访管理,权限配置,验证码实现
目录
1.CRM客户关系管理系统:客户拜访记录
1.1需求概述
一个系统的用户(公司业务员),业务员需要对客户进行拜访,对拜访的过程进行记录。业务员(用户)和客户(客户)之间关系(需要具体业务具体分析:一对多—公司产品比较单一,只允许一个业务员对应多个客户。多对多—大公司有不同的产品,不同产品下有不同业务员都可以接触到同一个客户,一个客户可以对应多个业务员)。大部分情况创建成多对多。
- 多对多建表原则:
- 创建中间表,中间表中至少两个字段分别作为外键指向多对多双方的主键。
1.2准备工作
1.2.1创建表
CREATE TABLE `sale_visit` (
`visit_id` varchar(32) NOT NULL,
`visit_cust_id` bigint(32) DEFAULT NULL COMMENT '客户id',
`visit_user_id` bigint(32) DEFAULT NULL COMMENT '负责人id',
`visit_time` datetime DEFAULT NULL COMMENT '拜访时间',
`visit_addr` varchar(128) DEFAULT NULL COMMENT '拜访地点',
`visit_detail` varchar(256) DEFAULT NULL COMMENT '拜访详情',
`visit_nexttime` date DEFAULT NULL COMMENT '下次拜访时间',
PRIMARY KEY (`visit_id`),
KEY `FK_sale_visit_cust_id` (`visit_cust_id`),
KEY `FK_sale_visit_user_id` (`visit_user_id`),
CONSTRAINT `FK_sale_visit_cust_id` FOREIGN KEY (`visit_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_sale_visit_user_id` FOREIGN KEY (`visit_user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1.2.2创建实体和映射
实体:
package com.albertyy.crm.entity;
import java.sql.Date;
import java.sql.Timestamp;
/**
* 项目名称:CRM 类名称:SaleVisit 类描述: 客户拜访实体类 创建人:yangyangyang
* 创建时间:2019年1月1日 下午4:32:53 修改人:yangyangyang 修改时间:2019年1月1日 下午4:32:53
* 修改备注: @version
*/
public class SaleVisit {
private String visit_id;
private Timestamp visit_time;
private String visit_addr;
private String visit_detail;
private Date visit_nexttime;
// 拜访记录关联的客户对象
private Customer customer;
// 拜访记录关联的用户对象
private User user;
public String getVisit_id() {
return visit_id;
}
public void setVisit_id(String visit_id) {
this.visit_id = visit_id;
}
public Timestamp getVisit_time() {
return visit_time;
}
public void setVisit_time(Timestamp visit_time) {
this.visit_time = visit_time;
}
public String getVisit_addr() {
return visit_addr;
}
public void setVisit_addr(String visit_addr) {
this.visit_addr = visit_addr;
}
public String getVisit_detail() {
return visit_detail;
}
public void setVisit_detail(String visit_detail) {
this.visit_detail = visit_detail;
}
public Date getVisit_nexttime() {
return visit_nexttime;
}
public void setVisit_nexttime(Date visit_nexttime) {
this.visit_nexttime = visit_nexttime;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
映射:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.albertyy.crm.entity.SaleVisit" table="sale_visit">
<id name="visit_id" column="visit_id">
<generator class="uuid"/>
</id>
<property name="visit_time" column="visit_time"/>
<property name="visit_addr" column="visit_addr"/>
<property name="visit_detail" column="visit_detail"/>
<property name="visit_nexttime" column="visit_nexttime"/>
<!-- 配置与客户的关联关系 -->
<many-to-one name="customer" class="com.albertyy.crm.entity.Customer" column="visit_cust_id" />
<!-- 配置与用户的关联关系 -->
<many-to-one name="user" class="com.albertyy.crm.entity.User" column="visit_user_id" />
</class>
</hibernate-mapping>
1.2.3创建相关类,并交给Spring管理
<!-- ======配置客户拜访的相关类======= -->
<!-- 配置Action -->
<bean id="saleVisitAction" class="com.albertyy.crm.web.action.SaleVisitAction" scope="prototype">
<property name="saleVisitService" ref="saleVisitService"/>
<property name="customerService" ref="customerService"/>
<property name="userService" ref="userService"/>
</bean>
<!-- 配置Service -->
<bean id="saleVisitService" class="com.albertyy.crm.serviceImpl.SaleVisitServiceImpl">
<property name="saleVisitDao" ref="saleVisitDao"/>
</bean>
<!-- 配置DAO -->
<bean id="saleVisitDao" class="com.albertyy.crm.daoImpl.SaleVisitDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
1.3客户拜访记录列表显示
1.3.1修改left.jsp的提交路径
<h3>客户拜访管理</h3>
<ul>
<li><a
href="${pageContext.request.contextPath }/saleVisit_saveUI.action">新增客户拜访</a></li>
<li><a
href="${pageContext.request.contextPath }/saleVisit_findAll.action">客户拜访列表</a></li>
</ul>
1.3.2编写action
// 分页查询客户拜访记录的方法
public String findAll() {
// 创建离线条件查询对象
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(SaleVisit.class);
// 设置条件
PageBean<SaleVisit> pageBean = saleVisitService.findByPage(detachedCriteria, page, pageSize);
ActionContext.getContext().getValueStack().push(pageBean);
return "findAll";
}
1.3.3编写service
//客户拜访分页查询业务层方法
@Override
public PageBean<SaleVisit> findByPage(DetachedCriteria detachedCriteria, Integer page, Integer pageSize) {
PageBean<SaleVisit> pageBean=new PageBean<SaleVisit>();
pageBean.setPage(page);
pageBean.setPageSize(pageSize);
int totalCount=saleVisitDao.findCount(detachedCriteria);
pageBean.setTotalCount(totalCount);
double tc=totalCount;
Double num=Math.ceil(tc/pageSize);
pageBean.setTotalPage(num.intValue());
Integer begin=(page-1)*pageSize;
List<SaleVisit> list=saleVisitDao.findByPage(detachedCriteria, begin, pageSize);
pageBean.setList(list);
return pageBean;
}
1.3.4编写显示页面
<div class="main" style="overflow-y: auto">
<div class="container">
<form name="customerForm"
action="${pageContext.request.contextPath }/saleVisit_findAll.action"
method="post">
<div id="search_bar" class="mt10">
<div class="box">
<div class="box_border">
<div class="box_top">
<b class="pl15">搜索</b>
</div>
<div class="box_center pt10 pb10">
<table class="form_table" cellspacing="0" cellpadding="0"
border="0">
<tbody>
<tr>
<td>拜访时间从:</td>
<td><input type="date" name="visit_time"
value="<s:date name="visit_time" format="yyyy-MM-dd"/>"
class="input-text lh25" size="10"></td>
<td>到:</td>
<td><input type="date" name="visit_endtime"
value="<s:date name="visit_endtime" format="yyyy-MM-dd"/>"
class="input-text lh25" size="10"></td>
<td><input type="submit" name="button"
class="btn btn82 btn_search" value="查询"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div id="table" class="mt10">
<div class="box span10 oh">
<table width="100%" border="0" cellpadding="0" cellspacing="0"
class="list_table">
<tr>
<th width="100">客户名称</th>
<th width="100">负责人名称</th>
<th width="100">拜访时间</th>
<th width="100">拜访地点</th>
<th width="100">拜访详情</th>
<th width="100">下次拜访时间</th>
<th width="150">操作</th>
</tr>
<s:iterator value="list">
<tr class="tr">
<td><s:property value="customer.cust_name" /></td>
<td><s:property value="user.user_name" /></td>
<td><s:date name="visit_time" format="yyyy-MM-dd"/></td>
<td><s:property value="visit_addr" /></td>
<td><div style="height: 30px; overflow-y: auto;">
<s:property value="visit_detail" />
</div></td>
<td><s:date name="visit_nexttime" format="yyyy-MM-dd"/></td>
<td><input type="button" name="button"
class="btn btn82 btn_add" id="modifyBtn"
onclick="toUpdate('<s:property value="lkm_id"/>')" value="修改">
<input type="button" name="button" class="btn btn82 btn_del"
onclick="toDelete('<s:property value="lkm_id"/>')" value="删除"></td>
</tr>
</s:iterator>
</table>
<div class="page mt10">
<div class="pagination">
<ul>
<li class="disabled"><span> 共<s:property
value="totalCount" />条记录, 共 <s:property value="totalPage" />页
</span></li>
<li><span> 每页显示记录数: <select name="pageSize"
onchange="to_page()">
<option value="5" <s:if test="pageSize==5">selected</s:if>>5条</option>
<option value="10" <s:if test="pageSize==10">selected</s:if>>10条</option>
<option value="20" <s:if test="pageSize==20">selected</s:if>>20条</option>
</select>
</span></li>
<s:if test="page!=1">
<li><a href="javascript:to_page(1)">首页</a></li>
<li><a
href="javascript:to_page(<s:property value="page-1" />)">上一页</a></li>
</s:if>
<s:iterator var="i" begin="1" end="totalPage">
<s:if test="#i==page">
<li class="active"><span><s:property value="#i" />
</span></li>
</s:if>
<s:else>
<li><a
href="javascript:to_page(<s:property value="#i" />)"><s:property
value="#i" /></a></li>
</s:else>
</s:iterator>
<s:if test="page!=totalPage">
<li><a
href="javascript:to_page(<s:property value="page+1" />)">下一页</a></li>
<li><a
href="javascript:to_page(<s:property value="totalPage" />)">末页</a></li>
</s:if>
<li>到第 <input class="input-text lh25" type="text"
id="page" name="page" size="2" height="10px" />页 <input
class="ext_btn" type="button" value="GO" onclick="to_page()" />
</li>
</ul>
</div>
</div>
</form>
</div>
</div>
1.4客户拜访记录列表显示
1.4.1编写action
// 跳转到添加页面的方法
public String saveUI() {
// 查询客户和负责人
List<Customer> customerlist = customerService.findAll();
List<User> userlist = userService.findAll();
ActionContext.getContext().getValueStack().set("customerlist", customerlist);
ActionContext.getContext().getValueStack().set("userlist", userlist);
return "saveUI";
}
// 保存拜访记录
public String save() {
saleVisitService.save(saleVisit);
// 跳转到列表页面
findAll();
return "saveSuccess";
}
配置action:
<!-- 客户拜访Action -->
<action name="saleVisit_*" class="saleVisitAction" method="{1}">
<result name="findAll">/salevisit/list.jsp</result>
<result name="saveUI">/salevisit/add.jsp</result>
<result name="saveSuccess">/salevisit/list.jsp</result>
</action>
1.4.2编写service
//保存客户拜访记录
@Override
public void save(SaleVisit saleVisit) {
saleVisitDao.save(saleVisit);
}
1.4.3编写保存页面
<div class="main" style="overflow-y: auto">
<div class="container">
<div class="main_top">
<div id="forms" class="mt10">
<div class="box">
<div class="box_border">
<div class="box_top">
<b class="pl15">新增客户拜访</b>
</div>
<div class="box_center">
<form
action="${pageContext.request.contextPath }/saleVisit_save.action"
method="post" class="jqtransform">
<table class="form_table pt15 pb15" width="100%" border="0"
cellpadding="0" cellspacing="0">
<tr>
<td class="td_right">客户名称:</td>
<td class=""><span class="fl">
<div class="select_border">
<div class="select_containers ">
<select name="customer.cust_id" id="cust_source"
class="select">
<option value="">-请选择-</option>
<s:iterator value="customerlist">
<option value='<s:property value="cust_id"/>'><s:property
value="cust_name" /></option>
</s:iterator>
</select>
</div>
</div>
</span></td>
</tr>
<tr>
<td class="td_right">负责人名称:</td>
<td class=""><span class="fl">
<div class="select_border">
<div class="select_containers ">
<select name="user.user_id" id="cust_source"
class="select">
<option value="">-请选择-</option>
<s:iterator value="userlist">
<option value='<s:property value="user_id"/>'><s:property
value="user_name" /></option>
</s:iterator>
</select>
</div>
</div>
</span></td>
</tr>
<tr>
<td class="td_right">拜访时间:</td>
<td class=""><input type="date" name="visit_time"
class="input-text lh30" ></td>
</tr>
<tr>
<td class="td_right">拜访地点:</td>
<td class=""><input type="text" name="visit_addr"
class="input-text lh30" ></td>
</tr>
<tr>
<td class="td_right">拜访详情:</td>
<td class=""><textarea name="visit_detail" id="" cols="30" rows="10"
class="textarea" style="width: 362px; height: 93px;"></textarea>
</td>
</tr>
<tr>
<td class="td_right">下次拜访时间:</td>
<td class=""><input type="date" name="visit_nexttime"
class="input-text lh30" ></td>
</tr>
<tr>
<td class="td_right"> </td>
<td class=""><input type="submit" name="button"
class="btn btn82 btn_save2" value="保存"> <input
type="reset" name="button" class="btn btn82 btn_res"
value="重置"></td>
</tr>
</table>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
2.权限管理
2.1编写一个类继承拦截器类
package com.albertyy.crm.web.intercept;
import org.apache.struts2.ServletActionContext;
import com.albertyy.crm.entity.User;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
/*
* 拦截器类
*/
public class PrivilegeInterceptor extends MethodFilterInterceptor {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//判断session中是否有登陆用户
User loginUser=(User) ServletActionContext.getRequest().getSession().getAttribute("loginuser");
if(loginUser==null){
//跳转到登陆页面
ActionSupport actionSupport=(ActionSupport) invocation.getAction();
actionSupport.addActionError("您还没有登陆,请登陆!");
return actionSupport.LOGIN;
}else{
//已经登陆
return invocation.invoke();
}
}
}
2.2配置拦截器
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 配置Struts2的常量 -->
<constant name="struts.action.extension" value="action" />
<!-- 配置Struts2中一个表单中上传文件总大小10M -->
<constant name="struts.multipart.maxSize" value="10485760"></constant>
<!-- 配置Action -->
<package name="crm" extends="struts-default" namespace="/">
<!-- 定义拦截器 -->
<interceptors>
<interceptor name="privilegeInterceptor"
class="com.albertyy.crm.web.intercept.PrivilegeInterceptor"></interceptor>
</interceptors>
<!-- 全局结果 -->
<global-results>
<result name="login">/login.jsp</result>
</global-results>
<!-- 用户 -->
<action name="user_*" class="userAction" method="{1}">
<result name="exitSuccess">/login.jsp</result>
<result name="success" type="redirect">/index.jsp</result>
<result name="register" >/register.jsp</result>
</action>
<!-- 客户管理Action -->
<action name="customer_*" class="customerAction" method="{1}">
<result name="saveUI">/customer/add.jsp</result>
<result name="findAll">/customer/list.jsp</result>
<result name="deleteSuccess" type="redirect">/customer_findAll.action
</result>
<result name="updateSuccess" type="redirect">/customer_findAll.action
</result>
<result name="input">/customer/add.jsp</result>
<interceptor-ref name="privilegeInterceptor"></interceptor-ref>
<!-- 配置文件上传拦截器 -->
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">5242880</param>
<param name="fileUpload.allowedExtensions">.jpg,.bmp,.png,.txt,.gif</param>
</interceptor-ref>
</action>
<!-- 字典管理Action -->
<action name="baseDict_*" class="baseDictAction" method="{1}">
<interceptor-ref name="privilegeInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<!-- 联系人管理Action -->
<action name="linkMan_*" class="linkManAction" method="{1}">
<result name="findAll">/linkman/list.jsp</result>
<result name="saveUI">/linkman/add.jsp</result>
<result name="saveSuccess">/linkman/list.jsp</result>
<result name="deleteSuccess">/linkman/list.jsp</result>
<result name="updateSuccess" type="redirect">/linkMan_findAll.action
</result>
<interceptor-ref name="privilegeInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<!-- 客户拜访Action -->
<action name="saleVisit_*" class="saleVisitAction" method="{1}">
<result name="findAll">/salevisit/list.jsp</result>
<result name="saveUI">/salevisit/add.jsp</result>
<result name="saveSuccess">/salevisit/list.jsp</result>
<interceptor-ref name="privilegeInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
</struts>
3验证码
3.1编写工具类
编写工具类SecurityCode:
package com.albertyy.crm.utils;
import java.util.Arrays;
/**
*
* 项目名称:CRM
* 类名称:SecurityCode
* 类描述: 生成验证码字符串
* 创建人:yangyangyang
* 创建时间:2019年1月4日 下午5:07:27
* 修改人:yangyangyang
* 修改时间:2019年1月4日 下午5:07:27
* 修改备注:
* @version
*
*/
public class SecurityCode {
/**
* 验证码难度级别,Simple只包含数字,Medium包含数字和小写英文,Hard包含数字和大小写英文
*/
public enum SecurityCodeLevel {Simple,Medium,Hard};
/**
* 产生默认验证码,4位中等难度
* @return String 验证码
*/
public static String getSecurityCode(){
return getSecurityCode(4,SecurityCodeLevel.Medium,false);
}
/**
* 产生长度和难度任意的验证码
* @param length 长度
* @param level 难度级别
* @param isCanRepeat 是否能够出现重复的字符,如果为true,则可能出现 5578这样包含两个5,如果为false,则不可能出现这种情况
* @return String 验证码
*/
public static String getSecurityCode(int length,SecurityCodeLevel level,boolean isCanRepeat){
//随机抽取len个字符
int len=length;
//字符集合(除去易混淆的数字0、数字1、字母l、字母o、字母O)
char[] codes={'1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f','g','h','i',
'j','k','m','n','p','q','r','s','t',
'u','v','w','x','y','z','A','B','C',
'D','E','F','G','H','I','J','K','L',
'M','N','P','Q','R','S','T','U','V',
'W','X','Y','Z'};
//根据不同的难度截取字符数组
if(level==SecurityCodeLevel.Simple){
codes=Arrays.copyOfRange(codes, 0,9);
}else if(level==SecurityCodeLevel.Medium){
codes=Arrays.copyOfRange(codes, 0,33);
}
//字符集合长度
int n=codes.length;
//抛出运行时异常
if(len>n&&isCanRepeat==false){
throw new RuntimeException(
String.format("调用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出现异常," +
"当isCanRepeat为%3$s时,传入参数%1$s不能大于%4$s",
len,level,isCanRepeat,n));
}
//存放抽取出来的字符
char[] result=new char[len];
//判断能否出现重复的字符
if(isCanRepeat){
for(int i=0;i<result.length;i++){
//索引 0 and n-1
int r=(int)(Math.random()*n);
//将result中的第i个元素设置为codes[r]存放的数值
result[i]=codes[r];
}
}else{
for(int i=0;i<result.length;i++){
//索引 0 and n-1
int r=(int)(Math.random()*n);
//将result中的第i个元素设置为codes[r]存放的数值
result[i]=codes[r];
//必须确保不会再次抽取到那个字符,因为所有抽取的字符必须不相同。
//因此,这里用数组中的最后一个字符改写codes[r],并将n减1
codes[r]=codes[n-1];
n--;
}
}
return String.valueOf(result);
}
}
编写工具类SecurityImage:
package com.albertyy.crm.utils;
/**
*
* 项目名称:CRM
* 类名称:SecurityImage
* 类描述: 生成验证码图片
* 创建人:yangyangyang
* 创建时间:2019年1月4日 下午5:09:18
* 修改人:yangyangyang
* 修改时间:2019年1月4日 下午5:09:18
* 修改备注:
* @version
*
*/
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.util.Random;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* 工具类,生成验证码图片
* @version 1.0 2012/08/21
* @author dongliyang
*
*/
public class SecurityImage {
/**
* 生成验证码图片
* @param securityCode 验证码字符
* @return BufferedImage 图片
*/
public static BufferedImage createImage(String securityCode){
//验证码长度
int codeLength=securityCode.length();
//字体大小
int fSize = 15;
int fWidth = fSize + 1;
//图片宽度
int width = codeLength * fWidth + 6 ;
//图片高度
int height = fSize * 2 + 1;
//图片
BufferedImage image=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g=image.createGraphics();
//设置背景色
g.setColor(Color.WHITE);
//填充背景
g.fillRect(0, 0, width, height);
//设置边框颜色
g.setColor(Color.LIGHT_GRAY);
//边框字体样式
g.setFont(new Font("Arial", Font.BOLD, height - 2));
//绘制边框
g.drawRect(0, 0, width - 1, height -1);
//绘制噪点
Random rand = new Random();
//设置噪点颜色
g.setColor(Color.LIGHT_GRAY);
for(int i = 0;i < codeLength * 6;i++){
int x = rand.nextInt(width);
int y = rand.nextInt(height);
//绘制1*1大小的矩形
g.drawRect(x, y, 1, 1);
}
//绘制验证码
int codeY = height - 10;
//设置字体颜色和样式
g.setColor(new Color(19,148,246));
g.setFont(new Font("Georgia", Font.BOLD, fSize));
for(int i = 0; i < codeLength;i++){
g.drawString(String.valueOf(securityCode.charAt(i)), i * 16 + 5, codeY);
}
//关闭资源
g.dispose();
return image;
}
/**
* 返回验证码图片的流格式
* @param securityCode 验证码
* @return ByteArrayInputStream 图片流
*/
public static ByteArrayInputStream getImageAsInputStream(String securityCode){
BufferedImage image = createImage(securityCode);
return convertImageToStream(image);
}
/**
* 将BufferedImage转换成ByteArrayInputStream
* @param image 图片
* @return ByteArrayInputStream 流
*/
private static ByteArrayInputStream convertImageToStream(BufferedImage image){
ByteArrayInputStream inputStream = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(bos);
try {
jpeg.encode(image);
byte[] bts = bos.toByteArray();
inputStream = new ByteArrayInputStream(bts);
} catch (ImageFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return inputStream;
}
}
3.2编写action
package com.albertyy.crm.web.action;
import java.io.ByteArrayInputStream;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import com.albertyy.crm.utils.SecurityCode;
import com.albertyy.crm.utils.SecurityCode.SecurityCodeLevel;
import com.albertyy.crm.utils.SecurityImage;
import com.opensymphony.xwork2.ActionSupport;
/**
*
* 项目名称:CRM
* 类名称:SecurityCodeImageAction
* 类描述: 验证码
* 创建人:yangyangyang
* 创建时间:2019年1月4日 下午5:35:21
* 修改人:yangyangyang
* 修改时间:2019年1月4日 下午5:35:21
* 修改备注:
* @version
*
*/
@SuppressWarnings("serial")
public class SecurityCodeImageAction extends ActionSupport implements SessionAware{
//Struts2中Map类型的session
private Map<String, Object> session;
//图片流
private ByteArrayInputStream imageStream;
public ByteArrayInputStream getImageStream() {
return imageStream;
}
public void setImageStream(ByteArrayInputStream imageStream) {
this.imageStream = imageStream;
}
public String execute() throws Exception {
//如果开启Hard模式,可以不区分大小写
String securityCode = SecurityCode.getSecurityCode(4,SecurityCodeLevel.Hard, false).toLowerCase();
//获取默认难度和长度的验证码
//String securityCode = SecurityCode.getSecurityCode();
imageStream = SecurityImage.getImageAsInputStream(securityCode);
//放入session中
session.put("SESSION_SECURITY_CODE", securityCode);
return SUCCESS;
}
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
配置文件:
<!-- 验证码action -->
<action name="SecurityCodeImageAction" class="com.albertyy.crm.web.action.SecurityCodeImageAction">
<result name="success" type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">imageStream</param>
<param name="bufferSize">2048</param>
</result>
</action>
3.3编写页面
Html:
<a href="###"><img id="Verify" src="${pageContext.request.contextPath}/SecurityCodeImageAction.action" alt="看不清换一张" width="80" height="40"></a>
Js:
<script type="text/javascript">
window.onload=function(){
var verifyObj = document.getElementById("Verify");
verifyObj.onclick=function(){
this.src="SecurityCodeImageAction.action?timestamp="+new Date().getTime();
};
}
</script>
本项目基本的功能已经实现,由于只是练手,后边的小功能不在实现,如有需要可以自己实现。
源码已经上传,地址为:https://github.com/AlbertYang666/CRM
演示地址:http://www.albertyy.com/CRM/