品优购day05之面包屑导航及fastDFS分布式文件上传

面包屑导航

  • 根据上级id获取下一级内容;

后端代码

 /**
 * 根据上级ID查询列表
 */
@Override
public List<TbItemCat> findByParentId(Long parentId) {		
	TbItemCatExample example1=new TbItemCatExample();
	Criteria criteria1 = example1.createCriteria();
	criteria1.andParentIdEqualTo(parentId);
	return  itemCatMapper.selectByExample(example1);		
}

前台代码

  • 修改itemCatService.js

      //根据上级ID查询下级列表
    this.findByParentId=function(parentId){
    return $http.get('../itemCat/findByParentId.do?parentId='+parentId);	
    

    }

  • 修改itemCatController.js

     //根据上级ID显示下级列表 
    $scope.findByParentId=function(parentId){
      itemCatService.findByParentId(parentId).success(
      	function(response){
      		$scope.list=response;
      	}			
      );} 
    
  • 修改item_cat.html

引入JS
< script type=“text/javascript” src="…/plugins/angularjs/angular.min.js"> < /script>
< script type=“text/javascript” src="…/js/base.js"> </ script>
< script type=“text/javascript” src="…/js/service/itemCatService.js"> < /script>
< script type=“text/javascript” src="…/js/controller/baseController.js"> < /script>
< script type=“text/javascript” src="…/js/controller/itemCatController.js"> < /script>
指令定义
< body class=“hold-transition skin-red sidebar-mini” ng-app=“pinyougou” ng-controller=“itemCatController” ng-init=“findByParentId(0)” >
循环列表
< tr ng-repeat=“entity in list”>
< td>< input type=“checkbox” >< /td>
< td>{{entity.id}}< /td>
< td>{{entity.name}}< /td>
< td>{{entity.typeId}}< /td>
< td class=“text-center”>
< button type=“button” class=“btn bg-olive btn-xs” ng-click=“findByParentId(entity.id)”>查询下级< /button>
< button type=“button” class=“btn bg-olive btn-xs” data-toggle=“modal” data-target="#editModal" >修改< /button>
< /td>
< /tr>

面包屑导航

修改itemCatController

$scope.grade=1;//默认为1级	
//设置级别
$scope.setGrade=function(value){
	$scope.grade=value;
}		
//读取列表
$scope.selectList=function(p_entity){			
	if($scope.grade==1){//如果为1级
		$scope.entity_1=null;	
		$scope.entity_2=null;
	}		
	if($scope.grade==2){//如果为2级
		$scope.entity_1=p_entity;	
		$scope.entity_2=null;
	}		
	if($scope.grade==3){//如果为3级
		$scope.entity_2=p_entity;		
	}		
	$scope.findByParentId(p_entity.id);	//查询此级下级列表
}

修改列表的查询下级按钮,设定级别值后 显示列表

ng-if指令用于条件判断

<span ng-if="grade!=3">	                                     
	<button type="button" class="btn bg-olive btn-xs" ng-click="setGrade(grade+1);selectList(entity)">查询下级</button> 		                                     
</span>

绑定面包屑

<ol class="breadcrumb">	                        	
  <li><a href="#" ng-click="grade=1;selectList({id:0})">顶级分类列表</a></li>
   <li><a href="#" ng-click="grade=2;selectList(entity_1)">{{entity_1.name}}</a></li>
   <li><a href="#" ng-click="grade=3;selectList(entity_2)">{{entity_2.name}}</a></li>
</ol>

FastDFS简介

  • FastDFS 是用 c 语言编写的一款开源的分布式文件系统。FastDFS 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
    FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。
    Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。
    Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。
    在这里插入图片描述 服务端两个角色:
    Tracker:管理集群,tracker 也可以实现集群。每个 tracker 节点地位平等。收集 Storage 集群的状态。
    Storage:实际保存文件 Storage 分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念。

文件上传流程

在这里插入图片描述

文件下载流程

FastDFS入门小Demo

引入依赖

  <dependency>
    <groupId>org.csource.fastdfs</groupId>
    <artifactId>fastdfs</artifactId>
    <version>1.2</version>
</dependency>

引入fastDFS的配置文件fdfs_client.conf ,将其中的服务器地址设置为192.168.25.133,默认端口号为22122

//......
tracker_server=192.168.25.133:22122
//......

