文章目录
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.txt
String extions = fileName.substring(idx); //.txt
String 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,结果就为d1
int 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.txt
String extions = file.substring(idx); //txt
System.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
@Override
public Customer getById(Long cust_id) {
return dao.getById(cust_id);
}
@Override
public void delete(Customer customer) {
dao.delete(customer);
}
第三步:编写Dao
@Override
public Customer getById(Long cust_id) {
return this.getHibernateTemplate().get(Customer.class, cust_id);
}
@Override
public 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
@Override
public void update(Customer customer) {
dao.update(customer);
}
编写Dao
@Override
public 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=sChannel2
style="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"
"http://www.hibernate.org/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
//action
public class LinkManAction extends ActionSupport implements ModelDriven<LinkMan>{
//模型驱动使用的对象
private LinkMan linkMan = new LinkMan();
@Override
public LinkMan getModel() {
return linkMan;
}
//注入Service
private LinkManService linkManService;
public void setLinkManService(LinkManService linkManService) {
this.linkManService = linkManService;
}
}
//service
public class LinkManServiceImpl implements LinkManService {
//注入dao
private LinkManDao dao;
public void setDao(LinkManDao dao) {
this.dao = dao;
}
}
//dao
public 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=grid
style="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>
<TR
style="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">
<TR
style="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>
<DIV
style="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>