1、实现商品类目选择功能
1.1需求
在商品添加页面,点击“选择类目”显示商品类目列表:
请求初始化树形控件的url:/item/cat/list
1.2 EasyUI tree数据结构
数据结构中必须包含:
Id:节点id
Text:节点名称
State:如果不是叶子节点就是close,叶子节点就是open。Close的节点点击后会在此发送请求查询子项目。
可以根据parentid查询分类列表。
1.3思路
1.3.1 dao层
SQL语句:select * from tb_item_cat where parent_id=0
单表查询,可以使用逆向工程生成的代码。
1.3.2 service层
功能:接受parentid的参数,根据parentid查询子类目类别。返回一个分类列表,可以创建一个pojo来描述一个节点的格式,返回一个pojo列表。
包含id、text、state属性。因为其他工程也有可能用到此pojo所以应该放到taoatao-common工程中。
创建一个接口ItemCatServic,编写接口getCatList
service
/**
* 商品分类管理
* @author Administrator
*
*/
@Service
public class ItemCatServicImpl implements ItemCatService {
@Autowired
private TbItemCatMapper itemcatmapper;
@Override
public List<EUTreeNode> getCatList(long parentId) {
//创建查询条件
TbItemCatExample example=new TbItemCatExample();
Criteria criteria=example.createCriteria();
criteria.andParentIdEqualTo(parentId);
//根据条件查询
List<TbItemCat> list=itemcatmapper.selectByExample(example);
List<EUTreeNode> resultlist=new ArrayList<>();
//把列表转换为treeNodelist
for (TbItemCat tbItemCat : list) {
EUTreeNode node=new EUTreeNode();
node.setId(tbItemCat.getId());
node.setText(tbItemCat.getName());
node.setState(tbItemCat.getIsParent()?"closed":"open");
resultlist.add(node);
}
return resultlist;
}
}
1.3.3 controller层
功能:接受页面请求的参数,名为id。调用service查询分类列表。返回的是JSON格式的列表,需要使用@ResponseBody注解。
@Controller
@RequestMapping("/item/cat")
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
@RequestMapping("/list")
@ResponseBody
//如果id为null是使用默认值,也就是parentid为0的分类列表
public List<EUTreeNode> getCatList(@RequestParam(value="id",defaultValue="0")long parentId)
{
List<EUTreeNode> list=itemCatService.getCatList(parentId);
return list;
}
}
2、上传图片
2.1图片服务器
2.1.1分布式环境的图片管理
2.1.2图片服务器的搭建
需要的软件
- linux centos6.5
- nginx
- vsftpd
2.1.2.1 安装nginx
(1)nginx安装环境
nginx是C语言开发,建议在linux上运行,本教程使用Centos6.5作为安装环境。
- gcc
安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc:yum install gcc-c++
- PCRE
PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。nginx的http模块使用pcre来解析正则表达式,所以需要在linux上安装pcre库。
yum install -y pcre pcre-devel
注:pcre-devel是使用pcre开发的一个二次开发库。nginx也需要此库。
- zlib
zlib库提供了很多种压缩和解压缩的方式,nginx使用zlib对http包的内容进行gzip,所以需要在linux上安装zlib库。
yum install -y zlib zlib-devel
- openssl
OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
nginx不仅支持http协议,还支持https(即在ssl协议上传输http),所以需要在linux安装openssl库。
yum install -y openssl openssl-devel
(2)编译安装
将nginx-1.8.0.tar.gz拷贝至linux服务器。
解压:
tar -zxvf nginx-1.8.0.tar.gz
cd nginx-1.8.0
- configure
./configure --help查询详细参数(参考本教程附录部分:nginx编译参数)
参数设置如下:
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi
注意:上边将临时文件目录指定为/var/temp/nginx,需要在/var下创建temp及nginx目录
- 编译makefile
make
make install
编译完后会在 /usr/local/sbin目录下有一个nginx可执行文件
- nginx的使用
启动:./nginx
关闭:./nginx -s stop
重新加载配置文件:./nginx -s reload
(4)开放Linux的对外访问的端口80(nginx默认端口号为80)
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/etc/rc.d/init.d/iptables save
(5)访问nginx服务成功!
2.1.2.2配置ftp服务
2.1.2.2.1安装ftp组件
(1)安装vsftpd组件
安装完后,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件。
[root@bogon ~]# yum -y install vsftpd
(2)添加一个ftp用户
此用户就是用来登录ftp服务器用的。
[root@bogon ~]# useradd ftpuser
这样一个用户建完,可以用这个登录,记得用普通登录不要用匿名了。登录后默认的路径为 /home/ftpuser.
(3)给ftp用户添加密码。
[root@bogon ~]# passwd ftpuser
输入两次密码后修改密码。
(4)防火墙开启21端口
因为ftp默认的端口为21,而centos默认是没有开启的,所以要修改iptables文件
[root@bogon ~]# vim /etc/sysconfig/iptables
在行上面有22 -j ACCEPT 下面另起一行输入跟那行差不多的,只是把22换成21,然后:wq保存。
还要运行下,重启iptables
[root@bogon ~]# service iptables restart
(5)修改selinux
外网是可以访问上去了,可是发现没法返回目录(使用ftp的主动模式,被动模式还是无法访问),也上传不了,因为selinux作怪了。
修改selinux:
执行以下命令查看状态:
[root@bogon ~]# getsebool -a | grep ftp
allow_ftpd_anon_write --> off
allow_ftpd_full_access --> off
allow_ftpd_use_cifs --> off
allow_ftpd_use_nfs --> off
ftp_home_dir --> off
ftpd_connect_db --> off
ftpd_use_passive_mode --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
[root@bogon ~]#
执行上面命令,再返回的结果看到两行都是off,代表,没有开启外网的访问
[root@bogon ~]# setsebool -P allow_ftpd_full_access on
[root@bogon ~]# setsebool -P ftp_home_dir on
这样应该没问题了(如果,还是不行,看看是不是用了ftp客户端工具用了passive模式访问了,如提示Entering Passive mode,就代表是passive模式,默认是不行的,因为ftp passive模式被iptables挡住了,下面会讲怎么开启,如果懒得开的话,就看看你客户端ftp是否有port模式的选项,或者把passive模式的选项去掉。如果客户端还是不行,看看客户端上的主机的电脑是否开了防火墙,关吧)
FileZilla的主动、被动模式修改:
菜单:编辑→设置
(6)关闭匿名访问
修改/etc/vsftpd/vsftpd.conf文件:
重启ftp服务:
[root@bogon ~]# service vsftpd restart
(7)开启被动模式
默认是开启的,但是要指定一个端口范围,打开vsftpd.conf文件,在后面加上
pasv_min_port=30000
pasv_max_port=30999
表示端口范围为30000~30999,这个可以随意改。改完重启一下vsftpd
由于指定这段端口范围,iptables也要相应的开启这个范围,所以像上面那样打开iptables文件。
也是在21上下面另起一行,更那行差不多,只是把21 改为30000:30999,然后:wq保存,重启下iptables。这样就搞定了。
(8)设置开机启动vsftpd ftp服务
[root@bogon ~]# chkconfig vsftpd on
- FileZilla连接成功!
密码:ftpuser 端口:21
2.1.2.2.2访问ftp服务
使用Java代码访问,用到Apache提供的一个工具包common-net
web已依赖了common中的这个包
需要把ftp上传功能封装成一个工具类,可以供其他项目使用。提高代码的复用性。
编写测试类
测试时出错
解决办法:
给ftpuser目录添加权限
命令:chmod 777 /home/ftpuser/
附:linux权限命令解释
Linux的权限命令
权限是Linux中的重要概念,每个文件/目录等都具有权限,通过ls -l命令我们可以 查看某个目录下的文件或目录的权限
示例:在随意某个目录下ls -l
第一列的内容的信息解释如下:
文件的类型:
d:代表目录
-:代表文件
l:代表链接(可以认为是window中的快捷方式)
后面的9位分为3组,每3位置一组,分别代表属主的权限,与当前用户同组的 用户的权限,其他用户的权限
r:代表权限是可读,r也可以用数字4表示
w:代表权限是可写,w也可以用数字2表示
x:代表权限是可执行,x也可以用数字1表示
修改文件/目录的权限的命令:chmod
示例:修改/test下的aaa.txt的权限为属主有全部权限,属主所在的组有读写权限,
其他用户只有读的权限
chmod u=rwx,g=rw,o=r aaa.txt
上述示例还可以使用数字表示:
chmod 764 aaa.txt
成功访问ftp上的图片!
2.2图片上传的实现
2.2.1需求分析
参考文档:http://kindeditor.net/doc.php
请求的url:/pic/upload
请求的参数:uploadfile
响应的结果:
2.2.2 dao层
无
2.2.3 service层
功能:接受controller传过来的参数,一个文件multipartfile对象。把文件上传到ftp服务器。生成一个新的文件名。返回文件url路径。需要包装成图片上传插件要求的数据格式。
使用map来实现:
map中的内容:
key value
--------------------------------------------------
error 1/0
url 图片的URL(成功时)
message 错误信息(失败时)
在PictureService创建一个接口uploadPicture,返回的是一个map
impl:
导入生成随机文件名的工具类IDUtils
在web工程下的resourse创建resource.properties,写入相关配置信息。修改spring文件,使之能够读取该文件。
/**
* 图片上传服务
* @author Administrator
*
*/
@Service
public class PictureServiceImpl implements PictureService {
//spring容器自动注入名称相同的属性
@Value("${FTP_ADDRESS}")
private String FTP_ADDRESS;
@Value("${FTP_PORT}")
private Integer FTP_PORT;
@Value("${FTP_USERNAME}")
private String FTP_USERNAME;
@Value("${FTP_PASSWORD}")
private String FTP_PASSWORD;
@Value("${FTP_BASEPATH}")
private String FTP_BASEPATH;
@Value("${IMAGE_BASE_URL}")
private String IMAGE_BASE_URL;
@Override
public Map uploadPicture(MultipartFile uploadFile) {
Map resultMap=new HashMap<>();
try {
//生成一个新的文件名
//先取原始文件名
String oldName=uploadFile.getOriginalFilename();
//生成新文件名
//方法一:使用UUID
//UUID.randomUUID();
//方法二:使用时间加随机数生成,已写好工具类IDUtils
String newName=IDUtils.genImageName();
//文件名=newName+oldName点后面的扩张名
newName=newName+oldName.substring(oldName.lastIndexOf("."));
//图片上传
//使用.joda.time组件按时间生成文件名路径
String imagePath=new DateTime().toString("/yyyy/MM/dd");
boolean result=FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, FTP_BASEPATH,
imagePath, newName, uploadFile.getInputStream());
//返回结果
if(!result)
{
resultMap.put("error", 1);
resultMap.put("message", "文件上传失败!");
return resultMap;
}
resultMap.put("error", 0);
resultMap.put("url", IMAGE_BASE_URL + imagePath+ "/" +newName);
return resultMap;
} catch (Exception e) {
resultMap.put("error", 1);
resultMap.put("message", "文件上传发生异常!");
return resultMap;
}
}
}
#FTP相关配置
#FTP的ip地址
FTP_ADDRESS=192.168.201.130
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASEPATH=/home/ftpuser/www/images
#图片服务器的相关配置
#服务器的基础URL
IMAGE_BASE_URL=http://192.168.204.130/images
2.2.4 controller层
功能:接受MultiPartFile对象。调用service上传图片返回的Json格式。使用@ResponseBody注解。
需要引入fie-load、和common-io包
需要在springMVC中配置文件上传解析器,添加如下内容:
<!-- 定义文件上传解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定默认编码 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传的最大值5MB,5*1024*1024 -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
contrleer层代码:
/**
*上传图片处理
* @author Administrator
*
*/
@Controller
public class PictureCntroller {
@Autowired
PictureService pictureService;
@RequestMapping("/pic/upload")
@ResponseBody
public String pictureUpload(MultipartFile uploadFile)
{
Map result=pictureService.uploadPicture(uploadFile);
//为了保证功能的兼容性,需要把result转换成json格式的字符串,需要导入jsonUtil工具类
String json=JsonUtils.objectToJson(result);
return json;
}
}
注意:ftp生成新的文件夹,需要重新添加权限
chmod 777 /home/ftpuser
上传成功!
2.3富文本编辑器
使用方法:
第一步:需要在jsp中添加富文本编辑器js的引用。
第二步:在jsp中添加一个textarea域
第三步:初始化富文本编辑器
在common.js中调用create
第四步:提交表单之前,先把富文本编辑器中的内容和textarea中的内容进行同步
2.4添加商品的实现
2.4.1需求分析
请求的url:/item/save
参数:表单中的内容,序列化成key-value形式的字符串。post请求。
响应的内容:可以自定义。封装在taotaoresult.java中
2.4.2 dao层
把商品信息插入到商品表。单表操作,使用逆向工程生成的代码。
2.4.3 service层
接收商品的pojo,把pojo的内容补全。把商品数据写入到表中(tb_item)。返回taotaoResult。
在itemservice接口中写一个createItem方法
@Override
public TaotaoResult createItem(TbItem item)
{
//item补全
//生成商品id,使用IDUtils工具类
Long itemid=IDUtils.genItemId();
item.setId(itemid);
item.setStatus((byte) 1);
item.setCreated(new Date());
item.setUpdated(new Date());
//插入到数据库
itemMapper.insert(item);
return TaotaoResult.ok();
2.4.4 controller层
接收表单中的内容。使用一个pojo接收。调用service,返回TaoTaoResult对象。返回Json数据,需要使用ResponseBody注解。
@RequestMapping(value="/item/save",method=RequestMethod.POST)
@ResponseBody
private TaotaoResult createItem(TbItem item)
{
TaotaoResult result=itemService.createItem(item);
return result;
}
欢迎进群交流258897306或关注公众号“IT群英汇”