首页 > 代码库 > fastdfs分布式文件系统之与dubbo整合实现分布式服务接口
fastdfs分布式文件系统之与dubbo整合实现分布式服务接口
fastdfs是开源的轻量级分布式文件系统,它提供了java版本的client api。通过client API可以实现对文件的上传、追加、下载、删除等功能。
为了避免每个应用都配置fasdtfs参数、读取配置文件、调用client api获取trackerServer和StorageServer进行上传、下载、删除等操作及返回结果的
处理。所以采用与dubbo整合,提供分布式服务接口,来简化其它服务和应用的文件操作处理,同时提高代码的复用性。
1.总体结构
如图,总共分为fastdfs-api、fastdfs-consumer、fastdfs-provider三个工程。
fastdfs-api:对外提供的接口、dto的定义;
fastdfs-provider:调用fastdfs java client api对外提供的上传、下载、删除等接口实现以及对外暴露dubbo接口;
fastdfs-consumer:调用远程接口,测试上传、下载、删除功能;
其中fastdfs-consumer、fastdfs-provider需要依赖fastdfs-api的jar包。
2.fastdfs-api
对外提供的接口、dto的定义,下图是代码结构图:
UploadFileDto是上传文件时需传入的dto里面包含了文件的字节数组、文件后缀名、文件访问类型等等信息。从图中我们可以看到resultDto、UploadFileDto等dto。其中resultDto是上传、删除、下载返回结果dto,里面包含了结果状态、错误信息及文件地址等等信息
在enums包里面的LinkType是一个枚举类,定义连接类型。里面定义了内网访问和外网访问两个类型。
在exception包里面的AppException,内部异常类定义。
service包里面的CommonUploadFileService接口,里面定义了上传和删除功能的接口,代码如下:
/** * * @ClassName: CommonUploadFileService * @Description: 公共文件上传业务逻辑层接口 * @author mr_smile mr_smile@xxxx.com * */ public interface CommonUploadFileService { /** * 上传文件 * * @param uploadFileDto * 上传文件dto * @return */ public ResultDto uploadFile(UploadFileDto uploadFileDto) throws AppException; /** * 删除远程文件 * * @param filePath * 文件远程地址 * @return */ public void deleteFile(String filePath) throws AppException; }
3.fastdfs-provider调用fastdfs java client api对外提供的上传、下载、删除等接口实现以及对外暴露dubbo接口,在该工程中需要导入fastdfs-api的包。
代码结构如下图所示:
图中我们看到有exception、pool和impl等包及相关的配置文件。
包代码介绍:
在exception中,ERRORS枚举类主要是对在调用接口时可能出现的错误的定义,代码如下:
public enum ERRORS { PARAMETER_IS_NULL("21001", "必填参数为空", "必填参数为空"), FASTDFS_CONNECTION_FAIL("21002", "连接fastdfs服务器失败", "文件上传异常,请重试"), WAIT_IDLECONNECTION_TIMEOUT("21003", "等待空闲连接超时", "连接超时,请重试"), NOT_EXIST_GROUP("21004", "文件组不存在", "文件组不存在"), UPLOAD_RESULT_ERROR("21005", "fastdfs文件系统上传返回结果错误", "文件上传异常,请重试"), NOT_EXIST_PORTURL("21006", "未找到对应的端口和访问地址", "文件上传异常,请重试"), SYS_ERROR("21007", "系统错误", "系统错误"), FILE_PATH_ERROR("2108", "文件访问地址格式不对","文件访问地址格式不对"), DELETE_RESULT_ERROR("21009", "fastdfs文件系统删除文件返回结果错误", "文件删除异常,请重试"), NOT_EXIST_FILE("21010", "文件不存在", "文件不存在"); /** 错误码 */ String code; /** 错误信息,用于日志输出,便于问题定位 */ String message; /** 错误提示,用于客户端提示 */ String descreption; ERRORS(String code, String message) { this.message = message; this.code = code; } ERRORS(String code, String message, String descreption) { this.message = message; this.code = code; this.descreption = descreption; } public AppException ERROR() { return new AppException("FASTDFS", this.code, this.message, this.descreption); } public AppException ERROR(String descreption) { return new AppException("FASTDFS", this.code, this.message, descreption); } }
pool包中的类主要实现连接池,提高程序的性能,在之前的代码中有所介绍。impl包中的CommonUploadFileServiceImpl类上传和删除功能的接口的实现,代码如下:
/** * 公共上传文件服务接口实现类 * * @author mr_smile * */ @Service("commonUploadFileService") public class CommonUploadFileServiceImpl implements CommonUploadFileService { /** 日志 */ private final Logger log = Logger .getLogger(CommonUploadFileServiceImpl.class); /** fastdfs工具类 */ @Autowired private FastDfsUtil fastDfsUtil; /** * 上传文件 * * @param uploadFileDto * 上传文件dto * @return */ @Override public ResultDto uploadFile(UploadFileDto uploadFileDto) throws AppException { /** 日志标识 */ String logId = UUID.randomUUID().toString(); log.info("[上传文件(uploadFile)][" + logId + "][prams:uploadFileDto=" + uploadFileDto.toString() + "]"); try { /** 判断参数是否为空 */ vlidParamIsNull(uploadFileDto, logId); /** 调用工具类上传 */ ResultDto result = fastDfsUtil.upload(uploadFileDto); log.info("[上传文件(uploadFile)-返回结果][" + logId + "][results:resultDto=" + result.toString() + "]"); return result; } catch (AppException e) { log.error("[上传文件(uploadFile)][" + logId + "][异常:" + e + "]"); throw e; } } /** * 删除fastdfs服务器中文件 * * @param filePath * 文件远程地址 * @return */ public void deleteFile(String filePath) throws AppException { /** 日志标识 */ String logId = UUID.randomUUID().toString(); log.info("[ 删除文件(deleteFile)][" + logId + "][parms:filePath=" + filePath + "]"); try { if (StringUtils.isBlank(filePath)) { throw ERRORS.PARAMETER_IS_NULL.ERROR(); } /** 解析文件路径 */ String[] results = CommonUtils.parseFilePath(filePath, logId); /** 删除文件 */ fastDfsUtil.deleteFile(results[0], results[1]); } catch (AppException e) { log.error("[ 删除文件(deleteFile)][" + logId + "][异常:" + e + "]"); throw e; } } /** * * @Description: 验证上传方法参数是否为空 * @param uploadFileDto * @param logId * */ public void vlidParamIsNull(UploadFileDto uploadFileDto, String logId) throws AppException { log.info("[验证上传方法参数是否为空(vlidParamIsNull)][" + logId + "][prams:uploadFileDto=" + uploadFileDto.toString() + "]"); if (null == uploadFileDto || uploadFileDto.getFileBytes() == null || null == uploadFileDto.getFileExtName()) { throw ERRORS.PARAMETER_IS_NULL.ERROR(); } } }ServiceMainTest类设置dubbo参数及加载spring容器,代码如下:
/** * * @ClassName: ServiceMainTest * @Description: TODO(这里用一句话描述这个类的作用) * @author mr_smile mr_smile@xxxxx.com * */ public class ServiceMainTest { public static void main(String[] args) throws Exception { // 设在dubbo参数 System.setProperty("dubbo.application.name", "payment-fastdfs"); System.setProperty("dubbo.registry.address", "zookeeper://192.168.6.41:2181"); System.setProperty("dubbo.protocol.port", "8080"); // 加载spring容器 @SuppressWarnings("resource") ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "classpath:applicationContext-provider.xml"); context.start(); System.out.println("Press any key to exit."); System.in.read(); } }
配置文件介绍:
applicationContext-provider.xml:对外暴露接口
<import resource="classpath*:applicationContext.xml"/> <dubbo:protocol name="hessian"/> <dubbo:service ref="commonUploadFileService" interface="com.fastdfs.service.CommonUploadFileService" timeout="1200000"/> applicationContext.xml:对bean、参数文件的定义: <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:property.properties</value> </list> </property> </bean> <bean name="connectionPool" class="com.fastdfs.pool.FastDfsUtil" init-method="init"> <property name="minPoolSize" value=http://www.mamicode.com/"${minPoolSize}" />>fastdfs_client.conf对fastdfs所需参数的定义:
connect_timeout = 10 network_timeout = 30 charset = UTF-8 http.anti_steal_token = no tracker_server = ip1:22122,ip2:22122 secret_key="";property.properties对组、端口、访问地址、连接池等相关配置:
#内网组名 INTRANET_GROUP=group2 #外网组名 OUTERNET_GROUP=group1 #虚拟访问地址 LINEK_URL=http://www.xxx.com #内网端口 LINKE_INTRANET_PORT=800 #外网端口 LINKE_OUTERNET_PORT=801 #连接池最大连接数 maxPoolSize=30 #等待时间(单位:秒) waitTimes=400 #连接池最小连接数 minPoolSize=204.fastdfs-consumer
调用远程接口,测试上传、下载、删除功能。
上面的demo是全部是拷贝所有的jar包放入到工程里面的,在实际的开发中建议采用maven。hessian的依赖配置如下:
MainTest类测试调用远程dubbo接口进行上传,上传成功后,线程睡眠2秒后执行删除操作。代码如下:
public static void main(String[] args) { try { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "applicationConsumer.xml" }); CommonUploadFileService commonUploadFileService = (CommonUploadFileService) context .getBean("commonUploadFileService"); File file = new File("D:\\data\\1.jpg"); UploadFileDto udto = new UploadFileDto(); try { byte[] bytes = MainTest.getByte(file); udto.setFileBytes(bytes); udto.setFileExtName("jpg"); udto.setLinkType(LinkType.INTRANET); //上传文件 ResultDto dto = commonUploadFileService.uploadFile(udto); System.out.println("上传:filePath:" + dto.getFilePath()); Thread.sleep(2000); //删除文件 commonUploadFileService.deleteFile(dto.getFilePath()); } catch (AppException e) { System.out.println(e.toString()); } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } public static byte[] getByte(File file) throws Exception { byte[] bytes = null; if (file != null) { InputStream is = new FileInputStream(file); int length = (int) file.length(); if (length > Integer.MAX_VALUE) // 当文件的长度超过了int的最大值 { System.out.println("this file is max "); return null; } bytes = new byte[length]; int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { offset += numRead; } // 如果得到的字节长度和file实际的长度不一致就可能出错了 if (offset < bytes.length) { System.out.println("file length is error"); return null; } is.close(); } return bytes; } }配置文件applicationConsumer.xml,需调用的远程接口bean的定义。配置如下:
<dubbo:application name="consumer-of-helloworld-app" /> <!-- 使用multicast广播注册中心暴露发现服务地址 --> <dubbo:registry protocol="hessian" address="zookeeper://192.168.6.41:2181" timeout="60000" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id="commonUploadFileService" interface="com.fastdfs.service.CommonUploadFileService" retries="0" timeout="100000"/> <dubbo:reference id="commonDowenloadFileService" interface="com.fastdfs.service.CommonDownloadFileService" retries="0" timeout="60000"/> </beans>在dubbo中默认使用的protocol为dubbo,在这种方式下,只能上传2M以内的文件,为了能解决传输大文件,那么需改为使用hessian协议。
<dependency> <groupId>com.caucho</groupId> <artifactId>hessian</artifactId> <version>4.0.7</version> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty</artifactId> <version>6.1.22</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.mortbay.jetty</groupId> <artifactId>jsp-2.1-jetty</artifactId> <version>6.1.22</version> <scope>provided</scope> </dependency>
注:所有代码已打包上传到我的资源库,有需要的可以前往下载。地址:http://download.csdn.net/detail/mr_smile2014/9629476
---------------------------------------------------------------------------版权声明-----------------------------------------------------------------------------------------------
版权声明:本文为博主原创文章,未经博主允许不得转载。本文地址:http://blog.csdn.net/mr_smile2014/article/details/52526065
fastdfs分布式文件系统之与dubbo整合实现分布式服务接口