业务逻辑。

OSS

通过断点续传上传的方式将文件上传到OSS前,您可以指定断点记录点。

上传过程中,如果出现网络异常或程序崩溃导致文件上传失败时,将从断点记录处继续上传未上传完成的部分。

参数

可以通过ossClient.uploadFile方法实现断点续传上传。此方法的uploadFileRequest请求包含的参数请参见下表。

参数描述
BucketName存储空间名称。
Key上传到OSS的文件名称。
UploadFile待上传的本地文件路径。
TaskNum上传并发线程数,默认值为1。
PartSize上传的分片大小,单位为Byte,取值范围为100 KB~5 GB。默认值为100 KB。
EnableCheckpoint是否开启断点续传功能,默认关闭。
CheckpointFile记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。如果未设置该值,默认与待上传的本地文件同路径,名称为${uploadFile}.ucp。
Callback使用上传回调。关于上传回调的更多信息,请参见Callback上传回调

示例

以下代码用于断点续传上传。

/// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "yourEndpoint";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。
meta.setContentType("text/plain");

// 文件上传时设置访问权限ACL。
// meta.setObjectAcl(CannedAccessControlList.Private);

// 通过UploadFileRequest设置多个参数。
// 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。
UploadFileRequest uploadFileRequest = new UploadFileRequest("examplebucket","exampleobject.txt");

// 通过UploadFileRequest设置单个参数。
// 填写Bucket名称。
//uploadFileRequest.setBucketName("examplebucket");
// 填写Object完整路径。Object完整路径中不能包含Bucket名称。
//uploadFileRequest.setKey("exampleobject.txt");
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
uploadFileRequest.setUploadFile("D:\\localpath\\examplefile.txt");
// 指定上传并发线程数,默认值为1。
uploadFileRequest.setTaskNum(5);
// 指定上传的分片大小。
uploadFileRequest.setPartSize(1 * 1024 * 1024);

// 开启断点续传,默认关闭。
uploadFileRequest.setEnableCheckpoint(true);
// 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中。
uploadFileRequest.setCheckpointFile("yourCheckpointFile");
// 文件的元数据。
uploadFileRequest.setObjectMetadata(meta);
// 设置上传成功回调,参数为Callback类型。
//uploadFileRequest.setCallback("yourCallbackEvent");

// 断点续传上传。
ossClient.uploadFile(uploadFileRequest);

// 关闭OSSClient。
ossClient.shutdown();            

分片处理

以下通过一个完整的示例对分片上传的流程进行逐步解析:

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
String endpoint = "yourEndpoint";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";

// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

// 创建InitiateMultipartUploadRequest对象。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);

// 如果需要在初始化分片时设置文件存储类型,请参考以下示例代码。
// ObjectMetadata metadata = new ObjectMetadata();
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// request.setObjectMetadata(metadata);

// 初始化分片。
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
// 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。
String uploadId = upresult.getUploadId();

// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
List<PartETag> partETags =  new ArrayList<PartETag>();
// 每个分片的大小,用于计算文件有多少个分片。单位为字节。
final long partSize = 1 * 1024 * 1024L;   //1 MB。

// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
final File sampleFile = new File("D:\\localpath\\examplefile.txt");
long fileLength = sampleFile.length();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
    partCount++;
}
// 遍历分片上传。
for (int i = 0; i < partCount; i++) {
    long startPos = i * partSize;
    long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
    InputStream instream = new FileInputStream(sampleFile);
    // 跳过已经上传的分片。
    instream.skip(startPos);
    UploadPartRequest uploadPartRequest = new UploadPartRequest();
    uploadPartRequest.setBucketName(bucketName);
    uploadPartRequest.setKey(objectName);
    uploadPartRequest.setUploadId(uploadId);
    uploadPartRequest.setInputStream(instream);
    // 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。
    uploadPartRequest.setPartSize(curPartSize);
    // 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,OSS将返回InvalidArgument错误码。
    uploadPartRequest.setPartNumber( i + 1);
    // 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。
    UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
    // 每次上传分片之后,OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
    partETags.add(uploadPartResult.getPartETag());
}


