电商项目第三天
优化dubbo
为了能更快速的开发,我们需优化dubbo,只需了解其工作原理即可。
采取直接连接,跳过zookeeper
dubbo-provider.xml更改:
<!-- 2.设置注册中心,zookeeper地址 -->
<!-- <dubbo:registry address="ip+端口号" protocol="zookeeper"/> -->
<dubbo:registry address="N/A"/>
dubbo-consumer.xml
<!-- 2.设置注册中心,zookeeper地址 -->
<!-- <dubbo:registry address="ip+端口号" protocol="zookeeper"/> -->
<dubbo:registry address="N/A" check="false"/>
<!-- 全局配置 -->
<dubbo:consumer timeout="超时时间" check="false"/>
后台搭建
void 无返回值 常用语Ajax请求
ModelAndView 企业开发不常用
String + Model 常用
搭建顺序
dao-mapper-service-serviceImpl-controller
代码实现
商品回显(分页)
pojo:
//品牌ID bigint
private Long id;
//品牌名称
private String name;
//描述
private String description;
//图片URL
private String imgUrl;
//排序 越大越靠前
private Integer sort;
//是否可用 0 不可用 1 可用
...
//附加字段
private Integer pageNo = 1;
private Integer pageSize = 10;
//开始行
private Integer startRow;
...
public void setPageNo(Integer pageNo) {
//计算开始行
this.startRow = (pageNo-1)*pageSize;
this.pageNo = pageNo;
}
...
public void setPageSize(Integer pageSize) {
//计算开始行
this.startRow = (pageNo-1)*pageSize;
this.pageSize = pageSize;
}
dao:
//查询结果集
public List<Brand> selectBrandListByQuery(BrandQuery brandQuery);
//查询总条数
public Integer selectCount(BrandQuery brandQuery);
mapper:
<!-- 配置映射 -->
<resultMap type="Brand" id="brand">
<result column="img_url" property="imgUrl"/><!-- 图片地址 -->
<result column="is_display" property="isDisplay"/><!-- 是否可用 -->
</resultMap>
<!-- 查询 -->
<select id="selectBrandListByQuery" parameterType="BrandQuery" resultMap="brand">
select id,name,description,img_url,sort,is_display
from bbs_brand
<where>
<if test="name != null">
name like "%"#{name}"%" <!-- 模糊查询 -->
</if>
<if test="isDisplay != null">
and is_display = #{isDisplay}
</if>
</where>
<if test="startRow != null">
limit #{startRow},#{pageSize}
</if>
</select>
<!-- 查询总条数 -->
<select id="selectCount" parameterType="BrandQuery" resultType="Integer">
select count(1)
from bbs_brand
<where>
<if test="name != null">
name like "%"#{name}"%" <!-- 模糊查询 -->
</if>
<if test="isDisplay != null">
and is_display = #{isDisplay}
</if>
</where>
</select>
service:
//查询分页对象
public Pagination selectPaginationByQuery(String name,Integer isDisplay,Integer pageNo);
//参数:查询名称、是否可用、起始页
serviceImpl:
public Pagination selectPaginationByQuery(String name,Integer isDisplay,Integer pageNo){
BrandQuery bq = new BrandQuery();
bq.setPageNo(Pagination.cpn(pageNo));
bq.setPageSize(5);//设置每页显示数目
StringBuilder params = new StringBuilder();
if(null != name){
bq.setName(name);
params.append("name=").append(name);//回显查询名称
}
if(null != isDisplay){
bq.setIsDisplay(isDisplay);
params.append("&isDisplay=").append(isDisplay);//回显是否可用
}else{
bq.setIsDisplay(1);//默认点击按钮为是
params.append("&isDisplay=").append(1);//点击左侧菜单进入没有是否可用,默认为可用
}
/**
* 构造器
*
* @param pageNo
* 页码
* @param pageSize
* 每页几条数据
* @param totalCount
* 总共几条数据
*/
Pagination pagination = new Pagination(
bq.getPageNo(),
bq.getPageSize(),
brandDao.selectCount(bq)
);
//设置结果集
pagination.setList(brandDao.selectBrandListByQuery(bq));
//设置分页展示
pagination.pageView("/brand/list.do", params.toString());
return pagination;
}
controller:
//分页列表查询
@RequestMapping(value="/brand/list.do")
public String list(String name,Integer isDisplay,Integer pageNo,Model model){
Pagination pagination = brandService.selectPaginationByQuery(name, isDisplay, pageNo);
model.addAttribute("pagination", pagination);
model.addAttribute("name", name);
if(null != isDisplay){
model.addAttribute("isDisplay", isDisplay);
}else{
model.addAttribute("isDisplay", 1);
}
return "brand/list";
}
前端页面:
//数据回显
<c:forEach items="${pagination.list}" var="brand">
...${brand.id}...
</c:forEach>
//分页
<c:forEach items="${pagination.pageView}" var="page">
${page }
</c:forEach>
商品信息修改
dao:
//通过id查询,数据回显
public Brand selectBrandById(Long id);
//修改
public void updateBrandById(Brand brand);
mapper:
<!-- 按id查询 -->
<select id="selectBrandById" parameterType="Long" resultMap="brand">
select id,name,description,img_url,sort,is_display
from bbs_brand
<where>
id=#{id}
</where>
</select>
<!-- 修改 -->
<update id="updateBrandById" parameterType="Brand">
update bbs_brand
<set>
<if test="name != null">
name = #{name},
</if>
<if test="description != null">
description = #{description},
</if>
<if test="imgUrl != null">
img_url = #{imgUrl},
</if>
<if test="sort != null">
sort = #{sort},
</if>
<if test="isDisplay != null">
is_display = #{isDisplay}
</if>
</set>
<where>
id=#{id}
</where>
</update>
service:
//通过id查询,数据回显
public Brand selectBrandById(Long id);
//修改
public void updateBrandById(Brand brand);
serviceImpl:
@Override
public Brand selectBrandById(Long id) {
// TODO Auto-generated method stub
return brandDao.selectBrandById(id);
}
@Override
public void updateBrandById(Brand brand) {
// TODO Auto-generated method stub
brandDao.updateBrandById(brand);
}
controller:
//去修改
@RequestMapping(value="/brand/toEdit.do")
public String toEdit(Long id,Model model){
Brand brand = brandService.selectBrandById(id);
model.addAttribute("brand", brand);
return "brand/edit";
}
//修改
@RequestMapping(value="/brand/edit.do")
public String edit(Brand brand){
brandService.updateBrandById(brand);
return "redirect:/brand/list.do";
}
FastDFS分布式文件系统原理
client(本机)向 tracker(跟踪器)发送请求 ,tracker查看管理的服务器,把分配好的存储地址返回client,client再根据得到的存储地址去找 storage(存储节点),进行文件上传,上传结束后,返回存储文件的地址信息。
…
通俗的说:你让人揍了,你去找老大搬救兵,老大看看手下谁有空,并把手下的联系方式给你,你通过联系方式找到帮手,带着帮手回去找场子了。
图片上传流程
配置上传图片工具类,common包下新建fastUtils,并引入配置文件 fdfs_client.conf
fastUtils:
public static String uploadPic(byte[] pic,String name,long size){
ClassPathResource resource = new ClassPathResource("fdfs_client.conf");
String path = null;
//ClientGlobal读取配置文件
try {
//读取配置文件
ClientGlobal.init(resource.getClassLoader().getResource("fdfs_client.conf").getPath());
//老大客户端
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
//小弟客户端
StorageServer storageServer = null;
StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
//上传图片
String ext = FilenameUtils.getExtension(name);//获取文件拓展名
//meta 信息
NameValuePair[] meta_list = new NameValuePair[3];
meta_list[0] = new NameValuePair("fileName",name);
meta_list[1] = new NameValuePair("fileNameExt",ext);
meta_list[2] = new NameValuePair("fileSize",String.valueOf(size));
//图片路径信息,还缺少ip
path = storageClient1.upload_file1(pic, ext, meta_list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return path;
}
设置固定ip,业务常量
public class ConStants {
//图片服务器
public static final String IMG_URL = "http://ip.../";
}
service:
//上传图片
public String upLoadPic(byte[] pic,String name,long size);
serviceImpl:
@Override
public String upLoadPic(byte[] pic, String name, long size) {
// TODO Auto-generated method stub
return FastDFSUtils.uploadPic(pic, name, size);
}
controller:
@Autowired
private UploadService uploadService;
//上传图片
@RequestMapping(value="/upload/uploadPic.do")
public void uploadPic(@RequestParam(required=false) MultipartFile pic,HttpServletResponse response){
try {
String path = uploadService.upLoadPic(pic.getBytes(), pic.getOriginalFilename(), pic.getSize());
String url = ConStants.IMG_URL+path;
JSONObject jo = new JSONObject();
jo.put("url", url);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(jo.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
第三天内容结束
所学知识
- 基础业务流程的巩固
- 分页工具类的应用(看了源码才明白差距)
- FastDFS原理及使用
- 新的编程思想
遇到错误
- controller参数写了实体类却没有接到对象信息(原因:实体类没写set方法)
- meta信息不能为空,否则显示空指针异常
- 图片不回显(原因:虚拟机镜像损坏)
- 控制台显示连接超时(原因:固定业务常量ip写错了,蠢!!!)
- 之前没搞懂分页的原理,看了源码已了解
致谢晓欣老师!