Commit 0f0392d7 authored by dqjdda's avatar dqjdda
Browse files

Merge branch '2.2DEV'

parents d0ffe1a8 f9bb8cf2
......@@ -10,5 +10,6 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-common</artifactId>
<name>公共模块</name>
</project>
\ No newline at end of file
......@@ -3,14 +3,14 @@ package me.zhengjie.redis;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -61,6 +61,7 @@ public class RedisConfig extends CachingConfigurerSupport {
// 建议使用这种方式,小范围指定白名单
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain");
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain");
......@@ -73,8 +74,8 @@ public class RedisConfig extends CachingConfigurerSupport {
}
/**
* 自定义缓存key生成策略
* 使用方法 @Cacheable(keyGenerator="keyGenerator")
* 自定义缓存key生成策略,默认将使用该策略
* 使用方法 @Cacheable
* @return
*/
@Bean
......@@ -90,4 +91,34 @@ public class RedisConfig extends CachingConfigurerSupport {
return sb.toString();
};
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError:", e);
}
};
return cacheErrorHandler;
}
}
package me.zhengjie.utils;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import me.zhengjie.exception.BadRequestException;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* File工具类,扩展 hutool 工具包
......@@ -100,7 +111,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
* @param size
* @return
*/
public static String getSize(int size){
public static String getSize(long size){
String resultSize = "";
if (size / GB >= 1) {
//如果当前Byte的值大于等于1GB
......@@ -139,4 +150,91 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
ins.close();
return file;
}
/**
* 将文件名解析成文件的上传路径
*
* @param file
* @param filePath
* @return 上传到服务器的文件名
*/
public static File upload(MultipartFile file, String filePath) {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
String name = getFileNameNoEx(file.getOriginalFilename());
String suffix = getExtensionName(file.getOriginalFilename());
String nowStr = "-" + format.format(date);
try {
String fileName = name + nowStr + "." + suffix;
String path = filePath + fileName;
File dest = new File(path);
// 检测是否存在目录
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();// 新建文件夹
}
String d = dest.getPath();
file.transferTo(dest);// 文件写入
return dest;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String fileToBase64(File file) throws Exception {
FileInputStream inputFile = new FileInputStream(file);
String base64 =null;
byte[] buffer = new byte[(int)file.length()];
inputFile.read(buffer);
inputFile.close();
base64=new Base64().encode(buffer);
String encoded = base64.replaceAll("[\\s*\t\n\r]", "");
return encoded;
}
/**
* 导出excel
* @param list
* @return
* @throws Exception
*/
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
String tempPath =System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
File file = new File(tempPath);
BigExcelWriter writer= ExcelUtil.getBigWriter(file);
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(list, true);
//response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition","attachment;filename=file.xlsx");
ServletOutputStream out=response.getOutputStream();
// 终止后删除临时文件
file.deleteOnExit();
writer.flush(out, true);
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
public static String getFileType(String type) {
String documents = "txt doc pdf ppt pps xlsx xls";
String music = "mp3 wav wma mpa ram ra aac aif m4a";
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
if(image.indexOf(type) != -1){
return "图片";
} else if(documents.indexOf(type) != -1){
return "文档";
} else if(music.indexOf(type) != -1){
return "音乐";
} else if(video.indexOf(type) != -1){
return "视频";
} else return "其他";
}
public static void checkSize(long maxSize, long size) {
if(size > (maxSize * 1024 * 1024)){
throw new BadRequestException("文件超出规定大小");
}
}
}
package me.zhengjie.utils;
import org.springframework.data.domain.Page;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* 分页工具
......@@ -39,11 +36,9 @@ public class PageUtil extends cn.hutool.core.util.PageUtil {
* @return
*/
public static Map toPage(Page page) {
Map map = new HashMap();
Map<String,Object> map = new LinkedHashMap<>(2);
map.put("content",page.getContent());
map.put("totalElements",page.getTotalElements());
return map;
}
......@@ -53,8 +48,7 @@ public class PageUtil extends cn.hutool.core.util.PageUtil {
* @return
*/
public static Map toPage(Object object, Object totalElements) {
Map map = new HashMap();
Map<String,Object> map = new LinkedHashMap<>(2);
map.put("content",object);
map.put("totalElements",totalElements);
......
......@@ -58,13 +58,24 @@ public class QueryHelp {
continue;
}
if (ObjectUtil.isNotEmpty(joinName)) {
switch (q.join()) {
case LEFT:
join = root.join(joinName, JoinType.LEFT);
break;
case RIGHT:
join = root.join(joinName, JoinType.RIGHT);
break;
String[] joinNames = joinName.split(">");
for (String name : joinNames) {
switch (q.join()) {
case LEFT:
if(ObjectUtil.isNotEmpty(join)){
join = join.join(name, JoinType.LEFT);
} else {
join = root.join(name, JoinType.LEFT);
}
break;
case RIGHT:
if(ObjectUtil.isNotEmpty(join)){
join = join.join(name, JoinType.RIGHT);
} else {
join = root.join(name, JoinType.RIGHT);
}
break;
}
}
}
switch (q.type()) {
......
package me.zhengjie.utils;
import me.zhengjie.exception.BadRequestException;
import org.hibernate.exception.ConstraintViolationException;
import java.io.PrintWriter;
import java.io.StringWriter;
......@@ -25,4 +28,15 @@ public class ThrowableUtil {
pw.close();
}
}
public static void throwForeignKeyException(Throwable e, String msg){
Throwable t = e.getCause();
while ((t != null) && !(t instanceof ConstraintViolationException)) {
t = t.getCause();
}
if (t instanceof ConstraintViolationException) {
throw new BadRequestException(msg);
}
throw new BadRequestException("删除失败:" + t.getMessage());
}
}
package me.zhengjie.utils;
import cn.hutool.json.JSONArray;
import lombok.var;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class TranslatorUtil {
public static String translate(String word){
try {
String url = "https://translate.googleapis.com/translate_a/single?" +
"client=gtx&" +
"sl=en" +
"&tl=zh-CN" +
"&dt=t&q=" + URLEncoder.encode(word, "UTF-8");
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return parseResult(response.toString());
}catch (Exception e){
return word;
}
}
private static String parseResult(String inputJson) throws Exception {
JSONArray jsonArray = new JSONArray(inputJson);
JSONArray jsonArray2 = (JSONArray) jsonArray.get(0);
String result ="";
for(var i = 0; i < jsonArray2.size(); i ++){
result += ((JSONArray) jsonArray2.get(i)).get(0).toString();
}
return result;
}
}
......@@ -10,6 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-generator</artifactId>
<name>代码生成模块</name>
<properties>
<configuration.version>1.9</configuration.version>
......
......@@ -5,6 +5,8 @@ import me.zhengjie.repository.GenConfigRepository;
import me.zhengjie.service.GenConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.Optional;
/**
......@@ -30,6 +32,22 @@ public class GenConfigServiceImpl implements GenConfigService {
@Override
public GenConfig update(GenConfig genConfig) {
genConfig.setId(1L);
// 自动设置Api路径,注释掉前需要同步取消前端的注释
String separator = File.separator;
String[] paths = null;
if (separator.equals("\\")) {
paths = genConfig.getPath().split("\\\\");
} else paths = genConfig.getPath().split(File.separator);
StringBuffer api = new StringBuffer();
for (int i = 0; i < paths.length; i++) {
api.append(paths[i]);
api.append(separator);
if(paths[i].equals("src")){
api.append("api");
break;
}
}
genConfig.setApiPath(api.toString());
return genConfigRepository.save(genConfig);
}
}
......@@ -10,6 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-logging</artifactId>
<name>日志模块</name>
<dependencies>
<dependency>
......
......@@ -10,6 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-system</artifactId>
<name>核心模块</name>
<properties>
<jjwt.version>0.9.1</jjwt.version>
......
......@@ -3,6 +3,7 @@ package me.zhengjie.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
......@@ -25,6 +26,12 @@ import java.util.List;
@EnableWebMvc
public class ConfigurerAdapter implements WebMvcConfigurer {
@Value("${file.path}")
private String path;
@Value("${file.avatar}")
private String avatar;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
......@@ -35,27 +42,12 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
}
// 可解决Long 类型在 前端精度丢失的问题, 如不想全局 直接添加注解 @JsonSerialize(using= ToStringSerializer.class) 到相应的字段
// @Override
// public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//
// MappingJackson2HttpMessageConverter jackson2HttpMessageConverter =
// new MappingJackson2HttpMessageConverter();
//
// ObjectMapper objectMapper = new ObjectMapper();
// SimpleModule simpleModule = new SimpleModule();
// simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
// simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
// simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
// objectMapper.registerModule(simpleModule);
// jackson2HttpMessageConverter.setObjectMapper(objectMapper);
// converters.add(jackson2HttpMessageConverter);
// converters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
// }
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String avatarUtl = "file:" + avatar.replace("\\","/");
String pathUtl = "file:" + path.replace("\\","/");
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0);
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
}
}
......@@ -21,7 +21,7 @@ public interface QuartzJobService {
* @param pageable
* @return
*/
@Cacheable(keyGenerator = "keyGenerator")
@Cacheable
Object queryAll(JobQueryCriteria criteria, Pageable pageable);
/**
......
package me.zhengjie.modules.quartz.task;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import org.springframework.stereotype.Component;
/**
......
......@@ -25,6 +25,7 @@ public class ExecutionJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(this.getClass());
// 建议自定义线程池实现方式,该处仅供参考
private ExecutorService executorService = Executors.newSingleThreadExecutor();
@Override
......@@ -61,8 +62,7 @@ public class ExecutionJob extends QuartzJobBean {
// 任务状态 0:成功 1:失败
log.setIsSuccess(false);
log.setExceptionDetail(ThrowableUtil.getStackTrace(e));
//出错就暂停任务
quartzManage.pauseJob(quartzJob);
quartzJob.setIsPause(false);
//更新状态
quartzJobService.updateIsPause(quartzJob);
} finally {
......
package me.zhengjie.modules.quartz.utils;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.SpringContextHolder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
/**
* 执行定时任务
* @author
*/
@Slf4j
public class QuartzRunnable implements Runnable {
public class QuartzRunnable implements Callable {
private Object target;
private Method method;
......@@ -30,17 +32,13 @@ public class QuartzRunnable implements Runnable {
}
@Override
public void run() {
try {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
} catch (Exception e) {
log.error("定时任务执行失败",e);
public Object call() throws Exception {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
return null;
}
}
......@@ -106,6 +106,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 接口限流测试
.antMatchers("/test/**").anonymous()
// 文件
.antMatchers("/avatar/**").anonymous()
.antMatchers("/file/**").anonymous()
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").anonymous()
.antMatchers("/druid/**").anonymous()
......
......@@ -34,13 +34,23 @@ public class Menu implements Serializable {
@NotNull
private Long sort;
@NotBlank
@Column(name = "path")
private String path;
private String component;
@Column(unique = true)
private String componentName;
private String icon;
@Column(columnDefinition = "bit(1) default 0")
private Boolean cache;
@Column(columnDefinition = "bit(1) default 0")
private Boolean hidden;
/**
* 上级菜单ID
*/
......
......@@ -31,7 +31,9 @@ public class User implements Serializable {
@Column(unique = true)
private String username;
private String avatar;
@OneToOne
@JoinColumn(name = "avatar_id")
private UserAvatar userAvatar;
@NotBlank
@Pattern(regexp = "([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}",message = "格式错误")
......@@ -69,7 +71,6 @@ public class User implements Serializable {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", avatar='" + avatar + '\'' +
", email='" + email + '\'' +
", enabled=" + enabled +
", password='" + password + '\'' +
......
package me.zhengjie.modules.system.domain;
import cn.hutool.core.util.ObjectUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019年9月7日 16:16:59
*/
@Entity
@Table(name = "user_avatar")
@Data
@NoArgsConstructor
public class UserAvatar {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String realName;
private String path;
private String size;
public UserAvatar(UserAvatar userAvatar,String realName, String path, String size) {
this.id = ObjectUtil.isNotEmpty(userAvatar) ? userAvatar.getId() : null;
this.realName = realName;
this.path = path;
this.size = size;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment