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


    目录

    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=" 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/

     

     

     

  • 相关阅读:
    permission 文档 翻译 运行时权限
    TabLayout ViewPager Fragment 简介 案例 MD
    Log 日志工具类 保存到文件 MD
    OkHttp 官方wiki 翻译 MD
    Okhttp 简介 示例 MD
    OkHttp 官方Wiki之【使用案例】
    DialogPlus
    倒计时 总结 Timer Handler CountDownTimer RxJava MD
    RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD
    CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全
  • 原文地址:https://www.cnblogs.com/yangxianyang/p/13675629.html
Copyright © 2020-2023  润新知