①公共字段填充----mybatis
第一步:自定义注解
/**
* 自定义注解用于标识某个方法需要进行功能字段的填充
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//枚举:数据库操作类型: update insert
OperationType value();
}
枚举类:
/**
* 数据库操作类型
*/
public enum OperationType {
/**
* 更新操作
*/
UPDATE,
/**
* 插入操作
*/
INSERT
}
第二步:自定义切面类
/**
* 自定义切面,实现公共字段自动填充处理逻辑
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
*/
//指定拦截哪些mapper类 拦截所有的mapper中的所有方法 && 方法上加入了自定义注解的方法
@Pointcut("execution(* com.sky.service.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointcut(){}
//前置通知,在方法前为公共字段赋值
@Before("autoFillPointcut()")
//传来切入点
public void autoFill(JoinPoint joinPoint){
log.info("开始进行公共字段的填充");
//获取到当前被拦截的方法上操作数据库的类型
MethodSignature signature = (MethodSignature)joinPoint.getSignature(); //先获得方法对象
AutoFill autofill = signature.getMethod().getAnnotation(AutoFill.class);//再获得方法上的注解对象
OperationType operationtype = autofill.value(); //最后获得数据库操作类型
//获取到当前被拦截的方法上的参数
Object[] args = joinPoint.getArgs();
if(args == null || args.length == 0){
return;
}
Object entity = args[0];
//准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//为参数里的属性进行反射赋值
if(operationtype == OperationType.INSERT){
//为四个公共字段赋值
try {
//获得属性的set方法
Method setCreatTime = entity.getClass().getDeclaredMethod("setCreatTime", LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
//反射赋值
setCreatTime.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}else if (operationtype == OperationType.UPDATE){
//为两个公共字段赋值
try {
//获得属性的set方法
Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);
//反射赋值
setUpdateTime.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
第三步:在mapper层的方法上加上我们的自定义注解以及类型
②公共字段填充----mybatisPlus
第一步:字段上添加注解
@TableField(fill = FieldFill.INSERT)//插入时填充
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入以及更新时填充
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)//插入时填充
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入以及更新时填充
private Long updateUser;
第二步:编写元数据处理类
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.sky.context.BaseContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
//元数据处理器
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充---新增 :{}",metaObject);
//设置数据
metaObject.setValue("createTime",LocalDateTime.now());
metaObject.setValue("createUser",BaseContext.getCurrentId());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充---更新 :{}",metaObject);
//设置数据
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
}
这样就可以实现mybatisPlus的公共字段填充,之后在写实体类的相关字段时就可以不用自己去set,用这个控制器去自动完成可以
③阿里云OSS----文件上传
前端上传:
后端接收:
后端进行文件存储-----存储在本地(transferTo):
后端进行文件存储-----存储在云(阿里云OSS,object storage service)
第一步:引入依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
//如果java 版本9以上则要添加以下依赖
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
第二步:改配置,存文件
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
第三步:集成!!!!!!!!!
引入工具类:这个工具类是用来把上传这个动作封装的,之后使用的画就直接把(文件,上传到云端保存的文件名)传入就可以实现上传功能,而其返回的数据就是文件在云端的访问地址
@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
/**
* 文件上传
*
* @param bytes
* @param objectName
* @return
*/
public String upload(byte[] bytes, String objectName) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
//文件访问路径规则 https://BucketName.Endpoint/ObjectName
StringBuilder stringBuilder = new StringBuilder("https://");
stringBuilder
.append(bucketName)
.append(".")
.append(endpoint)
.append("/")
.append(objectName);
log.info("文件上传到:{}", stringBuilder.toString());
return stringBuilder.toString();
}
}
配置云端密钥信息
alioss:
endpoint: oss-cn-beijing.aliyuncs.com
access-key-id: LTAI5t7HRcgiCBRrRfPkzo6f
access-key-secret: XZOMsLJdTaZvKHKW5qS55nQrhh95Bf
bucket-name: zzl-test-01
封装一个实体类去加载我们的yml中的数据
@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
}
创建一个配置类,去创建工具类对象并交给bean容器管理
/**
* 配置类
*/
@Configuration
@Slf4j
public class OssConfiguration {
@Bean
@ConditionalOnMissingBean
public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);
return new AliOssUtil(aliOssProperties.getEndpoint(),
aliOssProperties.getAccessKeyId(),
aliOssProperties.getAccessKeySecret(),
aliOssProperties.getBucketName());
}
}
在接口中使用OSS工具类
@PostMapping("/upload")
@ApiOperation("文件上传")
public Result<String> upload(MultipartFile file){
log.info("文件上传");
try {
//原始文件名
String originalFilename = file.getOriginalFilename();
//截取原始文件的类型,即获得文件的拓展名
String extention = originalFilename.substring(originalFilename.lastIndexOf("."));
String objectname = UUID.randomUUID().toString() + extention;
//把文件的二进制形式和存储到云端的名字传给工具类,返回在云端的访问路径
String filePath = aliOssUtil.upload(file.getBytes(), objectname);
//把文件路径返回
return Result.success(filePath);
} catch (IOException e) {
log.error("文件上传失败:{}",e);
}
return Result.error("文件上传失败");
}
④mp多表联合分页查询,很硬但可以
先展示一下自己实在直接硬搬代码的蠢办法,连多表查询都不需要:
public PageResult page(DishPageQueryDTO dishPageQueryDTO) {
//创建Ipage对象
IPage page = new Page(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
//创建QueryWrapper对象进行条件筛选
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq(dishPageQueryDTO.getCategoryId() != null,"category_id",dishPageQueryDTO.getCategoryId())
.like(dishPageQueryDTO.getName() != null,"name",dishPageQueryDTO.getName())
.eq(dishPageQueryDTO.getStatus() != null,"status",dishPageQueryDTO.getStatus());
//进行查询
dishMapper.selectPage(page, wrapper);
List<Dish> records = page.getRecords();
List<DishVO> dishVOS = new ArrayList<>();
List<Category> name =new ArrayList<>();
records.forEach(dish -> {
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(dish,dishVO);
dishVOS.add(dishVO);
name.add(categoryService.query().eq("id",dish.getCategoryId()).select("name").one());
});
for(int i=0;i< dishVOS.size();i++){
dishVOS.get(i).setCategoryName(name.get(i).getName());
}
//返回数据
return new PageResult(page.getTotal(),dishVOS);
}
不过再看了瑞吉外面的实现方法确实跟我这个差不了太多,都是直接把id提取出来去查过再放进链表中
List<Dish> records = page.getRecords();
List<DishVO> dishVOS = records.stream().map((item) -> {
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(item, dishVO);
Category byId = categoryService.getById(item.getCategoryId());
dishVO.setCategoryName(byId.getName());
return dishVO;
}).collect(Collectors.toList());
return new PageResult(page.getTotal(),dishVOS);