@Query 加入NOT_NULL查询,优化图床上传,加入图床同步功能

pull/302/head
Elune 2019-12-20 19:31:37 +08:00
parent 467e04adca
commit a6e57e160f
13 changed files with 427 additions and 16 deletions

View File

@ -54,6 +54,8 @@ public @interface Query {
,NOT_EQUAL
// between
,BETWEEN
// 不为空
,NOT_NULL
}
/**

View File

@ -20,6 +20,6 @@ public class ElAdminConstant {
*
*/
public static class Url{
public static final String SM_MS_URL = "https://sm.ms/api/upload";
public static final String SM_MS_URL = "https://sm.ms/api";
}
}

View File

@ -110,6 +110,9 @@ public class QueryHelp {
case NOT_EQUAL:
list.add(cb.notEqual(getExpression(attributeName,join,root), val));
break;
case NOT_NULL:
list.add(cb.isNotNull(getExpression(attributeName,join,root)));
break;
case BETWEEN:
List<Object> between = new ArrayList<>((List<Object>)val);
list.add(cb.between(getExpression(attributeName, join, root).as((Class<? extends Comparable>) between.get(0).getClass()),

View File

@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
/**
* @author Zheng Jie
@ -107,10 +108,10 @@ public class QuartzJobController {
@Log("删除定时任务")
@ApiOperation("删除定时任务")
@DeleteMapping(value = "/{id}")
@DeleteMapping
@PreAuthorize("@el.check('timing:del')")
public ResponseEntity<Object> delete(@PathVariable Long id){
quartzJobService.delete(quartzJobService.findById(id));
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
quartzJobService.delete(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -8,6 +8,7 @@ import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
@ -60,9 +61,9 @@ public interface QuartzJobService {
/**
*
* @param quartzJob /
* @param ids /
*/
void delete(QuartzJob quartzJob);
void delete(Set<Long> ids);
/**
* ID

View File

@ -23,10 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author Zheng Jie
@ -131,12 +128,15 @@ public class QuartzJobServiceImpl implements QuartzJobService {
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(QuartzJob quartzJob) {
if(quartzJob.getId().equals(1L)){
throw new BadRequestException("该任务不可操作");
public void delete(Set<Long> ids) {
for (Long id : ids) {
if(id.equals(1L)){
throw new BadRequestException("更新访客记录不可删除,你可以在后台代码中取消该限制");
}
QuartzJob quartzJob = findById(id);
quartzManage.deleteJob(quartzJob);
quartzJobRepository.delete(quartzJob);
}
quartzManage.deleteJob(quartzJob);
quartzJobRepository.delete(quartzJob);
}
@Override

View File

@ -55,4 +55,7 @@ loginCode:
#密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
smms:
token: 1oOP3ykFDI0K6ifmtvU7c8Y1eTWZSlyl

View File

@ -0,0 +1,53 @@
package me.zhengjie.domain;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* sm.ms
*
* @author Zheng Jie
* @date 2018-12-27
*/
@Data
@Entity
@Table(name = "picture")
public class Picture implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String filename;
private String url;
private String size;
private String height;
private String width;
@Column(name = "delete_url")
private String delete;
private String username;
@CreationTimestamp
@Column(name = "create_time")
private Timestamp createTime;
/** 用于检测文件是否重复 */
private String md5Code;
@Override
public String toString() {
return "Picture{" +
"filename='" + filename + '\'' +
'}';
}
}

View File

@ -0,0 +1,26 @@
package me.zhengjie.repository;
import me.zhengjie.domain.Picture;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2018-12-27
*/
public interface PictureRepository extends JpaRepository<Picture,Long>, JpaSpecificationExecutor<Picture> {
/**
* Mds
* @param code
* @return /
*/
Picture findByMd5Code(String code);
/**
*
* @param url /
* @return /
*/
boolean existsByUrl(String url);
}

View File

@ -0,0 +1,78 @@
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.domain.Picture;
import me.zhengjie.service.PictureService;
import me.zhengjie.service.dto.PictureQueryCriteria;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author
* @date 2018/09/20 14:13:32
*/
@RestController
@RequestMapping("/api/pictures")
@Api(tags = "工具:免费图床管理")
public class PictureController {
private final PictureService pictureService;
public PictureController(PictureService pictureService) {
this.pictureService = pictureService;
}
@Log("查询图片")
@PreAuthorize("@el.check('pictures:list')")
@GetMapping
@ApiOperation("查询图片")
public ResponseEntity<Object> getRoles(PictureQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(pictureService.queryAll(criteria,pageable),HttpStatus.OK);
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('pictures:list')")
public void download(HttpServletResponse response, PictureQueryCriteria criteria) throws IOException {
pictureService.download(pictureService.queryAll(criteria), response);
}
@Log("上传图片")
@PreAuthorize("@el.check('pictures:add')")
@PostMapping
@ApiOperation("上传图片")
public ResponseEntity<Object> upload(@RequestParam MultipartFile file){
String userName = SecurityUtils.getUsername();
Picture picture = pictureService.upload(file,userName);
return new ResponseEntity<>(picture,HttpStatus.OK);
}
@Log("同步图床数据")
@ApiOperation("同步图床数据")
@PostMapping(value = "/synchronize")
public ResponseEntity<Object> synchronize(){
pictureService.synchronize();
return new ResponseEntity<>(HttpStatus.OK);
}
@Log("多选删除图片")
@ApiOperation("多选删除图片")
@PreAuthorize("@el.check('pictures:del')")
@DeleteMapping
public ResponseEntity<Object> deleteAll(@RequestBody Long[] ids) {
pictureService.deleteAll(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@ -0,0 +1,66 @@
package me.zhengjie.service;
import me.zhengjie.domain.Picture;
import me.zhengjie.service.dto.PictureQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-12-27
*/
public interface PictureService {
/**
*
* @param criteria
* @param pageable
* @return /
*/
Object queryAll(PictureQueryCriteria criteria, Pageable pageable);
/**
*
* @param criteria
* @return /
*/
List<Picture> queryAll(PictureQueryCriteria criteria);
/**
*
* @param file /
* @param username /
* @return /
*/
Picture upload(MultipartFile file, String username);
/**
* ID
* @param id /
* @return /
*/
Picture findById(Long id);
/**
*
* @param ids /
*/
void deleteAll(Long[] ids);
/**
*
* @param queryAll
* @param response /
* @throws IOException /
*/
void download(List<Picture> queryAll, HttpServletResponse response) throws IOException;
/**
*
*/
void synchronize();
}

View File

@ -0,0 +1,26 @@
package me.zhengjie.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
import java.util.List;
/**
* sm.ms
*
* @author Zheng Jie
* @date 2019-6-4 09:52:09
*/
@Data
public class PictureQueryCriteria{
@Query(type = Query.Type.INNER_LIKE)
private String filename;
@Query(type = Query.Type.INNER_LIKE)
private String username;
@Query(type = Query.Type.BETWEEN)
private List<Timestamp> createTime;
}

View File

@ -0,0 +1,152 @@
package me.zhengjie.service.impl;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.domain.Picture;
import me.zhengjie.repository.PictureRepository;
import me.zhengjie.service.PictureService;
import me.zhengjie.service.dto.PictureQueryCriteria;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Zheng Jie
* @date 2018-12-27
*/
@Slf4j
@Service(value = "pictureService")
@CacheConfig(cacheNames = "picture")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class PictureServiceImpl implements PictureService {
@Value("${smms.token}")
private String token;
private final PictureRepository pictureRepository;
private static final String SUCCESS = "success";
private static final String CODE = "code";
private static final String MSG = "message";
public PictureServiceImpl(PictureRepository pictureRepository) {
this.pictureRepository = pictureRepository;
}
@Override
public Object queryAll(PictureQueryCriteria criteria, Pageable pageable){
return PageUtil.toPage(pictureRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
}
@Override
public List<Picture> queryAll(PictureQueryCriteria criteria) {
return pictureRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
}
@Override
@Transactional(rollbackFor = Throwable.class)
public Picture upload(MultipartFile multipartFile, String username) {
File file = FileUtil.toFile(multipartFile);
// 验证是否重复上传
Picture picture = pictureRepository.findByMd5Code(FileUtil.getMd5(file));
if(picture != null){
return picture;
}
HashMap<String, Object> paramMap = new HashMap<>(1);
paramMap.put("smfile", file);
// 上传文件
String result= HttpRequest.post(ElAdminConstant.Url.SM_MS_URL + "/v2/upload")
.header("Authorization", token)
.form(paramMap)
.timeout(20000)
.execute().body();
JSONObject jsonObject = JSONUtil.parseObj(result);
if(!jsonObject.get(CODE).toString().equals(SUCCESS)){
throw new BadRequestException(TranslatorUtil.translate(jsonObject.get(MSG).toString()));
}
picture = JSON.parseObject(jsonObject.get("data").toString(), Picture.class);
picture.setSize(FileUtil.getSize(Integer.parseInt(picture.getSize())));
picture.setUsername(username);
picture.setMd5Code(FileUtil.getMd5(file));
picture.setFilename(FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename())+"."+FileUtil.getExtensionName(multipartFile.getOriginalFilename()));
pictureRepository.save(picture);
//删除临时文件
FileUtil.del(file);
return picture;
}
@Override
public Picture findById(Long id) {
Picture picture = pictureRepository.findById(id).orElseGet(Picture::new);
ValidationUtil.isNull(picture.getId(),"Picture","id",id);
return picture;
}
@Override
public void deleteAll(Long[] ids) {
for (Long id : ids) {
Picture picture = findById(id);
try {
HttpUtil.get(picture.getDelete());
pictureRepository.delete(picture);
} catch(Exception e){
pictureRepository.delete(picture);
}
}
}
@Override
public void synchronize() {
//链式构建请求
String result = HttpRequest.get(ElAdminConstant.Url.SM_MS_URL + "/v2/upload_history")
//头信息,多个头信息多次调用此方法即可
.header("Authorization", token)
.timeout(20000)
.execute().body();
JSONObject jsonObject = JSONUtil.parseObj(result);
List<Picture> pictures = JSON.parseArray(jsonObject.get("data").toString(), Picture.class);
for (Picture picture : pictures) {
if(!pictureRepository.existsByUrl(picture.getUrl())){
picture.setSize(FileUtil.getSize(Integer.parseInt(picture.getSize())));
picture.setUsername("System Sync");
picture.setMd5Code("");
pictureRepository.save(picture);
}
}
}
@Override
public void download(List<Picture> queryAll, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (Picture picture : queryAll) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("文件名", picture.getFilename());
map.put("图片地址", picture.getUrl());
map.put("文件大小", picture.getSize());
map.put("操作人", picture.getUsername());
map.put("高度", picture.getHeight());
map.put("宽度", picture.getWidth());
map.put("删除地址", picture.getDelete());
map.put("创建日期", picture.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}