// 创建CompleteMultipartUploadRequest对象。
// 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
CompleteMultipartUploadRequest completeMultipartUploadRequest =
        new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);

// 如果需要在完成文件上传的同时设置文件访问权限,请参考以下示例代码。
// completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.PublicRead);

// 完成上传。
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
System.out.println(completeMultipartUploadResult.getETag());
// 关闭OSSClient。
ossClient.shutdown();

JWT

  1. JWT是由三段信息构成的,将这三段信息文本用。链接一起就构成了Jwt字符串。

    1. 头部(header)
    2. 载荷(payload, 就是具体内容)
    3. 签证(signature)
  2. jwt的头部承载两部分信息:

    1. 声明类型,这里是jwt
    2. 声明加密的算法 通常直接使用 hmac SHA256
  3. 签名

    1. header (base64后的)
    2. payload (base64后的)
    3. secret

shiro

Shiro 可以完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。其基本功能点

组件

Authentication:

​ 身份认证 / 登录,验证用户是不是拥有相应的身份;

Authorization:

​ 授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常 见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某 个权限;

Session Manager:

​ 会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;

Cryptography:

​ 加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web Support:

​ Web 支持,可以非常容易的集成到 Web 环境;

Caching:

​ 缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效 率;

Concurrency:shiro

​ 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing:

​ 提供测试支持;

Run As:

​ 允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me:

​ 记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

shiro以登录为例工作流

subject -> SecurityManager -> Authenticator ->JDBC Realm

  1. 首先通过 new IniSecurityManagerFactory 并指定一个 ini 配置文件来创建一个 SecurityManager 工厂;

  2. 接着获取 SecurityManager 并绑定到 SecurityUtils,这是一个全局设置,设置一次即可;
    通过 SecurityUtils 得到 Subject,其会自动绑定到当前线程;如果在 web 环境在请求结束时需要解除绑定;然后获取身份验证的 Token,如用户名 / 密码;
    调用 subject.login 方法进行登录,其会自动委托给 SecurityManager.login 方法进行登录;

  3. 如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如: DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)、UnknownAccountException(错误的帐号)、ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException (错误的凭证)、ExpiredCredentialsException(过期的凭证)等,

  4. 具体请查看其继承关系;对于页面的错误消息展示,最好使用如 “用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;
    最后可以调用 subject.logout 退出,自动委托给 SecurityManager.logout 方法退出。

评论

  1. 数据库设计

评论表:id 资源id(动态、资讯等) type(1.自评 2.别人评论) content(评论内容) 状态 时间 用户id

评论回复表:id parentid (评论表的id) type(1.回复评论 2.回复的是回复) 回复id 回复的内容 用户id 目标用户id(回复的是评论,那就是这个评论的用户id,如果回复的是回复,那就是这个回复的用户id) 时间

评论点赞表:id 评论或回复的id type(1.评论点赞 2.回复点赞) 用户id 时间

  1. 接口设计

https restful

  1. 技术选型

并发型:redis(缓存热点评论)+RabbitMQ(同步)+Mysql 微服务

  1. 业务逻辑

    1.发布评论:实现作品的评论的发布

    ​ 1.校验 参数、登陆

    ​ 2.评论内容进行文本审核

    ​ 3.审核通过,校验Redis,是否存在评论的缓存

    ​ 4.存在缓存,操作缓存,发送MQ消息,监听消息,实现数据库的同步

    ​ 5.缓存不存在,操作数据库,不做缓存

    ​ Redis—Hash类型–一个作品(动态)就是一个Hash集合,field:评论id-回复id value:评论的 内容(回复的内容)–有效期24小时

  2. 发布回复:

    1.校验 参数、登陆

    2.评论内容进行文本审核

    3.审核通过,校验Redis,是否存在评论的缓存

    4.存在缓存,操作缓存,发送MQ消息,监听消息,实现数据库的同步

    5.缓存不存在,操作数据库,不做缓存

