CRM第六天:客户拜访管理,权限配置,验证码实现

Source
版权声明:版权所有转载请注明出处 https://blog.csdn.net/qq_23853743/article/details/85798058

目录

1.CRM客户关系管理系统:客户拜访记录

1.1需求概述

1.2准备工作

1.2.1创建表

1.2.2创建实体和映射

1.2.3创建相关类,并交给Spring管理

1.3客户拜访记录列表显示

1.3.1修改left.jsp的提交路径

1.3.2编写action

1.3.3编写service

1.3.4编写显示页面

1.4客户拜访记录列表显示

1.4.1编写action

1.4.2编写service

1.4.3编写保存页面

2.权限管理

2.1编写一个类继承拦截器类

2.2配置拦截器

3验证码

3.1编写工具类

3.2编写action

3.3编写页面


 

1.CRM客户关系管理系统:客户拜访记录

1.1需求概述

一个系统的用户(公司业务员),业务员需要对客户进行拜访,对拜访的过程进行记录。业务员(用户)和客户(客户)之间关系(需要具体业务具体分析:一对多公司产品比较单一,只允许一个业务员对应多个客户。多对多大公司有不同的产品,不同产品下有不同业务员都可以接触到同一个客户,一个客户可以对应多个业务员)。大部分情况创建成多对多。

  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">&nbsp;</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/