文章目录
1、CRM综合练习:客户管理-保存客户上传客户资质图片文件上传回顾文件上传的代码实现2、CRM综合练习:客户管理-删除客户客户删除操作3、CRM综合练习:客户管理-修改客户客户的修改操作4、CRM综合练习:客户管理-条件查询客户客户管理的条件查询5、CRM综合练习:联系人管理-查询列表联系人准备工作查询联系人列表1、CRM综合练习:客户管理-保存客户上传客户资质图片
文件上传回顾
什么是文件上传
将本地文件通过流的形式写到服务器上
文件上传技术
JspSmartUpload(很少用)
fileupload
Servlet3.0
文件上传
注解开发
异步请求
Struts2框架
底层的实现还是FileUpload,对FileUpload进行封装
文件上传要素
表单的提交方式必须是POST
表单中需要提供<input type="file" name="upload">
并且这个文件项必须有name属性和值
表单的enctype属性必须是multipart/form-data
文件上传的代码实现
第一步:修改JSP页面(添加)
提供文件上传项
修改表单的enctype属性
第二步:编写UpLoadUtils
public class UpLoadUtils {//获得uuid文件名的方法public static String getUploadFileName(String fileName){int idx = fileName.lastIndexOf(".");//aa.txtString extions = fileName.substring(idx);//.txtString uuid = UUID.randomUUID().toString().replace("-", ""); //07d12c2a……fileName = uuid+extions;//全名称return fileName;}//用于目录分离的方法public static String getPath(String uuidFileName){int code1 = uuidFileName.hashCode();int d1 = code1 & 0xf;//作为一级目录,相当于&1111,结果就为d1int code2 = code1 >>> 4;//因为int是4个字节,所以右移4位int d2 = code2 & 0xf;//作为二级目录return "/"+d1+"/"+d2;}//用于测试是否可行public static void main(String[] args) {String file = "aa.txt";int idx = file.lastIndexOf(".");//aa.txtString extions = file.substring(idx);//txtSystem.out.println(extions);//String uuid = UuidUtil.getTimeBasedUuid().toString();String uuid = UUID.randomUUID().toString();file = uuid+extions;System.out.println(uuid);System.out.println(file);}}
第三步:修改Action中的save方法
Struts2的文件上传
在Action中提供三个属性,对三个属性提供set方法
字符串类型上传项名称+FileName
文件类型上传项名称
字符串类型上传项名称+ContentType
//页面传递过来的属性private String uploadFileName;//可用准确的拿到页面提交的文件名private File upload;//保存着源文件的代码数据private String uploadContentType;//保存着源文件的编码类型public void setUploadFileName(String uploadFileName) {this.uploadFileName = uploadFileName;}public void setUpload(File upload) {this.upload = upload;}public void setUploadContentType(String uploadContentType) {this.uploadContentType = uploadContentType;}//保存客户的方法public String save() throws IOException{System.out.println("Action中的save方法执行了....");//若web层没有使用struts2,则必须如下编写:/*ServletContext sc = ServletActionContext.getServletContext();WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(sc);CustomerService service = (CustomerService)context.getBean("customerService");*///customerService.save(customer);//上传公司资质文件的部分if(upload!=null){//文件上传//设置文件上传的路径String path = "D:/Study-program/SSH-image";//一个目录下存放的相同文件名:随机文件名uploadFileName = UpLoadUtils.getUploadFileName(uploadFileName);//一个目录下存放的文件过多:目录分离String realPath = UpLoadUtils.getPath(uploadFileName);String url = path+realPath;File dir = new File(url);//绝对路径if(!dir.exists())dir.mkdirs();//创建多级目录//文件上传File file = new File(url+"/"+uploadFileName);FileUtils.copyFile(upload, file);//前是源文件,即网页传过来的文件}return NONE;}
第四步:将文件上传路径存入到数据库中
修改实体:增加一个属性-cust_image
修改映射:增加一个属性映射-cust_image
修改ActionResult:增加一个saveSuccess的result
<result name="saveSuccess" type="redirectAction">customer_findAll</result>
修改文件上传代码
//页面传递过来的属性private String uploadFileName;//可用准确的拿到页面提交的文件名private File upload;//保存着源文件的代码数据private String uploadContentType;//保存着源文件的编码类型public void setUploadFileName(String uploadFileName) {this.uploadFileName = uploadFileName;}public void setUpload(File upload) {this.upload = upload;}public void setUploadContentType(String uploadContentType) {this.uploadContentType = uploadContentType;}//保存客户的方法publicString save() throws IOException{//上传公司资质文件的部分if(upload!=null){//文件上传//设置文件上传的路径String path = "D:/Study-program/SSH-image";//一个目录下存放的相同文件名:随机文件名uploadFileName = UpLoadUtils.getUploadFileName(uploadFileName);//一个目录下存放的文件过多:目录分离String realPath = UpLoadUtils.getPath(uploadFileName);String url = path+realPath;File dir = new File(url);//绝对路径if(!dir.exists())dir.mkdirs();//创建多级目录//文件上传File file = new File(url+"/"+uploadFileName);customer.setCust_image(url+"/"+uploadFileName);FileUtils.copyFile(upload, file);//前是源文件,即网页传过来的文件}//最后执行保存客户的方法customerService.save(customer);return "saveSuccess";}
对于上传文件的几点扩展
可以设置一次上传中总的最大的文件大小限制
可以设置一次上传中每个文件的最大大小限制
可以设置一次上传中每个文件的文件类型与扩展名
设置完这些限制之后要写个input视图和页面错误回显,否则页面就崩了
2、CRM综合练习:客户管理-删除客户
客户删除操作
第一步:修改list页面中的删除链接
<a href="${pageContext.request.contextPath }/customer_delete?cust_id=<s:property value="cust_id"/>">删除</a>
第二步:编写Service
@Overridepublic Customer getById(Long cust_id) {return dao.getById(cust_id);}@Overridepublic void delete(Customer customer) {dao.delete(customer);}
第三步:编写Dao
@Overridepublic Customer getById(Long cust_id) {return this.getHibernateTemplate().get(Customer.class, cust_id);}@Overridepublic void delete(Customer customer) {this.getHibernateTemplate().delete(customer);}
第四步:编写Action
//删除客户的方法public String delete(){//调用service中的查找单个客户方法Customer cust = customerService.getById(customer.getCust_id());//先删除客户中保存的资质文件if(cust.getCust_image()!=null){File file = new File(cust.getCust_image());file.delete();}//最后执行删除用户的操作customerService.delete(cust);return "deleteSuccess";}
第五步:配置deleteSuccess的result
<result name="deleteSuccess" type="redirectAction">customer_findAll</result>
3、CRM综合练习:客户管理-修改客户
客户的修改操作
修改list页面的修改链接
<a href="${pageContext.request.contextPath }/customer_edit?cust_id=<s:property value="cust_id"/>">修改</a>
编写Action中的edit方法
//修改客户的方法public String edit(){System.out.println("Action的edit方法被执行了");//调用service中的查找单个客户方法customer = customerService.getById(customer.getCust_id());//将customer传递到页面的两种方式://第一种:回显数据-<s:property value="cust_name"/> <s:textfield name="cust_name"/>//第二种:回显数据-<s:property value="model.cust_name"/> 第二种不用写代码ActionContext.getContext().getValueStack().push(customer);//第一种方式//跳转页面return "editSuccess";}
在页面中回显数据
普通输入框的回显
<td>客户名称:</td><td><s:hidden name="cust_image"/>//这里一定要有隐藏id<s:hidden name="cust_id"/><s:textfield cssClass="textbox" cssStyle="WIDTH: 180px" maxlength="50" name="cust_name" /></td>......
下拉列表的回显
<script type="text/javascript">$(function(){/*页面加载函数就会执行页面加载,异步查询字典数据加载客户来源*/$.post("${pageContext.request.contextPath }/baseDict_findByTypeCode",{"dict_type_code":"002"},function(data){//遍历json的数据$(data).each(function(i,n){$("#cust_source").append("<option value='"+n.dict_id+"'>"+n.dict_item_name+"</option>");});//利用EL获取到值栈的数据$("#cust_source option[value='${cust_source.dict_id}']").prop("selected","selected");},"json");$.post("${pageContext.request.contextPath }/baseDict_findByTypeCode",{"dict_type_code":"001"},function(data){$(data).each(function(i,n){$("#cust_industry").append("<option value='"+n.dict_id+"'>"+n.dict_item_name+"</option>");});$("#cust_industry option[value='${cust_industry.dict_id}']").prop("selected","selected");},"json");$.post("${pageContext.request.contextPath }/baseDict_findByTypeCode",{"dict_type_code":"006"},function(data){$(data).each(function(i,n){$("#cust_level").append("<option value='"+n.dict_id+"'>"+n.dict_item_name+"</option>");});$("#cust_level option[value='${cust_level.dict_id}']").prop("selected","selected");},"json");});</script>
修改edit.jsp中的提交路径
<s:form id="form1" name="form1" action="customer_update" namespace="/" method="post" enctype="multipart/form-data" theme="simple">
编写Service
@Overridepublic void update(Customer customer) {dao.update(customer);}
编写Dao
@Overridepublic void update(Customer customer) {this.getHibernateTemplate().update(customer);}
编写Action中的update方法
//修改客户的方法public String update() throws IOException{//文件是否已经选择,若选择了就上传;否则使用原来的if(upload != null){String cust_image = customer.getCust_image();if(cust_image!=null || !"".equals(cust_image)){//删除原有文件File old_file = new File(cust_image);if(old_file.exists())old_file.delete();}//设置文件上传的路径String path = "D:/Study-program/SSH-image";//一个目录下存放的相同文件名:随机文件名uploadFileName = UpLoadUtils.getUploadFileName(uploadFileName);//一个目录下存放的文件过多:目录分离String realPath = UpLoadUtils.getPath(uploadFileName);String url = path+realPath;File dir = new File(url);//绝对路径if(!dir.exists())dir.mkdirs();//创建多级目录//文件上传File file = new File(url+"/"+uploadFileName);FileUtils.copyFile(upload, file);//前是源文件,即网页传过来的文件customer.setCust_image(url+"/"+uploadFileName);}//调用service中的更新客户的方法customerService.update(customer);return "updateSuccess";}
配置struts中的result
<result name="editSuccess">/jsp/customer/add.jsp</result><result name="updateSuccess" type="redirectAction">customer_findAll</result>
小结:
1、文件上传的代码一定要熟练掌握
2、下拉列表的回显,中间套用了ognl
3、theme="simple"即struts2自带表单的样式为空
4、CRM综合练习:客户管理-条件查询客户
客户管理的条件查询
在list页面准备条件
提供表单元素
<TD>客户名称:</TD><TD><INPUT class=textbox id=sChannel2style="WIDTH: 80px" maxLength=50 name="cust_name"value="<s:property value="cust_name"/>"></TD><TD>客户来源:</TD><TD><select id="cust_source" name="cust_source.dict_id"><option value="">-请选择-</option></select><TD>客户级别:</TD><TD><select id="cust_level" name="cust_level.dict_id"><option value="">-请选择-</option></select></TD><TD>所属行业:</TD><TD><select id="cust_industry" name="cust_industry.dict_id"><option value="">-请选择-</option></select></TD>
异步加载数据并在条件上回显数据
<script type="text/javascript">$(function(){/*页面加载函数就会执行页面加载,异步查询字典数据加载客户来源*/$.post("${pageContext.request.contextPath }/baseDict_findByTypeCode.action",{"dict_type_code":"002"},function(data){//遍历json的数据$(data).each(function(i,n){$("#cust_source").append("<option value='"+n.dict_id+"'>"+n.dict_item_name+"</option>");});},"json");$.post("${pageContext.request.contextPath }/baseDict_findByTypeCode.action",{"dict_type_code":"001"},function(data){//遍历json的数据$(data).each(function(i,n){$("#cust_industry").append("<option value='"+n.dict_id+"'>"+n.dict_item_name+"</option>");});},"json");$.post("${pageContext.request.contextPath }/baseDict_findByTypeCode.action",{"dict_type_code":"006"},function(data){//遍历json的数据$(data).each(function(i,n){$("#cust_level").append("<option value='"+n.dict_id+"'>"+n.dict_item_name+"</option>");});},"json");});</script>
改写Action中的findAll方法
//分页查询客户的方法public String findAll(){System.out.println("执行了```");//最好使用DetachedCriteria对象(条件查询--带分页)DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);//设置web查询条件if(customer.getCust_name()!=null){criteria.add(Restrictions.like("cust_name", "%"+customer.getCust_name()+"%"));}if(customer.getCust_source()!=null){if(customer.getCust_source().getDict_id()!=null&&!"".equals(customer.getCust_source().getDict_id())){criteria.add(Restrictions.eq("cust_source.dict_id", customer.getCust_source().getDict_id()));}}if(customer.getCust_level()!=null){if(customer.getCust_level().getDict_id()!=null&&!"".equals(customer.getCust_level().getDict_id())){System.out.println(customer.getCust_level().getDict_id());criteria.add(Restrictions.eq("cust_level.dict_id", customer.getCust_level().getDict_id()));}}if(customer.getCust_industry()!=null){if(customer.getCust_industry().getDict_id()!=null&&!"".equals(customer.getCust_industry().getDict_id())){criteria.add(Restrictions.eq("cust_industry.dict_id", customer.getCust_industry().getDict_id()));}}//调用业务层进行查询PageBean<Customer> pageBean = customerService.findAll(criteria, curPage, pageSize);ServletActionContext.getRequest().setAttribute("pageBean", pageBean);System.out.println(pageBean.getPageSize());return "customer_list";}
5、CRM综合练习:联系人管理-查询列表
联系人准备工作
创建表
CREATE TABLE `cst_linkman` (`lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',`lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',`lkm_cust_id` bigint(32) NOT NULL COMMENT '客户id',`lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别',`lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',`lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',`lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',`lkm_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq',`lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',`lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',PRIMARY KEY (`lkm_id`),KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
创建实体和映射
实体类的编写
public class LinkMan {private Long lkm_id;private String lkm_name;private String lkm_gender;private String lkm_phone;private String lkm_mobile;private String lkm_email;private String lkm_qq;private String lkm_position;private String lkm_memo;//联系人属于多的一方private Customer customer;}
映射的配置
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><!-- 建立类与表的映射 --><class name="domain.LinkMan" table="cst_linkman"><!-- 主键字段 --><id name="lkm_id" column="lkm_id"><generator class="native"/></id><!-- 普通的属性字段 --><property name="lkm_name"/><property name="lkm_gender"/><property name="lkm_phone"/><property name="lkm_mobile"/><property name="lkm_email"/><property name="lkm_qq"/><property name="lkm_position"/><property name="lkm_memo"/><many-to-one name="customer" class="domain.Customer" column="lkm_cust_id"/><!-- 如果查询时没用到关联对象就不用设置 --></class></hibernate-mapping>
在Spring中配置映射:加上<value>domain/LinkMan.hbm.xml</value>
创建相关类
创建Action
创建Service
创建Dao
//actionpublic class LinkManAction extends ActionSupport implements ModelDriven<LinkMan>{//模型驱动使用的对象private LinkMan linkMan = new LinkMan();@Overridepublic LinkMan getModel() {return linkMan;}//注入Serviceprivate LinkManService linkManService;public void setLinkManService(LinkManService linkManService) {this.linkManService = linkManService;}}//servicepublic class LinkManServiceImpl implements LinkManService {//注入daoprivate LinkManDao dao;public void setDao(LinkManDao dao) {this.dao = dao;}}//daopublic class LinkManDaoImpl extends HibernateDaoSupport implements LinkManDao {}
配置Spring的dao、service、action、映射
<bean id="linkManService" class="service.serviceImpl.LinkManServiceImpl"><property name="dao" ref="linkManDao"/></bean><bean id="linkManDao" class="dao.daoImpl.LinkManDaoImpl"><property name="sessionFactory" ref="sessionFactory"/></bean><bean id="linkManAction" class="web.action.LinkManAction" scope="prototype"><property name="linkManService" ref="linkManService"/></bean>
查询联系人列表
修改menu.jsp的链接
<TD class=menuSmall><A class=style2 href="${pageContext.request.contextPath}/linkMan_findAll"
编写action
编写service
编写dao
list页面显示联系人信息
<TR><TD><TABLE id=gridstyle="BORDER-TOP-WIDTH: 0px; FONT-WEIGHT: normal; BORDER-LEFT-WIDTH: 0px; BORDER-LEFT-COLOR: #cccccc; BORDER-BOTTOM-WIDTH: 0px; BORDER-BOTTOM-COLOR: #cccccc; WIDTH: 100%; BORDER-TOP-COLOR: #cccccc; FONT-STYLE: normal; BACKGROUND-COLOR: #cccccc; BORDER-RIGHT-WIDTH: 0px; TEXT-DECORATION: none; BORDER-RIGHT-COLOR: #cccccc"cellSpacing=1 cellPadding=2 rules=all border=0><TBODY><TRstyle="FONT-WEIGHT: bold; FONT-STYLE: normal; BACKGROUND-COLOR: #eeeeee; TEXT-DECORATION: none"><TD>联系人名称</TD><TD>性别</TD><TD>办公电话</TD><TD>手机</TD><TD>邮箱</TD><TD>qq</TD><TD>职位</TD><TD>所属客户</TD><TD>操作</TD></TR><s:iterator value="list"><TRstyle="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"><TD><s:property value="lkm_name"/></TD><TD><s:property value="lkm_gender"/></TD><TD><s:property value="lkm_phone"/></TD><TD><s:property value="lkm_mobile"/></TD><TD><s:property value="lkm_email"/></TD><TD><s:property value="lkm_qq"/></TD><TD><s:property value="lkm_position"/></TD><TD><s:property value="customer.cust_name"/></TD><TD><a href="${pageContext.request.contextPath }/linkmanServlet?method=edit&lkmId=${linkman.lkmId}">修改</a> <a href="${pageContext.request.contextPath }/linkmanServlet?method=delete&lkmId=${linkman.lkmId}">删除</a></TD></TR></s:iterator></TBODY></TABLE></TD></TR><TR><TD><SPAN id=pagelink><DIVstyle="LINE-HEIGHT: 20px; HEIGHT: 20px; TEXT-ALIGN: right">共[<B><s:property value="totalCount"/></B>]条记录,[<B><s:property value="totalPage"/></B>]页,每页显示<select name="pageSize" onchange="to_page()"><option value="3" <s:if test="pageSize==3">selected</s:if>>3</option><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></select>条<s:if test="curPage!=1">[<A name="curPage" href="javascript:to_page(<s:property value="curPage"/>-1)">前一页</A>]</s:if><B><s:property value="curPage"/></B><s:if test="curPage!=totalPage">[<A name="curPage" href="javascript:to_page(<s:property value="curPage"/>+1)">后一页</A>] </s:if>到<input type="text" size="3" id="page" name="curPage" />页<input type="button" value="Go" onclick="to_page()"/></DIV></SPAN></TD></TR>