Redis—Hash类型–一个作品(动态)就是一个Hash集合,field:评论id-回复id value:评论的内容(回复的内容)–有效期24小时

  1. 查询评论:分页加载一级评论

    点赞/取消点赞评论:

    Redis–缓存–Hash 高频点赞行为 field:用户id:评论id val:0(取消)或者1(点赞)

    1.验证参数

    2.校验缓存

    3.存在,更改值,数据同步(MQ—Mysql,定时任务,间隔10分钟)

    4.不存在,操作数据库,同时更新缓存(下一次操作速度更快)

并发量不高:直接操作数据库,1.查询点赞2.存在就删除,不存在就新增

还可以前端伪处理点赞行为,点赞的时候只记录js信息,不请求接口,等前端页面切换时,请求接口,一次性提交数据

Redis实现缓存的方式:(不频繁修改,频繁访问)

1.热点数据缓存 使用就是热

只要使用,就校验缓存是否存在,存在就找缓存,不存在就找数据库,更新缓存,有效期2小时,有效期内不操作数据同步

2.新数据缓存 根据时间,只为新的做缓存–我们采用

后台系统审核通过,自动实现缓存,缓存有效期设置为24小时。在这期间所有相关的操作都是落到缓存中,需要实现数据同步(Redis—Mysql 可以使用定时任务,也可以使用MQ)

5.4 编码

结合你的技术选型,实现对应接口的业务逻辑的流程图

1.发布评论

2.发布回复

3.点赞接口

优惠券

需求的分析

实现系统的促销业务,优惠劵设置–都是通过后台系统–需要审核—通过才可以展示

优惠券的发放类型

1.需要领取

2.系统自发(简单,没有限制,也不需要用户去抢)

功能列表:

1.可领取的优惠劵列表–查询

2.我的优惠劵–查询

3.领取优惠劵–重点-新增

4.商品(商铺)可用的优惠劵

5.订单预览-可用的优惠劵(优惠劵同类型不可叠加)

6.我的优惠记录(用过的优惠劵,省钱秘籍)

3.3 设计

1.数据库设计

1.优惠劵活动表():id type(1.平台 2.品类 3.商品) count name ctime flag sdate

2.优惠劵表(t_coupon):id name aid money(优惠金额或者折扣) stock(库存量) minmoney(使用最小金额) type(类型1.金钱 2.折扣) endtime ctime

3.用户优惠劵表:id uid cid flag ctime source(来源,为什么给优惠劵)

4.用户优惠券抵扣表:id ucid oid count ctime flag

2.接口设计

开发规范、https、restful

3.功能接口业务

1.查询可领取优惠劵–入口

1.店铺

​ 店铺首页–请求店铺的优惠劵

2.商品详情页

​ 优惠劵信息:1.商品优惠劵 2.品类优惠劵 3.店铺优惠劵

3.领卷中心

​ 1.平台优惠劵

​ 2.品类优惠劵

​ 3.单品优惠劵

2.领取优惠劵

​ 1.校验用户资格

​ 2.上锁(分布式锁-Redisson-RLock(优惠劵id))

​ 3.读取缓存(没有读数据库,有就使用缓存)

​ 4.校验库存

​ 5.领取,领取成功(Redis—更新缓存数量,更新数据库(MQ))

思考点:为什么加缓存,怎么加?

缓存数据(1.后台优惠劵审核成功,自动做缓存 2.使用的时候进行缓存,每种优惠劵,第一个人领取时,稍微会慢一些)

购物车

  1. 价格变动

  2. 相似推荐

  3. 商品的价格以下单为准

  4. 加购方式:登录加购,不登录加购

  5. 并发:

    ​ 不高:直接走MySQL

    ​ 高:Redis+RabbitMQ

  6. 购物车的查询

    多表联查,8张表以上。

    购物车表(上限),

  7. 对购物车左缓存

    设置有效期:

    数据类型选择:

    ​ 小并发用hash

    ​ 高并发用SortSet

    客户端:(微服务:Redission单体项目Jedis)

订单

来源:商品列表,秒杀,促销

秒杀

订单不走购物车,直接结算

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值