网站建设调研报告,高仿微博wordpress,天津企业网站开发,做彩票网站模板1 完善实名认证功能
1.1 实名认证分布式事务问题
1.1.1 问题分析
在昨天的实名认证代码中#xff0c;审核完毕后添加 id5的演示异常#xff0c;重新使用postman进行测试, 会发现 出现异常后 本地方法因为有
Transactional注解 对ap_user ap_user_realname的操作会回滚
而…1 完善实名认证功能
1.1 实名认证分布式事务问题
1.1.1 问题分析
在昨天的实名认证代码中审核完毕后添加 id5的演示异常重新使用postman进行测试, 会发现 出现异常后 本地方法因为有
Transactional注解 对ap_user ap_user_realname的操作会回滚
而 基于Feign远程调用 article服务 wemedia服务 确没有回滚
这时我们的代码 存在分布式事务问题传统的数据库事务无法解决 1.1.2 seata快速回顾
Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务为用户打造一站式的分布式解决方案。
官网地址http://seata.io/其中的文档、播客中提供了大量的使用说明、源码分析。
Seata事务管理中有三个重要的角色 TC (Transaction Coordinator) - 事务协调者维护全局和分支事务的状态协调全局事务提交或回滚。 TM (Transaction Manager) - 事务管理器定义全局事务的范围、开始全局事务、提交或回滚全局事务。 RM (Resource Manager) - 资源管理器管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚。 整体的架构如图 Seata基于上述架构提供了四种不同的分布式事务解决方案 XA模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入 TCC模式最终一致的分阶段事务模式有业务侵入 AT模式最终一致的分阶段事务模式无业务侵入也是Seata的默认模式 SAGA模式长事务模式有业务侵入
无论哪种方案都离不开TC也就是事务的协调者。 Seata AT模式 阶段一RM的工作 - 注册分支事务 - 记录undo-log数据快照 - 执行业务sql并提交 - 报告事务状态
阶段二提交时RM的工作 - 删除undo-log即可
阶段二回滚时RM的工作 - 根据undo-log恢复数据到更新前 1.1.3 项目集成seata 记得Springboot seata用1.6.1版本低版本会报错
准备seata数据库
导入资料中的seata.sql
docker部署seata TC
如果使用docker安装 registry 默认使用 file 模式 存储事务数据
docker run --name seata --restartalways -p 8091:8091 -e SEATA_IP192.168.200.130 -e SEATA_PORT8091 -v seata-config:/seata-server/resources -id seataio/seata-server:1.4.2
我们使用nacos作为seata的配置和注册中心方便以后的高可用 及 统一的配置管理
在seata命名空间 创建配置seataServer.properties 分组为: SEATA_GROUP 1.1.3 项目集成seata
准备seata数据库
导入资料中的seata.sql
docker部署seata TC
如果使用docker安装 registry 默认使用 file 模式 存储事务数据
docker run --name seata --restartalways -p 8091:8091 -e SEATA_IP192.168.200.130 -e SEATA_PORT8091 -v seata-config:/seata-server/resources -id seataio/seata-server:1.4.2
我们使用nacos作为seata的配置和注册中心方便以后的高可用 及 统一的配置管理
在seata命名空间 创建配置seataServer.properties 分组为: SEATA_GROUP # 数据存储方式db代表数据库 store.modedb store.db.datasourcedruid store.db.dbTypemysql store.db.driverClassNamecom.mysql.jdbc.Driver store.db.urljdbc:mysql://192.168.200.130:3306/seata?useUnicodetruerewriteBatchedStatementstrue store.db.userroot store.db.passwordroot store.db.minConn5 store.db.maxConn30 store.db.globalTableglobal_table store.db.branchTablebranch_table store.db.queryLimit100 store.db.lockTablelock_table store.db.maxWait5000 # 事务、日志等配置 server.recovery.committingRetryPeriod1000 server.recovery.asynCommittingRetryPeriod1000 server.recovery.rollbackingRetryPeriod1000 server.recovery.timeoutRetryPeriod1000 server.maxCommitRetryTimeout-1 server.maxRollbackRetryTimeout-1 server.rollbackRetryTimeoutUnlockEnablefalse server.undo.logSaveDays7 server.undo.logDeletePeriod86400000
# 客户端与服务端传输方式 transport.serializationseata transport.compressornone # 关闭metrics功能提高性能 metrics.enabledfalse metrics.registryTypecompact metrics.exporterListprometheus metrics.exporterPrometheusPort9898 修改seataTC配置
准备好nacos配置中心后修改seata TC端 使用nacos作为配置中心
# 进入到挂载目录
cd /var/lib/docker/volumes/seata-config/_data
# 修改注册中心配置
vi registry.conf
配置中内容:
registry {# tc服务的注册中心类这里选择nacos也可以是eureka、zookeeper等type nacosnacos {# seata tc 服务注册到 nacos的服务名称可以自定义 spring.application.nameapplication seata-tc-serverserverAddr 192.168.200.130:8848group SEATA_GROUPnamespace seatacluster SHusername nacospassword nacos}
}
config {# 读取tc服务端的配置文件的方式这里是从nacos配置中心读取这样如果tc是集群可以共享配置type nacos# 配置nacos地址等信息nacos {serverAddr 192.168.200.130:8848namespace seatagroup SEATA_GROUPusername nacospassword nacosdataId seataServer.properties}
}
修改后 记得重启seata
注意检查 mysql中是否准备了seata库哦~~ 微服务配置seata
配置步骤参考官网
创建日志表undo_log (已创建)
分别在leadnews_user、leadnews_article、leadnews_wemedia三个库中都创建undo_log表
创建seata共享配置
在配置中心nacos 的 dev 环境中 创建share-seata.yml
seata:registry: # TC服务注册中心的配置微服务根据这些信息去注册中心获取tc服务地址# 参考tc服务自己的registry.conf中的配置type: nacosnacos: # tcserver-addr: ${spring.profiles.ip}:8848namespace: seatagroup: SEATA_GROUPapplication: seata-tc-server # tc服务在nacos中的服务名称tx-service-group: seata-demo # 事务组根据这个获取tc服务的cluster名称service:vgroup-mapping: # 事务组与TC服务cluster的映射关系seata-demo: SH 修改微服务
参与分布式事务的微服务 ( leadnews-user、leadnews-wemedia、leadnews-article)引入依赖
dependencies!--seata--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusions!--版本较低1.3.0因此排除--exclusionartifactIdseata-spring-boot-starter/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactId!--seata starter 采用1.4.2版本--version${seata.version}/version/dependency/dependencies
修改bootstrap.yml配置
以 leadnews-user服务为例 其它一样
spring:application:name: leadnews-user # 服务名称profiles:active: dev # 开发环境配置ip: 192.168.200.130 # 环境ip地址cloud:nacos:discovery: # 注册中心地址配置server-addr: ${spring.profiles.ip}:8848namespace: ${spring.profiles.active}config: # 配置中心地址配置server-addr: ${spring.profiles.ip}:8848namespace: ${spring.profiles.active}file-extension: yml # data-id 后缀name: ${spring.application.name} # data-id名称shared-configs: # 共享配置- data-id: share-feign.yml # 配置文件名-Data Idgroup: DEFAULT_GROUP # 默认为DEFAULT_GROUPrefresh: false # 是否动态刷新默认为false- data-id: share-seata.yml # 配置文件名-Data Idgroup: DEFAULT_GROUP # 默认为DEFAULT_GROUPrefresh: false # 是否动态刷新默认为fals
管理事务加全局事务注解
在实名认证审核的方法上加上seata提供的全局事务管理注解 GlobalTransactional 注解 开启全局事务 测试分布式事务
再次通过postman测试使用认证审核接口查看出现异常时 事务是否回滚
注意字段为tinyind的数据长度不要设为1不然大于0都默认值为true就不会回滚了 1.2 扩展 - 网关knife4j实现聚合文档
见扩展资料
1.3 扩展 - AI实名认证方案
见扩展资料
2 云存储解决方案-阿里云OSS
2.1 阿里云OSS简介
2.4 OSS starter工具封装
1heima-leadnews-basic 模块在当前模块下创建 heima-file-spring-boot-starter子模块
添加依赖
dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-autoconfigure/artifactId/dependency!--OSS--dependencygroupIdcom.aliyun.oss/groupIdartifactIdaliyun-sdk-oss/artifactIdversion3.10.2/version/dependencydependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion21.0/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency
/dependencies
2创建包com.heima.file
资料文件夹下导入 service和 config包下的内容:
结构如下: 3在resources目录下新建 META-INF/spring.factories 配置文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration\com.heima.file.service.impl.OSSAliyunFileStorageService
4wemedia-service 添加OSS配置 wemedia-service 添加依赖 dependencyartifactIdheima-file-spring-boot-starter/artifactIdgroupIdcom.heima/groupIdversion1.0-SNAPSHOT/version/dependency
配置中心nacos添加 share-file.yml 共享配置
#OSS配置
file:oss:bucket-name: 替换成自己的access-key-id: 替换成自己的 access-key-secret: 替换成自己的endpoint: oss-cn-shanghai.aliyuncs.comweb-site: 替换成自己的proxy-username: aliyun-sdk-javasocket-timeout: 10000idle-connection-time: 10000connection-request-timeout: 4000max-connections: 2048max-error-retry: 5white-list: 127.0.0.1connection-timeout: 10000prefix: material
bucket就是我们刚刚申请的在它的概览页面 有对应的外网访问地址前缀贴到配置中 记得加上http://开头 和 斜杠结尾哦
bootstrap.yml 新增共享配置
spring:cloud:nacos:config: # 配置中心地址配置shared-configs: # 共享配置- data-id: share-file.yml # 配置文件名-Data Idgroup: DEFAULT_GROUP # 默认为DEFAULT_GROUPrefresh: false # 是否动态刷新默认为false
5在 wemedia-service 中新建测试类测试OSS工具类
package com.heima.wemedia;
import com.heima.file.service.FileStorageService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/*** Description:* Version: V1.0*/
SpringBootTest(classes WemediaApplication.class)
RunWith(SpringRunner.class)
public class OssTest {
AutowiredFileStorageService fileStorageService;Value(${file.oss.web-site})String webSite;
Testpublic void testFileUpload() throws Exception {
// FileInputStream inputStream new FileInputStream(new File(/Users/Ares/Desktop/temp/banner1.jpg));
// String wemedia fileStorageService.store(upload, aaa1.jpg, inputStream);
// System.out.println(webSitewemedia);
// 删除文件fileStorageService.delete(wemedia/2020/12/20201227/aaa1.jpg);}
}
3 自媒体管理
3.1 自媒体用户登录
自媒体登录操作与admin端登录思路是一样的
1自媒体登录接口定义
接口地址:/login/in
请求方式:POST
请求数据类型:application/json
响应数据类型:*/*
接口描述:
请求示例:
{name: ,password:
}
请求参数:
参数名称参数说明in是否必须数据类型schemadtodtobodytrueWmUserDtoWmUserDto namefalsestring passwordfalsestringWmUserDto
Data
public class WmUserDTO {/*** 用户名*/private String name;/*** 密码*/private String password;
}
WmUserVO
Data
public class WmUserVO {private Integer id;private String name;private String nickname;private String image;private String email;private Date loginTime;private Date createdTime;
} 1业务层service
新增业务层接口
package com.heima.wemedia.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.dtos.WmUserDTO;
import com.heima.model.wemedia.pojos.WmUser;
public interface WmUserService extends IServiceWmUser {/*** 登录* param dto* return*/public ResponseResult login(WmUserDTO dto);
}
实现类
package com.heima.wemedia.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.exception.CustException;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmUserDTO;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.model.wemedia.vos.WmUserVO;
import com.heima.utils.common.AppJwtUtil;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.util.HashMap;
import java.util.Map;
Service
public class WmUserServiceImpl extends ServiceImplWmUserMapper, WmUser implements WmUserService {/*** 登录* param dto* return*/Overridepublic ResponseResult login(WmUserDTO dto) {//1.检查参数if(StringUtils.isBlank(dto.getName())||StringUtils.isBlank(dto.getPassword())){CustException.cust(AppHttpCodeEnum.PARAM_INVALID);}//2 查询自媒体用户WmUser wmUser getOne(Wrappers.WmUserlambdaQuery().eq(WmUser::getName, dto.getName()));if (wmUser null) {CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);}if(wmUser.getStatus().intValue()!9){// 可替换为常量CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW,该用户状态异常请联系管理员);}String pswd DigestUtils.md5DigestAsHex((dto.getPassword() wmUser.getSalt()).getBytes());if (!wmUser.getPassword().equals(pswd)) {CustException.cust(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);}//4 返回jwt结果MapString, Object map new HashMap();map.put(token, AppJwtUtil.getToken(Long.valueOf(wmUser.getId())));WmUserVO userVO new WmUserVO();BeanUtils.copyProperties(wmUser,userVO);map.put(user, userVO);return ResponseResult.okResult(map);}
} 2控制器controller
新增控制器
package com.heima.wemedia.controller.v1;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.dtos.WmUserDTO;
import com.heima.wemedia.service.WmUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
RestController
RequestMapping(/login)
public class LoginController {Autowiredprivate WmUserService wmUserService;PostMapping(/in)public ResponseResult login(RequestBody WmUserDTO dto){return wmUserService.login(dto);}
}
3小刀无网关测试
3.2 自媒体网关和获取登录用户
1自媒体网关
上一次创建的admin平台管理的网关自媒体端也有自己的网关后边还需要创建app端的网关
自媒体网关与admin端网关几乎是一样的可以参考admin端网关 创建wemedia-gateway网关工程pom文件如下 从admin网关中把必要的类拷贝过来 新增bootstrap.yml spring: application: name: wemedia-gateway # 服务名称 profiles: active: dev # 开发环境配置 ip: 192.168.200.130 # 环境ip地址 cloud: nacos: discovery: # 注册中心地址配置 server-addr: ${spring.profiles.ip}:8848 namespace: ${spring.profiles.active} config: # 配置中心地址配置 server-addr: ${spring.profiles.ip}:8848 namespace: ${spring.profiles.active} file-extension: yml # data-id 后缀 name: ${spring.application.name} # data-id名称
配置中心dev环境新增 wemedia-gateway.yml
server:port: 6002
spring:cloud:gateway:globalcors:cors-configurations:[/**]: # 匹配所有请求allowedOrigins: * #跨域处理 允许所有的域allowedMethods: # 支持的方法- GET- POST- PUT- DELETEroutes:# 平台管理- id: wemediauri: lb://leadnews-wemediapredicates:- Path/wemedia/**filters:- StripPrefix 1
2获取登录用户思路分析
在去保存图片之前需要先知道是哪一位自媒体人登录了当前系统也就是需要确定哪个自媒体人上传了图片 操作步骤 上传图片需要携带token 首先请求到网关服务解析token是否有效如果有效解析后把用户数据设置到下一级请求的header中 在自媒体微服务中使用过滤器解析header中的数据拿到用户数据使用threadlocal设置到当前线程中 在具体业务代码中可以从当前线程threadlocal中获取用户
3获取登录用户
前面两步都已经实现主要是在代码中实现后两步即可
1)添加工具类
在使用过滤器解析后的用户需要放在当前线程中可以使用工具类来实现,
在heima-leadnews-model中com.heima.model.threadlocal添加如下类,用于存储自媒体的用户登录信息
package com.heima.model.threadlocal;
import com.heima.model.wemedia.pojos.WmUser;
public class WmThreadLocalUtils {private final static ThreadLocalWmUser userThreadLocal new ThreadLocal();/*** 设置当前线程中的用户* param user*/public static void setUser(WmUser user){userThreadLocal.set(user);}/*** 获取线程中的用户* return*/public static WmUser getUser( ){return userThreadLocal.get();}/*** 清空线程中的用户信息*/public static void clear(){userThreadLocal.remove();}
}
2)在wemedia-service自媒体微服务中使用过滤器解析header数据并设置到当前线程中
package com.heima.wemedia.filter;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.wemedia.pojos.WmUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Order(1)
WebFilter(filterName wmTokenFilter,urlPatterns /*)
Slf4j
Component // 扫描包
public class WmTokenFilter extends GenericFilterBean {Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request (HttpServletRequest) servletRequest;HttpServletResponse response (HttpServletResponse) servletResponse;//得到header中的信息String userId request.getHeader(userId);if(userId ! null){WmUser wmUser new WmUser();wmUser.setId(Integer.valueOf(userId));// 保存到当前线程中WmThreadLocalUtils.setUser(wmUser);}// 如果没有则直接放行filterChain.doFilter(request,response);// 过滤器处理完毕后 清空用户信息WmThreadLocalUtils.clear();}
} 3.3 素材管理
效果演示: heima-leadnews-wemedia
3.3.1 图片上传
3.3.1.1 文件上传需求 对应实体类
package com.heima.model.wemedia.pojos;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/*** p* 自媒体图文素材信息表* /p** author itheima*/
Data
TableName(wm_material)
public class WmMaterial implements Serializable {
private static final long serialVersionUID 1L;
/*** 主键*/TableId(value id, type IdType.AUTO)private Integer id;
/*** 自媒体用户ID*/TableField(user_id)private Integer userId;
/*** 图片地址*/TableField(url)private String url;
/*** 素材类型0 图片1 视频*/TableField(type)private Short type;
/*** 是否收藏*/TableField(is_collection)private Short isCollection;
/*** 创建时间*/TableField(created_time)private Date createdTime;
}
3.3.1.2 接口定义
接口地址:/api/v1/material/upload_picture
请求方式:POST
请求数据类型:multipart/form-data
响应数据类型:*/*
接口描述: 文件上传
请求参数:
参数名称参数说明in是否必须数据类型schemamultipartFilemultipartFileformDatafalsefile3.3.1.3 定义mapper
新建接口com.heima.wemedia.mapper.WmMaterialMapper
package com.heima.wemedia.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.pojos.WmMaterial;
import org.apache.ibatis.annotations.Mapper;
public interface WmMaterialMapper extends BaseMapperWmMaterial {
}
3.3.1.4 定义service
新建接口com.heima.wemedia.service.MaterialService
package com.heima.wemedia.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmMaterial;
import org.springframework.web.multipart.MultipartFile;
public interface WmMaterialService extends IServiceWmMaterial {/*** 上传图片接口* param multipartFile* return*/ResponseResult uploadPicture(MultipartFile multipartFile);
}
实现类
package com.heima.wemedia.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.exception.CustException;
import com.heima.common.exception.CustomException;
import com.heima.file.service.FileStorageService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.service.WmMaterialService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
Service
Slf4j
public class WmMaterialServiceImpl extends ServiceImplWmMaterialMapper, WmMaterial implements WmMaterialService {AutowiredFileStorageService fileStorageService;Value(${file.oss.prefix})String prefix;Value(${file.oss.web-site})String webSite;Overridepublic ResponseResultWmMaterial uploadPicture(MultipartFile multipartFile) {// 1 参数校验if (multipartFile null || multipartFile.getSize() 0) {CustException.cust(AppHttpCodeEnum.PARAM_INVALID,请上传正确的文件);}// 当前线程中获取用户IDWmUser user WmThreadLocalUtils.getUser();if (user null) {CustException.cust(AppHttpCodeEnum.NO_OPERATOR_AUTH);}String originalFilename multipartFile.getOriginalFilename();if (!checkFileSuffix(originalFilename)) {CustException.cust(AppHttpCodeEnum.PARAM_INVALID,请上传正确的素材格式,[jpg,jpeg,png,gif]);}// 2 上传到ossString fileId null;try {String filename UUID.randomUUID().toString().replace(-, );String suffix originalFilename.substring(originalFilename.lastIndexOf(.));fileId fileStorageService.store(prefix, filenamesuffix, multipartFile.getInputStream());log.info(阿里云OSS 文件 fileId: {},fileId);} catch (IOException e) {e.printStackTrace();log.error(阿里云文件上传失败 uploadPicture error: {}, e);CustException.cust(AppHttpCodeEnum.SERVER_ERROR,服务器繁忙请稍后重试);}// 3 封装数据并保持到素材库中WmMaterial wmMaterial new WmMaterial();wmMaterial.setIsCollection((short)0);wmMaterial.setType((short)0);wmMaterial.setCreatedTime(new Date());// 设置文件idwmMaterial.setUrl(fileId);wmMaterial.setUserId(user.getId());save(wmMaterial);// 前端显示wmMaterial.setUrl(webSitefileId);// 4 返回结果return ResponseResult.okResult(wmMaterial);}/*** 检查文件格式 目前仅仅支持jpg jpeg png gif 图片的上传* param path* return*/private boolean checkFileSuffix(String path){if(StringUtils.isBlank(path)) return false;ListString allowSuffix Arrays.asList(jpg, jpeg, png, gif);boolean isAllow false;for (String suffix : allowSuffix) {if(path.endsWith(suffix)){isAllow true;break;}}return isAllow;}
}
3.3.1.5 控制层
package com.heima.wemedia.controller.v1;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.wemedia.service.WmMaterialService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
Api(value 素材管理API,tags 素材管理API)
RestController
RequestMapping(/api/v1/material)
public class WmMaterialController {Autowiredprivate WmMaterialService materialService;ApiOperation(上传素材)PostMapping(/upload_picture)public ResponseResult uploadPicture(MultipartFile multipartFile) {return materialService.uploadPicture(multipartFile);}
}
3.3.1.6 测试
启动清单 naocs WemediaGatewayApplication 网关 WemediaApplication 自媒体服务 使用postman 或 小刀文档测试需要先登录设置token后再操作 3.3.2 素材列表加载 素材列表查询前台有可能给传一个条件 是否收藏 0 不收藏 1 收藏 只能查询当前登录用户上传的素材 按照发布时间 降序排序 返回的结果 图片需要加上前缀访问路径
3.3.2.1 接口定义
接口地址:/api/v1/material/list
请求方式:POST
请求数据类型:application/json
响应数据类型:*/*
接口描述: 查询素材列表
请求示例:
{isCollected: 0,page: 0,size: 0
}
请求参数:
参数名称参数说明in是否必须数据类型schemadtodtobodytrueWmMaterialDtoWmMaterialDto isCollectedfalseinteger(int32) page当前第几页falseinteger(int32) size每页显示条数falseinteger(int32)WmMaterialDTO
package com.heima.model.wemedia.dtos;
import com.heima.model.common.dtos.PageRequestDTO;
import lombok.Data;
Data
public class WmMaterialDTO extends PageRequestDTO {Short isCollection; //1 查询收藏的 0: 未收藏
}
3.3.2.2 定义service
在com.heima.wemedia.service.WmMaterialService类中新增方法
/*** 素材列表查询* param dto* return*/
ResponseResult findList(WmMaterialDTO dto);
实现类
Overridepublic ResponseResult findList(WmMaterialDTO dto) {// 1 参数校验dto.checkParam();// 2 执行业务查询LambdaQueryWrapperWmMaterial wrapper new LambdaQueryWrapper();// 收藏if (dto.getIsCollection() ! null dto.getIsCollection() 1) {wrapper.eq(WmMaterial::getIsCollection, dto.getIsCollection());}// 当前登录用户的素材WmUser user WmThreadLocalUtils.getUser();if (user null) {throw new CustomException(AppHttpCodeEnum.NO_OPERATOR_AUTH);}wrapper.eq(WmMaterial::getUserId, user.getId());// 时间倒序wrapper.orderByDesc(WmMaterial::getCreatedTime);IPageWmMaterial pageParam new Page(dto.getPage(), dto.getSize());IPageWmMaterial resultPage page(pageParam, wrapper);ListWmMaterial records resultPage.getRecords();for (WmMaterial record : records) {record.setUrl(webSite record.getUrl());}// 3 封装结果PageResponseResult pageResponseResult new PageResponseResult(dto.getPage(), dto.getSize(), resultPage.getTotal());pageResponseResult.setData(records);return pageResponseResult;}
3.3.2.3 控制层
在com.heima.wemedia.controller.v1.WmMaterialController新增方法 ApiOperation(查询素材列表)PostMapping(/list)public ResponseResult findList(RequestBody WmMaterialDTO dto) {return materialService.findList(dto);}
3.3.2.4 测试
使用postman测试需要先登录设置token后再操作