①公共字段填充----mybatis
第一步:自定义注解
/*** 自定义注解用于标识某个方法需要进行功能字段的填充*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {//枚举:数据库操作类型: update insertOperationType 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 {@Overridepublic 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());}@Overridepublic 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/ObjectNameStringBuilder 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.comaccess-key-id: LTAI5t7HRcgiCBRrRfPkzo6faccess-key-secret: XZOMsLJdTaZvKHKW5qS55nQrhh95Bfbucket-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@ConditionalOnMissingBeanpublic 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);