创建java类

    // 1、加载配置文件,配置文件中的内容就是 tracker 服务的地址。
	ClientGlobal.init("D:/maven_work/fastDFS-demo/src/fdfs_client.conf");
	// 2、创建一个 TrackerClient 对象。直接 new 一个。
	TrackerClient trackerClient = new TrackerClient();
	// 3、使用 TrackerClient 对象创建连接,获得一个 TrackerServer 对象。
	TrackerServer trackerServer = trackerClient.getConnection();
	// 4、创建一个 StorageServer 的引用,值为 null
	StorageServer storageServer = null;
	// 5、创建一个 StorageClient 对象,需要两个参数 TrackerServer 对象、StorageServer 的引用
	StorageClient storageClient = new StorageClient(trackerServer, storageServer);
	// 6、使用 StorageClient 对象上传图片。
	//扩展名不带“.”
	String[] strings = storageClient.upload_file("D:/pic/benchi.jpg", "jpg",
			null);
	// 7、返回数组。包含组名和图片的路径。
	for (String string : strings) {
		System.out.println(string);
	}
	//控制台输出以下结果:
	group1
    M00/00/00/wKgZhVkMP4KAZEy-AAA-tCf93Fo973.jpg
    //浏览器中输入:
    http://192.168.25.133/group1/M00/00/00/wKgZhVkMP4KAZEy-AAA-tCf93Fo973.jpg

MVC上传文件:angularjs+FastDFS+MVC

1、pinyougou-common工程pom.xml引入依赖
	<dependency>
	    <groupId>org.csource.fastdfs</groupId>
	    <artifactId>fastdfs</artifactId>
	</dependency>
	<dependency>
		<groupId>commons-fileupload</groupId>
		<artifactId>commons-fileupload</artifactId>
	</dependency>	

2、将FastDFS的工具类拷贝到此工程当中;
3、pinyougou-shop-web工程中引入pnyougou-common依赖;

4、将“资源/fastDFS/配置文件”文件夹中的 fdfs_client.conf 拷贝到pinyougou-shop-web工程config文件夹;

5、在pinyougou-shop-web工程application.properties添加配置:

    FILE_SERVER_URL=http://192.168.25.133/
    
6、在pinyougou-shop-web工程springmvc.xml添加配置:

<!-- 配置多媒体解析器 -->
<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>

后端代码之控制层,创建一个UploadController

package com.pinyougou.shop.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import entity.Result;
import util.FastDFSClient;
/**
 * 文件上传Controller
 * @author Administrator
 *
 */
@RestController
public class UploadController {

@Value("${FILE_SERVER_URL}")
private String FILE_SERVER_URL;//文件服务器地址

@RequestMapping("/upload")
public Result upload( MultipartFile file){				
	//1、取文件的扩展名
	String originalFilename = file.getOriginalFilename();
	String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
	try {
//2、创建一个 FastDFS 的客户端
		FastDFSClient fastDFSClient  
= new FastDFSClient("classpath:config/fdfs_client.conf");
		//3、执行上传处理
		String path = fastDFSClient.uploadFile(file.getBytes(), extName);
		//4、拼接返回的 url 和 ip 地址,拼装成完整的 url
		String url = FILE_SERVER_URL + path;			
		return new Result(true,url);			
	} catch (Exception e) {
		e.printStackTrace();
		return new Result(false, "上传失败");
	}		
}	
}

前端代码之service

在pinyougou-shop-web工程创建uploadService.js

//文件上传服务层
app.service("uploadService",function($http){
this.uploadFile=function(){
	var formData=new FormData();
    formData.append("file",file.files[0]);   
	return $http({
        method:'POST',
        url:"../upload.do",
        data: formData,
        headers: {'Content-Type':undefined},
        transformRequest: angular.identity
    });		
}	
});
anjularjs对于post和get请求默认的Content-Type header 是application/json。通过设置‘Content-Type’: undefined,这样浏览器会帮我们把Content-Type 设置为 multipart/form-data.

通过设置 transformRequest: angular.identity ,anjularjs transformRequest function 将序列化我们的formdata object.
  • 将uploadService服务注入到goodsController 中;

goodsController上传图片:

/**
 * 上传图片
 */
$scope.uploadFile=function(){	  
	uploadService.uploadFile().success(function(response) {        	
    	if(response.success){//如果上传成功,取出url
    		$scope.image_entity.url=response.message;//设置文件地址
    	}else{
    		alert(response.message);
    	}
    }).error(function() {           
    	     alert("上传发生错误");
    });        
};    

图片回显:

<div class="modal-body">			
		<table class="table table-bordered table-striped">
	      	<tr>
	      		<td>颜色</td>
	      		<td><input  class="form-control" placeholder="颜色" ng-model="image_entity.color">  </td>
	      	</tr>			    
	      	<tr>
	      		<td>商品图片</td>
	      		<td>
					<table>
						<tr>
							<td>
							<input type="file" id="file" />				                
				                <button class="btn btn-primary" type="button" ng-click="uploadFile()">
			                   		上传
				                </button>	
				            </td>
							<td>
								<img  src="{{image_entity.url}}" width="200px" height="200px">
							</td>
						</tr>						
					</table>
	      		</td>
	      	</tr>		      	
		 </table>			
	</div>

