目录
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/
文章来源: albertyang.blog.csdn.net,作者:Albert Yang,版权归原作者所有,如需转载,请联系作者。
原文链接:albertyang.blog.csdn.net/article/details/85798058