修改新建按钮

    <button type="button" class="btn btn-default" title="新建" data-target="#uploadModal"  data-toggle="modal" ng-click="image_entity={}" ><i class="fa fa-file-o"></i> 新建</button> 

在goodsController增加方法:

$scope.entity={goods:{},goodsDesc:{itemImages:[]}};//定义页面实体结构
//添加图片列表
$scope.add_image_entity=function(){    	
    $scope.entity.goodsDesc.itemImages.push($scope.image_entity);
}

修改上传窗口的保存按钮

<button class="btn btn-success" ng-click="add_image_entity()" data-dismiss="modal" aria-hidden="true">保存</button>

遍历图片列表

<tr ng-repeat="pojo in entity.goodsDesc.itemImages">
 <td>{{pojo.color}}</td>
 <td><img alt="" src="{{pojo.url}}" width="100px" height="100px"></td>
<td><button type="button" class="btn btn-default" title="删除" ><i class="fa fa-trash-o"></i> 删除</button></td>
</tr>

删除图片

$scope.remove_image_entity=function(index){
	    $scope.entity.goodsDesc.itemImages.splice(index,1);
}
-- 调用remove_image_entity($index)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.2. 结构化一下 1.3. 图形化一下 1.3.1. 运营商后台 1.3.2. 商家后台 1.3.3. 网页前台 参考京东 2. 技术选型 前端:angularJS + Bootstrap 后台:SSM( springmvc+spring+mybatis) 数据库:mysql,使用mycat读写分离 开发模式:SOA 服务中间件:dubbox,需要和zookeeper配合使用 注册中心:zookeeper 消息中间件:Activemq,使用spring-jms 负载均衡:nginx 搜索:solr集群(solrCloud),配合zookeeper搭建, 使用spring-data-solor 缓存:redis集群,使用spring-data-redis 图片存储:fastDFS集群 网页静态化:freemarker 单点登录:cas 权限管理:SpringSecurity, 跨域:cros 支付:微信扫描 短信验证:阿里大于 密码加密:BCrypt 富文本:KindEditor 事务:声明式事务 任务调度:spring task 所有的技术,都可能涉及到为什么用?怎么用?用的过程中有什么问题? 3. 框架搭建 3.1. 前端 理解baseControler.js、base.js、base_pagination.js,以及每一个xxxController.js里面都公共的了些什么。 baseControler.js 分页配置 列表刷新 处理checkBox勾选 xxxControler.js 自动生成增删改查 base_pagination.js 带分页 base.js 不带分页 3.2. dao 使用了mybatis逆向工程 4. 模块开发 逐个模块开发就好 4.1. 学会评估模块难不难 一个模块难不难从几方面考虑。 涉及几张表? 1,2张表的操作还是没有什么难度的。 涉及哪些功能? 增删改查,批量删除。 前端展示? 分页列表、树形、面包屑、三级联动、内容格式化。 4.2. 举几个简单模块的例子 4.2.1. 品牌管理 单表 分页、新增、删除、修改 4.2.2. 规格管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) 4.2.3. 模板管理 2张表 分页、新增、删除、修改、显示优化(显示列表内容的一部分) 4.2.4. 分类管理 单表 4.2.5. 商家审核 单表 4.3. 举一个复杂模块 4.3.1. 商品新增 需要插入3张表,tb_goods、tb_goods_desc、tb_item 前端:三级联动、富文本、图片上传、动态生成内容 4.3.2. 商品修改 需要从3张表获取数据,然后进行回显。 4.4. 典型模块设计 4.4.1. 管理后台 商品新增、商品修改 4.4.2. 前台页面 搜索模块实现 购物车模块实现 支付模块实现 秒杀模块实现 5. 开发过程中问题&优化 1.1. 登录 单点登录怎么实现 session怎么共享 1.2. 缓存 哪些场景需要用到redis redis存储格式的选择 怎么提高redis缓存利用率 缓存如何同步 1.3. 图片上传 图片怎么存储 图片怎么上传 1.4. 搜索 ​ 怎么实现 数据量大、 并发量高的搜索 怎么分词 1.5. 消息通知 ​ 哪些情况用到activeMq 1.6. 优化 seo怎么优化 怎么加快访问速度 1.7. 秒杀 ​ 怎么处理高并发 ​ 秒杀过程中怎么控制库存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值