This commit is contained in:
aoli.qu 2023-10-11 11:37:24 +08:00
commit af3b160551
146 changed files with 12566 additions and 0 deletions

173
pom.xml Normal file
View File

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dc</groupId>
<artifactId>welfare-api</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- springWeb -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.23</version>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.74</version>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!-- 此包一般在Servlet容器中都有提供 -->
<scope>provided</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- commons -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<!-- Excel -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,15 @@
package com.org;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
public class WelfareApplication {
public static void main(String[] args) {
SpringApplication.run(WelfareApplication.class, args);
}
}

View File

@ -0,0 +1,181 @@
package com.org.oss.controller;
import cn.hutool.core.util.IdUtil;
import com.org.oss.entity.SysOss;
import com.org.oss.service.SysOssService;
import com.org.system.annotation.Log;
import com.org.system.controller.BaseController;
import com.org.system.enums.BusinessType;
import com.org.utils.AjaxResult;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import com.org.utils.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("sys/oss")
public class SysOssController extends BaseController {
@Autowired
private SysOssService sysOssService;
/**
* 分页查询
*
* @return RestResponse
*/
@GetMapping("/list")
@PreAuthorize("@ss.hasPermi('sys:oss:list')")
@Log(title = "系统文件分页查询", businessType = BusinessType.SELECT)
public TableDataInfo getList(SysOss sysOss) {
log.info("SysOssController - getList sysOss:{}", sysOss);
startPage();
List<SysOss> list = sysOssService.queryList(sysOss);
return getDataTable(list);
}
/**
* 上传文件
*
* @param file file
* @return RestResponse
*/
@RequestMapping("/upload")
@PreAuthorize("@ss.hasPermi('sys:oss:edit')")
@Log(title = "系统文件上传", businessType = BusinessType.INSERT)
public Object upload(@RequestParam(value = "file", required = false) MultipartFile file,
@RequestParam(value = "sourceId", required = false) String sourceId,
@RequestParam(value = "fileType", required = false) String fileType) throws IOException {
if (null == file || file.isEmpty()) throw new CustomException("上传文件不能为空");
return sysOssService.upload(file, sourceId, fileType);
}
/**
* 上传图片-指定图片大小
*
* @param file file
* @return RestResponse
*/
@RequestMapping("/uploadImg")
@PreAuthorize("@ss.hasPermi('sys:oss:edit')")
@Log(title = "系统文件上传", businessType = BusinessType.INSERT)
public Object uploadImg(@RequestParam(value = "file", required = false) MultipartFile file,
@RequestParam(value = "sourceId", required = false) String sourceId,
@RequestParam(value = "fileType", required = false) String fileType,
@RequestParam(value = "fileSize", required = false) Long fileSize) throws IOException {
if (null == file || file.isEmpty()) throw new CustomException("上传文件不能为空");
if (null == fileSize) return sysOssService.upload(file, sourceId, fileType);
return sysOssService.uploadImg(file, sourceId, fileType, fileSize);
}
/**
* 文件上传-图片Base64
*
* @param base64
* @return
* @throws IOException
*/
@PostMapping("/upload/base64")
@PreAuthorize("@ss.hasPermi('sys:oss:edit')")
@Log(title = "系统文件上传-图片Base64", businessType = BusinessType.INSERT)
public Object uploadBase64(@RequestBody String base64) throws IOException {
if(StringUtils.isEmpty(base64)) throw new CustomException("上传文件Base64不能为空");
base64 = base64.substring(base64.indexOf(",")+1);
byte[] data = Base64.decodeBase64(base64);
String fileName = String.format("%s.%s", IdUtil.simpleUUID(), "png") ;
MultipartFile file = new MockMultipartFile(fileName, fileName, "application/x-png", data);
return sysOssService.upload(file, "", "");
}
/**
* 删除文件上传记录
*
* @param ids ids
* @return RestResponse
*/
@PostMapping("/delete")
@PreAuthorize("@ss.hasPermi('sys:oss:edit')")
@Log(title = "系统文件删除", businessType = BusinessType.DELETE)
public AjaxResult delete(@RequestBody Integer[] ids) {
log.info("SysOssController - delete ids:{}", ids);
sysOssService.delete(ids);
return AjaxResult.success();
}
/**
* 根据文件全路径数组删除上传文件
*
* @param urls
* @return
*/
@PostMapping("/deleteByUrl")
@PreAuthorize("@ss.hasPermi('sys:oss:edit')")
@Log(title = "系统文件删除", businessType = BusinessType.DELETE)
public AjaxResult deleteByUrl(@RequestBody String[] urls) {
log.info("SysOssController - deleteByUrl urls:{}", urls);
sysOssService.deleteByUrl(urls);
return AjaxResult.success();
}
/**
* 获取文件
*
* @param dateDir
* @param fileName
*/
@GetMapping(value = "/show/{dateDir}/{fileName}")
public void show(@PathVariable("dateDir") String dateDir, @PathVariable("fileName") String fileName) {
log.info("SysOssController - show dateDir:{}", dateDir);
log.info("SysOssController - show fileName:{}", fileName);
sysOssService.show(dateDir, fileName);
}
/**
* 根据文件ID获取文件
* @param id
*/
@GetMapping(value = "/show")
public void show(@RequestParam String id) {
log.info("SysOssController - show id:{}", id);
sysOssService.show(id);
}
/**
* COS工作流回调
* @param callbackStr
* @return
@PostMapping("/cos/callback")
public String cosCallback(@RequestBody String callbackStr){
log.info("SysOssController - cosCallback callbackStr:{}", callbackStr);
sysOssService.cosCallback(callbackStr);
return "ok";
}
*/
}

View File

@ -0,0 +1,28 @@
package com.org.oss.controller;
import com.org.system.controller.BaseController;
import com.org.utils.upload.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("common")
public class commonController extends BaseController {
/**
* 通用下载接口
*
* @param fileName
*/
@GetMapping("/download")
public void fileDownload(String fileName){
log.info("commonController - fileDownload fileName:{}", fileName);
CommonUtil.download(fileName, true);
}
}

View File

@ -0,0 +1,33 @@
package com.org.oss.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.org.system.entity.BaseEntity;
import lombok.Data;
@Data
public class SysOss extends BaseEntity {
/** 附件ID **/
@TableId(type = IdType.AUTO)
private String id;
/** 来源ID **/
private String sourceId;
/** 附件名称 **/
private String fileName;
/** 附件新名称 **/
private String newName;
/** 附件类型 **/
private String fileType;
/** 附件存放地址 **/
private String realPath;
/** URL地址 **/
private String url;
}

View File

@ -0,0 +1,22 @@
package com.org.oss.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.oss.entity.SysOss;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface SysOssMapper extends BaseMapper<SysOss> {
@Select("SELECT * FROM sys_oss WHERE url = #{fileUrl}")
SysOss findByUrl(@Param("fileUrl") String fileUrl);
@Select("SELECT * FROM sys_oss WHERE real_path = #{realPath}")
SysOss findByRealPath(@Param("realPath") String realPath);
@Select("select * from sys_oss where real_path like concat('%', #{suffix})")
List<SysOss> findByRealPathSuffix(@Param("suffix") String suffix);
}

View File

@ -0,0 +1,288 @@
package com.org.oss.service;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.oss.entity.SysOss;
import com.org.oss.mapper.SysOssMapper;
import com.org.system.enums.YesOrNoState;
import com.org.utils.AjaxResult;
import com.org.utils.SecurityUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import com.org.utils.upload.UpLoadUtil;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
@Service
public class SysOssService extends ServiceImpl<SysOssMapper, SysOss> {
/**
* 分页查询
*
* @param sysOss
* @return
*/
public List<SysOss> queryList(SysOss sysOss){
log.info("SysOssService - queryList sysOss:{}", sysOss);
LambdaQueryWrapper<SysOss> queryWrapper = new LambdaQueryWrapper<>();
if(StringUtils.isNotEmpty(sysOss.getFileName())) queryWrapper.like(SysOss::getFileName, sysOss.getFileName());
return list(queryWrapper);
}
/**
* 文件上传
*
* @param file
* @param sourceId
* @param fileType
* @return
* @throws IOException
*/
public AjaxResult upload(MultipartFile file, String sourceId, String fileType) throws IOException {
log.info("SysOssService - upload file:{}", file);
log.info("SysOssService - upload sourceId:{}", sourceId);
log.info("SysOssService - upload fileType:{}", fileType);
// 上传文件
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
String url = UpLoadUtil.uploadSuffix(file.getBytes(), suffix);
String[] urlArr = url.split("/");
String fileName = urlArr[urlArr.length - 1];
// String realPath = url.replace(UpLoadUtil.domain, "");
String realPath = url.replace(UpLoadUtil.proxyServer, "");
realPath = UpLoadUtil.diskPath + realPath;
// 保存文件信息
SysOss sysOss = new SysOss();
sysOss.setSourceId(sourceId);
sysOss.setFileName(file.getOriginalFilename());
sysOss.setNewName(fileName);
sysOss.setFileType(fileType);
sysOss.setRealPath(realPath);
sysOss.setUrl(url);
// 富文本上传图片 没带token 增加是否登录判断
if (SecurityUtil.isLogin()) sysOss.setCreateBy(SecurityUtil.getUserId());
sysOss.setCreateTime(new Date());
sysOss.setIsDelete(YesOrNoState.NO.getState());
save(sysOss);
// 返回兼容UEditor的参数
return AjaxResult.success().put("url", url)
.put("name", sysOss.getFileName())
.put("id", sysOss.getId())
.put("uid", sysOss.getId())
.put("createTime", sysOss.getCreateTime());
}
/**
* 删除文件上传记录
*
* @param ids
*/
public void delete(Integer[] ids){
log.info("SysOssService - delete ids:{}", ids);
for (Integer id : ids) {
try {
SysOss oss = getById(id);
log.info("SysOssService - delete oss:{}", oss);
FileUtil.del(oss.getRealPath());
} catch (Exception err) {
log.error("删除文件出现错误:" + id, err);
}
}
removeByIds(Arrays.asList(ids));
}
/**
* 根据文件全路径数组删除上传文件
*
* @param urls
*/
public void deleteByUrl(String[] urls){
log.info("SysOssService - deleteByUrl urls:{}", urls);
for (String url : urls) {
try {
LambdaQueryWrapper<SysOss> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysOss::getUrl, url);
SysOss sysOss = getOne(queryWrapper);
log.info("SysOssService - deleteByUrl sysOss:{}", sysOss);
FileUtil.del(sysOss.getRealPath());
removeById(sysOss.getId());
} catch (Exception err) {
log.error("删除文件出现错误:" + url, err);
}
}
}
public void show(String dateDir, String fileName){
log.info("SysOssService - show dateDir:{}", dateDir);
log.info("SysOssService - show fileName:{}", fileName);
fileName = UpLoadUtil.diskPath + "/" + dateDir + "/" + fileName;
log.info("SysOssService - show fileName:{}", fileName);
SysOss oss = findByRealPath(fileName);
// 如果是视频文件 则走视频文件方法
if(fileName.toLowerCase().endsWith("mp4") || fileName.toLowerCase().endsWith("flv")
|| fileName.toLowerCase().endsWith("avi") || fileName.toLowerCase().endsWith("rm")
|| fileName.toLowerCase().endsWith("rmvb") || fileName.toLowerCase().endsWith("wmv")
|| fileName.toLowerCase().endsWith("m3u8")) {
UpLoadUtil.getVideo(fileName);
return;
}
UpLoadUtil.getFile(fileName, oss.getFileName());
}
public void show(String id){
log.info("SysOssService - show id:{}", id);
SysOss oss = getById(id);
if(oss == null || StringUtils.isEmpty(oss.getId())) return ;
String fileName = oss.getRealPath();
log.info("SysOssService - show fileName:{}", fileName);
// 如果是视频文件 则走视频文件方法
if(fileName.toLowerCase().endsWith("mp4") || fileName.toLowerCase().endsWith("flv")
|| fileName.toLowerCase().endsWith("avi") || fileName.toLowerCase().endsWith("rm")
||fileName.toLowerCase().endsWith("rmvb") || fileName.toLowerCase().endsWith("wmv")) {
UpLoadUtil.getVideo(fileName);
return;
}
UpLoadUtil.getFile(fileName, oss.getFileName());
}
/**
* 通过url获取sysOss
* @param fileUrl
*/
public SysOss findByUrl(String fileUrl) {
log.info("SysOssService - findByUrl fileUrl:{}", fileUrl);
SysOss sysOss = baseMapper.findByUrl(fileUrl);
log.info("SysOssService - findByUrl sysOss:{}", sysOss);
if (sysOss == null || StringUtils.isNull(sysOss.getId())) throw new CustomException("文件未找到!");
return sysOss;
}
/**
* 通过url获取sysOss
* @param realPath
*/
public SysOss findByRealPath(String realPath) {
log.info("SysOssService - findByRealPath realPath:{}", realPath);
SysOss sysOss = baseMapper.findByRealPath(realPath);
log.info("SysOssService - findByRealPath sysOss:{}", sysOss);
if (sysOss == null || StringUtils.isNull(sysOss.getId())) throw new CustomException("文件未找到!");
return sysOss;
}
public AjaxResult uploadImg(MultipartFile file, String sourceId, String fileType, long fileSize) throws IOException {
log.info("SysOssService - uploadImg file:{}", file);
log.info("SysOssService - uploadImg sourceId:{}", sourceId);
log.info("SysOssService - uploadImg fileType:{}", fileType);
log.info("SysOssService - uploadImg fileSize:{}", fileSize);
// 上传文件
/*//压缩图片到指定大小以内
byte[] bytes = PicUtils.compressPicForScale(file.getBytes(), fileSize);
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
String suffix = ".jpg";*/
// 上传文件
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
String url = UpLoadUtil.uploadSuffix(file.getBytes(), suffix);
String[] urlArr = url.split("/");
String fileName = urlArr[urlArr.length - 1];
String realPath = url.replace(UpLoadUtil.proxyServer, "");
realPath = UpLoadUtil.diskPath + realPath;
// String realPath = url.replace(UpLoadUtil.domain, "");
String originalFilename = file.getOriginalFilename();
String suffix1 = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
originalFilename = originalFilename.substring(0, originalFilename.lastIndexOf(".")) + suffix1;
// 保存文件信息
SysOss sysOss = new SysOss();
sysOss.setSourceId(sourceId);
sysOss.setFileName(originalFilename);
sysOss.setNewName(fileName);
sysOss.setFileType(fileType);
sysOss.setRealPath(realPath);
sysOss.setUrl(url);
sysOss.setCreateBy(SecurityUtil.getUserId());
sysOss.setCreateTime(new Date());
sysOss.setIsDelete(YesOrNoState.NO.getState());
save(sysOss);
// 返回兼容UEditor的参数
return AjaxResult.success().put("url", url)
.put("name", sysOss.getFileName())
.put("id", sysOss.getId())
.put("uid", sysOss.getId())
.put("createTime", sysOss.getCreateTime());
}
/**
* COS工作流回调
* @param callbackStr
public void cosCallback(String callbackStr) {
log.info("SysOssService - cosCallback callbackStr:{}", callbackStr);
JSONObject jsonObject = JSONUtil.parseObj(callbackStr);
JSONObject workflowExecution = jsonObject.getJSONObject("WorkflowExecution");
String state = workflowExecution.getStr("State");
log.info("SysOssService - cosCallback state:{}", state);
if(!"Success".equals(state)) return;
String object = workflowExecution.getStr("Object");
log.info("SysOssService - cosCallback object:{}", object);
if(Validator.isNotEmpty(object)){
String url = object;
String bakUrl = String.format("%s_bak%s", object.substring(0, object.lastIndexOf(".")), object.substring(object.lastIndexOf(".")));
String transcodingUrl = String.format("%s_transcoding%s", object.substring(0, object.lastIndexOf(".")), object.substring(object.lastIndexOf(".")));
log.info("SysOssService - cosCallback url:{}", url);
log.info("SysOssService - cosCallback bakUrl:{}", bakUrl);
log.info("SysOssService - cosCallback transcodingUrl:{}", transcodingUrl);
// 备份源视频文件
UpLoadUtil.copyObject(url, bakUrl);
UpLoadUtil.deleteObject(url);
// 转移转码后的视频文件
UpLoadUtil.copyObject(transcodingUrl, url);
UpLoadUtil.deleteObject(transcodingUrl);
}
}
*/
}

View File

@ -0,0 +1,13 @@
package com.org.system.annotation;
import java.lang.annotation.*;
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface CheckVerify {
public String phone() default "";
public String type() default "";
public String code() default "";
}

View File

@ -0,0 +1,142 @@
package com.org.system.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
/**
* 自定义导出Excel数据注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
/**
* 导出时在excel中排序
*/
public int sort() default Integer.MAX_VALUE;
/**
* 导出到Excel中的名字.
*/
public String name() default "";
/**
* 日期格式, : yyyy-MM-dd
*/
public String dateFormat() default "";
/**
* 如果是字典类型请设置字典的type值 (: sys_user_sex)
*/
public String dictType() default "";
/**
* 读取内容转表达式 (: 0=,1=,2=未知)
*/
public String readConverterExp() default "";
/**
* 分隔符读取字符串组内容
*/
public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出类型0数字 1字符串
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出时在excel中每个列的高度 单位为字符
*/
public double height() default 14;
/**
* 导出时在excel中每个列的宽 单位为字符
*/
public double width() default 16;
/**
* 文字后缀,% 90 变成90%
*/
public String suffix() default "";
/**
* 当值为空时,字段的默认值
*/
public String defaultValue() default "";
/**
* 提示信息
*/
public String prompt() default "";
/**
* 设置只能选择不能输入的列内容.
*/
public String[] combo() default {};
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
public boolean isExport() default true;
/**
* 另一个类中的属性名称,支持多级获取,以小数点隔开
*/
public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/**
* 字段类型0导出导入1仅导出2仅导入
*/
Type type() default Type.ALL;
public enum Type
{
ALL(0), EXPORT(1), IMPORT(2);
private final int value;
Type(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
public enum ColumnType
{
NUMERIC(0), STRING(1);
private final int value;
ColumnType(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
}

View File

@ -0,0 +1,18 @@
package com.org.system.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel注解集
*
* @author ruoyi
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
Excel[] value();
}

View File

@ -0,0 +1,26 @@
package com.org.system.annotation;
import com.org.system.enums.BusinessType;
import com.org.system.enums.OperatorType;
import java.lang.annotation.*;
/** 自定义操作日志记录注解 **/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/** 模块 **/
public String title() default "";
/** 功能 **/
public BusinessType businessType() default BusinessType.OTHER;
/** 操作人类别 **/
public OperatorType operatorType() default OperatorType.MANAGE;
/** 是否保存请求的参数 **/
public boolean isSaveRequestData() default true;
}

View File

@ -0,0 +1,198 @@
package com.org.system.aspectj;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.org.system.annotation.Log;
import com.org.system.config.async.AsyncFactory;
import com.org.system.config.async.AsyncManager;
import com.org.system.entity.LoginUser;
import com.org.system.entity.SysOperLog;
import com.org.system.enums.BusinessStatus;
import com.org.system.service.TokenService;
import com.org.utils.HttpServletUtil;
import com.org.utils.SpringUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
/** 操作日志记录处理 **/
@Aspect
@Component
public class LogAspect
{
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
// 配置织入点
@Pointcut("@annotation(com.org.system.annotation.Log)")
public void logPointCut() { }
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
{
handleLog(joinPoint, null, jsonResult);
}
/**
* 拦截异常操作
*
* @param joinPoint 切点
* @param e 异常
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) { handleLog(joinPoint, e, null); }
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
try {
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) return;
// 获取当前的用户
LoginUser loginUser = SpringUtil.getBean(TokenService.class).getLoginUser(HttpServletUtil.getRequest());
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
// 请求的地址
operLog.setOperIp(ServletUtil.getClientIP(HttpServletUtil.getRequest(), ""));
// 返回参数
operLog.setJsonResult(JSON.toJSONString(jsonResult));
operLog.setOperUrl(HttpServletUtil.getRequest().getRequestURI());
if (loginUser != null) operLog.setOperName(loginUser.getUser().getUserName());
if (e != null) {
operLog.setStatus(BusinessStatus.FAIL.ordinal());
operLog.setErrorMsg(StrUtil.subWithLength(e.getMessage(), 0, 2000));
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// 设置请求方式
operLog.setRequestMethod(HttpServletUtil.getRequest().getMethod());
// 处理设置注解上的参数
getControllerMethodDescription(joinPoint, controllerLog, operLog);
operLog.setOperTime(new Date());
// 保存数据库
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp);
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param log 日志
* @param operLog 操作日志
* @throws Exception
*/
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception {
// 设置action动作
operLog.setBusinessType(log.businessType().ordinal());
// 设置标题
operLog.setTitle(log.title());
// 设置操作人类别
operLog.setOperatorType(log.operatorType().ordinal());
// 是否需要保存request参数和值
if (log.isSaveRequestData()) {
// 获取参数的信息传入到数据库中
setRequestValue(joinPoint, operLog);
}
}
/**
* 获取请求的参数放到log中
*
* @param operLog 操作日志
* @throws Exception 异常
*/
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception {
String requestMethod = operLog.getRequestMethod();
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StrUtil.subWithLength(params, 0, 2000));
} else {
Map<?, ?> paramsMap = (Map<?, ?>) HttpServletUtil.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
operLog.setOperParam(StrUtil.subWithLength(paramsMap.toString(), 0, 2000));
}
}
/**
* 是否存在注解如果存在就获取
*/
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(Log.class);
}
return null;
}
/**
* 参数拼装
*/
private String argsArrayToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null && paramsArray.length > 0) {
for (int i = 0; i < paramsArray.length; i++) {
if (!isFilterObject(paramsArray[i])) {
Object jsonObj = null;
try {
jsonObj = JSON.toJSON(paramsArray[i]);
} catch (Exception e){
log.error("{}", e);
}
if(jsonObj != null) params.append(jsonObj.toString()).append(" ");
}
}
}
return params.toString().trim();
}
/**
* 判断是否需要过滤的对象
*
* @param o 对象信息
* @return 如果是需要过滤的对象则返回true否则返回false
*/
public boolean isFilterObject(final Object o) {
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
}
}

View File

@ -0,0 +1,76 @@
package com.org.system.config.async;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.org.system.entity.SysOperLog;
import com.org.system.service.SysOperLogService;
import com.org.utils.Constants;
import com.org.utils.HttpServletUtil;
import com.org.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.TimerTask;
/** 异步工厂(产生任务用) **/
@Slf4j
public class AsyncFactory {
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息
* @param args 列表
* @return 任务task
*/
public static TimerTask recordLogininfor(final String username, final String status, final String message,
final Object... args) {
final UserAgent userAgent = UserAgentUtil.parse(HttpServletUtil.getRequest().getHeader("User-Agent"));
final String ip = ServletUtil.getClientIP(HttpServletUtil.getRequest(), "");
return new TimerTask() {
@Override
public void run() {
String address = "";
String os = userAgent.getOs().getName(); // 获取客户端操作系统
String browser = userAgent.getBrowser().getName(); // 获取客户端浏览器
// 封装对象
SysOperLog sysOperLog = new SysOperLog();
sysOperLog.setTitle("用户登陆");
sysOperLog.setMethod("/login");
sysOperLog.setRequestMethod(HttpServletUtil.getRequest().getMethod());
sysOperLog.setOperName(username);
sysOperLog.setOperIp(ip);
sysOperLog.setOperLocation(address);
sysOperLog.setErrorMsg(browser+";"+os+";"+message);
sysOperLog.setOperTime(new Date());
// 日志状态
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status)) sysOperLog.setStatus(Integer.parseInt(Constants.SUCCESS));
else if (Constants.LOGIN_FAIL.equals(status)) sysOperLog.setStatus(Integer.parseInt(Constants.FAIL));
// 插入数据
SpringUtil.getBean(SysOperLogService.class).save(sysOperLog);
}
};
}
/**
* 操作日志记录
*
* @param sysOperLog 操作日志信息
* @return 任务task
*/
public static TimerTask recordOper(final SysOperLog sysOperLog) {
return new TimerTask() {
@Override
public void run() {
// 远程查询操作地点
SpringUtil.getBean(SysOperLogService.class).save(sysOperLog);
}
};
}
}

View File

@ -0,0 +1,54 @@
package com.org.system.config.async;
import com.org.utils.HttpServletUtil;
import com.org.utils.SpringUtil;
import com.org.utils.Threads;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** 异步任务管理器 **/
public class AsyncManager
{
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 异步操作任务调度线程池
*/
private ScheduledExecutorService executor = SpringUtil.getBean("scheduledExecutorService");
/**
* 单例模式
*/
private AsyncManager(){}
private static AsyncManager me = new AsyncManager();
public static AsyncManager me()
{
return me;
}
/**
* 执行任务
*
* @param task 任务
*/
public void execute(TimerTask task) {
RequestContextHolder.setRequestAttributes(HttpServletUtil.getServletRequestAttributes(), true);
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
/**
* 停止任务线程池
*/
public void shutdown()
{
Threads.shutdownAndAwaitTermination(executor);
}
}

View File

@ -0,0 +1,10 @@
package com.org.system.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class config {
}

View File

@ -0,0 +1,204 @@
package com.org.system.config.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/** spring redis 工具类 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache {
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection) {
return redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> long setCacheList(final String key, final List<T> dataList) {
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
return count == null ? 0 : count;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(final String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> long setCacheSet(final String key, final Set<T> dataSet) {
Long count = redisTemplate.opsForSet().add(key, dataSet);
return count == null ? 0 : count;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) redisTemplate.opsForHash().putAll(key, dataMap);
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
}

View File

@ -0,0 +1,28 @@
package com.org.system.config.security;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.ContentType;
import com.alibaba.fastjson.JSONObject;
import com.org.utils.AjaxResult;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
/** 认证失败处理类 返回未授权 **/
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = 1L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
String msg = String.format("请求访问:%s认证失败无法访问系统资源", request.getRequestURI());
ServletUtil.write(response, JSONObject.toJSONString(AjaxResult.error(HttpStatus.UNAUTHORIZED.value(), msg)), ContentType.JSON.toString(Charset.defaultCharset()));
}
}

View File

@ -0,0 +1,39 @@
package com.org.system.config.security;
import com.org.system.entity.LoginUser;
import com.org.system.service.TokenService;
import com.org.utils.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** token过滤器 验证token有效性 **/
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private TokenService tokenService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
LoginUser loginUser = tokenService.getLoginUser(request);
if (null != loginUser && null == SecurityUtil.getAuthentication()) {
tokenService.verifyToken(loginUser);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
chain.doFilter(request, response);
}
}

View File

@ -0,0 +1,51 @@
package com.org.system.config.security;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.ContentType;
import com.alibaba.fastjson.JSONObject;
import com.org.system.config.async.AsyncFactory;
import com.org.system.config.async.AsyncManager;
import com.org.system.entity.LoginUser;
import com.org.system.service.TokenService;
import com.org.utils.AjaxResult;
import com.org.utils.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;
/** 自定义退出处理类 返回成功 **/
@Configuration
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
{
@Autowired
private TokenService tokenService;
/**
* 退出处理
*
* @return
*/
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
LoginUser loginUser = tokenService.getLoginUser(request);
if (null != loginUser) {
String userName = loginUser.getUsername();
// 删除用户缓存记录
tokenService.delLoginUser(loginUser.getToken());
// 记录用户退出日志
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
}
ServletUtil.write(response, JSONObject.toJSONString(AjaxResult.success("退出成功")), ContentType.JSON.toString(Charset.defaultCharset()));
}
}

View File

@ -0,0 +1,67 @@
package com.org.system.config.security;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
@Slf4j
public class Md5PasswordEncoder implements PasswordEncoder {
private String salt;
public void setSalt(String salt) {
this.salt = salt;
}
private static Md5PasswordEncoder instance = new Md5PasswordEncoder();
private Md5PasswordEncoder() {
}
//以单例模式构造
public static Md5PasswordEncoder getInstance() {
return instance;
}
// 用户密码加盐
private String mergePasswordAndSalt(CharSequence password) {
if (password == null) password = "";
if ((salt == null) || "".equals(salt)) {
return password.toString();
} else {
return password + salt;
}
}
/**
* MD5加密
*
* @param rawPassword 原始密码
* @return 加密后的md5密文
*/
@Override
public String encode(CharSequence rawPassword) {
String result = null;
try {
String passwordAndSalt = mergePasswordAndSalt(rawPassword);
result = SecureUtil.md5(passwordAndSalt);
} catch (Exception ignored) {
}
return result;
}
/**
* 密码比较
*
* @param rawPassword 原始密码
* @param encodedPassword 加密后的密码
* @return boolean
*/
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equalsIgnoreCase(encode(rawPassword));
}
}

View File

@ -0,0 +1,124 @@
package com.org.system.config.security;
import com.org.system.service.CustomUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/** spring security配置 **/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
/** 自定义用户认证逻辑 **/
@Autowired
private CustomUserService customUserService;
/** 认证失败处理类 **/
@Autowired
private AuthenticationEntryPointImpl unauthorizedHandler;
/** 退出处理类 **/
@Autowired
private LogoutSuccessHandlerImpl logoutSuccessHandler;
/** token认证过滤器 **/
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
/**
* 解决 无法直接注入 AuthenticationManager
*
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* anyRequest | 匹配所有请求路径
* access | SpringEl表达式结果为true时可以访问
* anonymous | 匿名可以访问
* denyAll | 用户不能访问
* fullyAuthenticated | 用户完全认证可以访问非remember-me下自动登录
* hasAnyAuthority | 如果有参数参数表示权限则其中任何一个权限可以访问
* hasAnyRole | 如果有参数参数表示角色则其中任何一个角色可以访问
* hasAuthority | 如果有参数参数表示权限则其权限可以访问
* hasIpAddress | 如果有参数参数表示IP地址如果用户IP和参数匹配则可以访问
* hasRole | 如果有参数参数表示角色则其角色可以访问
* permitAll | 用户可以任意访问
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
// CSRF禁用因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录 login 允许匿名访问
.antMatchers("/login").anonymous()
.antMatchers("/person/register/invitation").anonymous()
.antMatchers("/person/register/add").anonymous()
// 文件下载接口例外
.antMatchers("/sys/oss/show/**").anonymous()
.antMatchers("/common/download").anonymous()
.antMatchers("/sys/ueditor/config").anonymous()
// 获取短信验证码接口
.antMatchers("/sys/sms/getCode").anonymous()
// 获取数据词典项下拉选
.antMatchers("/sys/dictionary/item/mobile/dropDown").anonymous()
// 获取app版本管理相关信息
.antMatchers("/sys/appVersion/getVersionNumByAppType","/sys/appVersion/clearVersionCache").anonymous()
// COS队列回调
// .antMatchers("/sys/oss/cos/callback").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
// httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
// httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
/**
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); }
@Bean
public Md5PasswordEncoder passwordEncoder(){ return Md5PasswordEncoder.getInstance(); }
/** 身份认证接口 **/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/** user Details Service验证 **/
auth.userDetailsService(customUserService).passwordEncoder(passwordEncoder());
}
}

View File

@ -0,0 +1,56 @@
package com.org.system.config.thread;
import com.org.utils.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/** 线程池配置 **/
@Configuration
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}

View File

@ -0,0 +1,7 @@
package com.org.system.config.validation;
import javax.validation.groups.Default;
/** 分组校验 新增 **/
public interface Insert extends Default {
}

View File

@ -0,0 +1,7 @@
package com.org.system.config.validation;
import javax.validation.groups.Default;
/** 分组校验 修改 **/
public interface Update extends Default {
}

View File

@ -0,0 +1,118 @@
package com.org.system.config.xss;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HTMLFilter;
/** 转义和反转义工具类 **/
public class EscapeUtil {
public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
private static final char[][] TEXT = new char[64][];
static {
for (int i = 0; i < 64; i++) {
TEXT[i] = new char[] { (char) i };
}
// special HTML characters
TEXT['\''] = "&#039;".toCharArray(); // 单引号
TEXT['"'] = "&#34;".toCharArray(); // 单引号
TEXT['&'] = "&#38;".toCharArray(); // &
TEXT['<'] = "&#60;".toCharArray(); // 小于号
TEXT['>'] = "&#62;".toCharArray(); // 大于号
}
/**
* 转义文本中的HTML字符为安全的字符
*
* @param text 被转义的文本
* @return 转义后的文本
*/
public static String escape(String text) {
return encode(text);
}
/**
* 还原被转义的HTML特殊字符
*
* @param content 包含转义符的HTML内容
* @return 转换后的字符串
*/
public static String unescape(String content) {
return decode(content);
}
/**
* 清除所有HTML标签但是不删除标签内的内容
*
* @param content 文本
* @return 清除标签后的文本
*/
public static String clean(String content) {
return new HTMLFilter().filter(content);
}
/**
* Escape编码
*
* @param text 被编码的文本
* @return 编码后的字符
*/
private static String encode(String text) {
int len;
if ((text == null) || ((len = text.length()) == 0)) {
return StrUtil.EMPTY;
}
StringBuilder buffer = new StringBuilder(len + (len >> 2));
char c;
for (int i = 0; i < len; i++) {
c = text.charAt(i);
if (c < 64) {
buffer.append(TEXT[c]);
} else {
buffer.append(c);
}
}
return buffer.toString();
}
/**
* Escape解码
*
* @param content 被转义的内容
* @return 解码后的字符串
*/
public static String decode(String content)
{
if (StrUtil.isEmpty(content)) {
return content;
}
StringBuilder tmp = new StringBuilder(content.length());
int lastPos = 0, pos = 0;
char ch;
while (lastPos < content.length()) {
pos = content.indexOf("%", lastPos);
if (pos == lastPos) {
if (content.charAt(pos + 1) == 'u') {
ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
tmp.append(ch);
lastPos = pos + 6;
} else {
ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
tmp.append(ch);
lastPos = pos + 3;
}
} else {
if (pos == -1) {
tmp.append(content.substring(lastPos));
lastPos = content.length();
} else {
tmp.append(content.substring(lastPos, pos));
lastPos = pos;
}
}
}
return tmp.toString();
}
}

View File

@ -0,0 +1,53 @@
package com.org.system.config.xss;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
import java.util.HashMap;
import java.util.Map;
/** Filter配置 **/
@Configuration
public class FilterConfig {
@Value("${xss.enabled}")
private String enabled;
@Value("${xss.excludes}")
private String excludes;
@Value("${xss.urlPatterns}")
private String urlPatterns;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean xssFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns(urlPatterns.split(","));
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", excludes);
initParameters.put("enabled", enabled);
registration.setInitParameters(initParameters);
return registration;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean someFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatableFilter());
registration.addUrlPatterns("/*");
registration.setName("repeatableFilter");
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
return registration;
}
}

View File

@ -0,0 +1,39 @@
package com.org.system.config.xss;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
/** 通用http工具封装 **/
@Slf4j
public class HttpHelper {
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream()) {
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
log.warn("getBodyString出现问题");
log.error("{}", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
log.error("{}", e);
}
}
}
return sb.toString();
}
}

View File

@ -0,0 +1,38 @@
package com.org.system.config.xss;
import cn.hutool.core.util.StrUtil;
import org.springframework.http.MediaType;
import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/** Repeatable 过滤器 **/
public class RepeatableFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest && StrUtil.equalsAnyIgnoreCase(request.getContentType(),
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE)) {
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
if (null == requestWrapper) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
}
}

View File

@ -0,0 +1,57 @@
package com.org.system.config.xss;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/** 构建可重复读取inputStream的request **/
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
super(request);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
body = HttpHelper.getBodyString(request).getBytes("UTF-8");
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}

View File

@ -0,0 +1,73 @@
package com.org.system.config.xss;
import cn.hutool.core.util.StrUtil;
import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** 防止XSS攻击的过滤器 **/
public class XssFilter implements Filter {
/** 排除链接 **/
public List<String> excludes = new ArrayList<>();
/** xss过滤开关 **/
public boolean enabled = false;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String tempExcludes = filterConfig.getInitParameter("excludes");
String tempEnabled = filterConfig.getInitParameter("enabled");
if (StrUtil.isNotEmpty(tempExcludes)) {
String[] url = tempExcludes.split(",");
for (int i = 0; url != null && i < url.length; i++) {
excludes.add(url[i]);
}
}
if (StrUtil.isNotEmpty(tempEnabled)) {
enabled = Boolean.valueOf(tempEnabled);
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp)) {
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
if (!enabled) {
return true;
}
if (excludes == null || excludes.isEmpty()) {
return false;
}
String url = request.getServletPath();
for (String pattern : excludes) {
Pattern p = Pattern.compile("^" + pattern);
Matcher m = p.matcher(url);
if (m.find()) {
return true;
}
}
return false;
}
@Override
public void destroy() {
}
}

View File

@ -0,0 +1,86 @@
package com.org.system.config.xss;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/** XSS过滤处理 **/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* @param request
*/
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null) {
int length = values.length;
String[] escapseValues = new String[length];
for (int i = 0; i < length; i++) {
// 防xss攻击和过滤前后空格
escapseValues[i] = EscapeUtil.clean(values[i]).trim();
}
return escapseValues;
}
return super.getParameterValues(name);
}
@Override
public ServletInputStream getInputStream() throws IOException {
// 非json类型直接返回
if (!isJsonRequest()) {
return super.getInputStream();
}
// 为空直接返回
String json = IOUtils.toString(super.getInputStream(), "utf-8");
if (StrUtil.isEmpty(json)) {
return super.getInputStream();
}
// xss过滤
json = EscapeUtil.clean(json).trim();
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bis.read();
}
};
}
/**
* 是否是Json请求
*
*/
public boolean isJsonRequest() {
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(header)
|| MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(header);
}
}

View File

@ -0,0 +1,87 @@
package com.org.system.controller;
import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.org.utils.AjaxResult;
import com.org.utils.SqlUtil;
import com.org.utils.StringUtils;
import com.org.utils.page.PageDomain;
import com.org.utils.page.TableDataInfo;
import com.org.utils.page.TableSupport;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
/** web层通用数据处理 **/
public class BaseController {
/**
* 将前台传递过来的日期格式的字符串自动转化为Date类型
*
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(DateUtil.parseDate(text));
}
});
}
/**
* 设置请求分页数据
*
*/
protected void startPage() {
PageDomain pageDomain = TableSupport.buildPageRequest();
Integer pageNum = pageDomain.getPageNum();
Integer pageSize = pageDomain.getPageSize();
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.startPage(pageNum, pageSize, orderBy);
}
}
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected TableDataInfo getDataTable(List<?> list) {
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.OK.value());
rspData.setMsg("查询成功");
rspData.setRows(list);
rspData.setTotal(new PageInfo(list).getTotal());
rspData.setPageNo(TableSupport.buildPageRequest().getPageNum());
return rspData;
}
/**
* 响应返回结果
*
* @param rows 影响行数
* @return 操作结果
*/
protected AjaxResult toAjax(int rows) {
return rows > 0 ? AjaxResult.success() : AjaxResult.error();
}
protected AjaxResult toAjax(boolean bz) {
return bz == true ? AjaxResult.success() : AjaxResult.error();
}
/**
* 页面跳转
*/
public String redirect(String url) {
return StringUtils.format("redirect:{}", url);
}
}

View File

@ -0,0 +1,87 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.config.validation.Update;
import com.org.system.entity.SysDataDictionary;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysDataDictionaryService;
import com.org.utils.AjaxResult;
import com.org.utils.StringUtils;
import com.org.utils.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("sys/dictionary")
public class SysDataDictionaryController extends BaseController {
@Autowired
private SysDataDictionaryService sysDataDictionaryService;
// 新增
@PostMapping("/add")
@PreAuthorize("@ss.hasPermi('sys:dictionary:edit')")
@Log(title = "词典分类新增", businessType = BusinessType.INSERT)
public AjaxResult add(@RequestBody @Validated SysDataDictionary sysDataDictionary){
log.info("SysDataDictionaryController - add sysDataDictionary:{}", sysDataDictionary);
return toAjax(sysDataDictionaryService.saveOrUpdate(sysDataDictionary));
}
// 详情
@PostMapping("/get")
@PreAuthorize("@ss.hasPermi('sys:dictionary:get')")
@Log(title = "词典分类详情", businessType = BusinessType.UPDATE)
public AjaxResult get(@RequestParam Long id){
log.info("SysDataDictionaryController - get id:{}", id);
return AjaxResult.success(sysDataDictionaryService.getById(id));
}
// 修改
@PostMapping("/edit")
@PreAuthorize("@ss.hasPermi('sys:dictionary:edit')")
@Log(title = "词典分类修改", businessType = BusinessType.UPDATE)
public AjaxResult edit(@RequestBody @Validated(Update.class) SysDataDictionary sysDataDictionary){
log.info("SysDataDictionaryController - edit sysDataDictionary:{}", sysDataDictionary);
return toAjax(sysDataDictionaryService.saveOrUpdate(sysDataDictionary));
}
// 删除
@PostMapping("/del")
@PreAuthorize("@ss.hasPermi('sys:dictionary:del')")
@Log(title = "词典分类删除", businessType = BusinessType.DELETE)
public AjaxResult del(@RequestParam String ids, @RequestParam String deleteReason){
log.info("SysDataDictionaryController - del ids:{}", ids);
log.info("SysDataDictionaryController - del deleteReason:{}", deleteReason);
if(StringUtils.isEmpty(ids)) return AjaxResult.success();
List<Long> idList = Arrays.asList(ids.split(",")).stream().map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
return toAjax(sysDataDictionaryService.del(idList, deleteReason));
}
// 列表
@GetMapping("/pageList")
@PreAuthorize("@ss.hasPermi('sys:dictionary:list')")
@Log(title = "词典分类列表", businessType = BusinessType.SELECT)
public TableDataInfo list(SysDataDictionary sysDataDictionary){
log.info("SysDataDictionaryController - list sysDataDictionary:{}", sysDataDictionary);
startPage();
List<SysDataDictionary> list = sysDataDictionaryService.findList(sysDataDictionary);
return getDataTable(list);
}
}

View File

@ -0,0 +1,137 @@
package com.org.system.controller;
import cn.hutool.core.lang.Dict;
import com.org.system.annotation.Log;
import com.org.system.config.validation.Update;
import com.org.system.entity.SysDataDictionaryItem;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysDataDictionaryItemService;
import com.org.utils.AjaxResult;
import com.org.utils.StringUtils;
import com.org.utils.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("sys/dictionary/item")
public class SysDataDictionaryItemController extends BaseController {
@Autowired
private SysDataDictionaryItemService sysDataDictionaryItemService;
// 新增
@PostMapping("/add")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:edit')")
@Log(title = "词典项新增", businessType = BusinessType.INSERT)
public AjaxResult add(@RequestBody @Validated SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemController - add sysDataDictionaryItem:{}", sysDataDictionaryItem);
return toAjax(sysDataDictionaryItemService.saveOrUpdate(sysDataDictionaryItem));
}
// 详情
@PostMapping("/get")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:get')")
@Log(title = "词典项详情", businessType = BusinessType.UPDATE)
public AjaxResult get(@RequestParam Long id){
log.info("SysDataDictionaryItemController - get id:{}", id);
return AjaxResult.success(sysDataDictionaryItemService.getById(id));
}
// 修改
@PostMapping("/edit")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:edit')")
@Log(title = "词典项修改", businessType = BusinessType.UPDATE)
public AjaxResult edit(@RequestBody @Validated(Update.class) SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemController - edit sysDataDictionaryItem:{}", sysDataDictionaryItem);
return toAjax(sysDataDictionaryItemService.saveOrUpdate(sysDataDictionaryItem));
}
// 删除
@PostMapping("/del")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:del')")
@Log(title = "词典项删除", businessType = BusinessType.DELETE)
public AjaxResult del(@RequestParam String ids, @RequestParam String deleteReason){
log.info("SysDataDictionaryItemController - del ids:{}", ids);
log.info("SysDataDictionaryItemController - del deleteReason:{}", deleteReason);
if(StringUtils.isEmpty(ids)) return AjaxResult.success();
List<Long> idList = Arrays.asList(ids.split(",")).stream().map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
return toAjax(sysDataDictionaryItemService.del(idList, deleteReason));
}
// 列表
@GetMapping("/pageList")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:list')")
@Log(title = "词典项列表", businessType = BusinessType.SELECT)
public TableDataInfo pageList(SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemController - pageList sysDataDictionaryItem:{}", sysDataDictionaryItem);
startPage();
List<SysDataDictionaryItem> list = sysDataDictionaryItemService.findList(sysDataDictionaryItem);
return getDataTable(list);
}
// 列表
@GetMapping("/list")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:list')")
@Log(title = "词典项列表", businessType = BusinessType.SELECT)
public AjaxResult list(SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemController - list sysDataDictionaryItem:{}", sysDataDictionaryItem);
List<SysDataDictionaryItem> list = sysDataDictionaryItemService.findList(sysDataDictionaryItem);
return AjaxResult.success(list);
}
// 查询最大词典项值
@GetMapping("/findMaxValue")
@PreAuthorize("@ss.hasPermi('sys:dictionary:item:list')")
@Log(title = "查询最大词典项值", businessType = BusinessType.SELECT)
public AjaxResult findMaxValue(SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemController - findMaxValue sysDataDictionaryItem:{}", sysDataDictionaryItem);
if(StringUtils.isEmpty(sysDataDictionaryItem.getDictionaryCode())) return AjaxResult.error("词典项标识不能为空");
Integer maxValue = sysDataDictionaryItemService.findMaxValueByCode(sysDataDictionaryItem.getDictionaryCode());
log.info("SysDataDictionaryItemController - findMaxValue sysDataDictionaryItem:{},maxValue:{}", sysDataDictionaryItem, maxValue);
return AjaxResult.success(maxValue);
}
// 词典项下拉选
@GetMapping("/dropDown")
@Log(title = "词典项下拉选", businessType = BusinessType.SELECT)
public AjaxResult dropDown(String dictionaryCode){
log.info("SysDataDictionaryItemController - dropDown dictionaryCode:{}", dictionaryCode);
List<Dict> list = sysDataDictionaryItemService.listByCode(dictionaryCode);
return AjaxResult.success(list);
}
// 词典项下拉选
@GetMapping("/mobile/dropDown")
@Log(title = "词典项下拉选", businessType = BusinessType.SELECT)
public AjaxResult dropDownNoToken(String dictionaryCode){
log.info("SysDataDictionaryItemController - dropDown dictionaryCode:{}", dictionaryCode);
List<Dict> list = sysDataDictionaryItemService.listByCode(dictionaryCode);
return AjaxResult.success(list);
}
}

View File

@ -0,0 +1,72 @@
package com.org.system.controller;
import cn.hutool.core.util.StrUtil;
import com.org.system.annotation.Log;
import com.org.system.entity.LoginBody;
import com.org.system.entity.vo.PersonVo;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysLoginService;
import com.org.utils.AjaxResult;
import com.org.utils.Constants;
import com.org.utils.SecurityUtil;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
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.RestController;
import java.util.Map;
/** 登录验证 **/
@Slf4j
@RestController
public class SysLoginController {
@Autowired
private SysLoginService sysLoginService;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@PostMapping("/login")
@Log(title = "登陆系统", businessType = BusinessType.LOGIN)
public AjaxResult login(@RequestBody LoginBody loginBody) {
log.info("SysLoginController - login loginBody:{}", loginBody);
if(loginBody == null) throw new CustomException("未找到登陆信息");
if(StrUtil.isEmpty(loginBody.getUsername()) || StrUtil.isEmpty(loginBody.getPassword()))
throw new CustomException("用户名或密码不能为空");
// 生成令牌
Map<String, String> result = sysLoginService.login(loginBody, true);
return AjaxResult.success().put(Constants.TOKEN, result.get("token"))
.put("identity", result.get("identity"));
}
@PostMapping("/getLoginUser")
@Log(title = "获取当前登录用户信息", businessType = BusinessType.LOGIN)
public AjaxResult getLoginUser(){
log.info("SysLoginController - getLoginUser userId:{}", SecurityUtil.getUserId());
sysLoginService.setLoginUserRole();
return AjaxResult.success(SecurityUtil.getLoginUser());
}
@PostMapping("/getUserInfo")
@Log(title = "获取当前用户信息", businessType = BusinessType.LOGIN)
public AjaxResult getUserInfo(){
log.info("SysLoginController - getUserInfo userId:{}", SecurityUtil.getUserId());
PersonVo personVo = sysLoginService.getUserInfo(SecurityUtil.getUserId());
return AjaxResult.success(personVo);
}
}

View File

@ -0,0 +1,85 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.config.validation.Update;
import com.org.system.entity.SysMenu;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysMenuService;
import com.org.utils.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("sys/menu")
public class SysMenuController extends BaseController {
@Autowired
private SysMenuService sysMenuService;
// 新增菜单
@PostMapping("/add")
@PreAuthorize("@ss.hasPermi('sys:menu:add')")
@Log(title = "新增系统菜单", businessType = BusinessType.INSERT)
public AjaxResult add(@RequestBody @Validated SysMenu sysMenu){
log.info("SysMenuController - add sysMenu:{}", sysMenu);
return toAjax(sysMenuService.add(sysMenu));
}
// 编辑菜单
@PostMapping("/edit")
@PreAuthorize("@ss.hasPermi('sys:menu:edit')")
@Log(title = "编辑系统菜单", businessType = BusinessType.UPDATE)
public AjaxResult edit(@RequestBody @Validated(Update.class) SysMenu sysMenu){
log.info("SysMenuController - edit sysMenu:{}", sysMenu);
return toAjax(sysMenuService.edit(sysMenu));
}
// 删除菜单
@PostMapping("/del")
@PreAuthorize("@ss.hasPermi('sys:menu:del')")
@Log(title = "删除系统菜单", businessType = BusinessType.DELETE)
public AjaxResult del(@RequestParam Long id, @RequestParam String deleteReason){
log.info("SysMenuController - del id:{}", id);
log.info("SysMenuController - del deleteReason:{}", deleteReason);
return toAjax(sysMenuService.del(id, deleteReason));
}
// 菜单列表
@GetMapping("/list")
@PreAuthorize("@ss.hasPermi('sys:menu:list')")
@Log(title = "查询系统菜单", businessType = BusinessType.SELECT)
public AjaxResult menuList(SysMenu sysMenu){
log.info("SysMenuController - list sysMenu:{}", sysMenu);
List<SysMenu> list = sysMenuService.queryList(sysMenu);
// 由于children属性存在前端菜单树会加载children故此处不处理前端处理树结构如果没有子节点会删掉children属性
// list = sysMenuService.buildMenuTree(list, 0L);
return AjaxResult.success(list);
}
@GetMapping("/tree")
@PreAuthorize("@ss.hasPermi('sys:menu:list')")
@Log(title = "菜单树", businessType = BusinessType.SELECT)
public AjaxResult tree(){
List<SysMenu> menuTree = sysMenuService.tree();
return AjaxResult.success(menuTree);
}
@GetMapping("/treeForGrant")
@PreAuthorize("@ss.hasPermi('sys:menu:list')")
@Log(title = "角色授权菜单树", businessType = BusinessType.SELECT)
public AjaxResult treeForGrant(){
List<SysMenu> menuTree = sysMenuService.treeForGrant();
return AjaxResult.success(menuTree);
}
}

View File

@ -0,0 +1,42 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.entity.SysOperLog;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysOperLogService;
import com.org.utils.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("sys/operLog")
public class SysOperLogController extends BaseController {
@Autowired
private SysOperLogService sysOssService;
/**
* 分页查询
*
* @return RestResponse
*/
@GetMapping("/list")
@PreAuthorize("@ss.hasPermi('sys:operLog:list')")
@Log(title = "系统文件分页查询", businessType = BusinessType.SELECT)
public TableDataInfo getList(SysOperLog sysOperLog) {
log.info("SysOperLogController - getList sysOperLog:{}", sysOperLog);
startPage();
List<SysOperLog> list = sysOssService.queryList(sysOperLog);
return getDataTable(list);
}
}

View File

@ -0,0 +1,105 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.config.validation.Update;
import com.org.system.entity.SysRole;
import com.org.system.enums.BusinessType;
import com.org.system.params.SysRoleGrantMenuParam;
import com.org.system.service.SysRoleService;
import com.org.utils.AjaxResult;
import com.org.utils.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("sys/role")
public class SysRoleController extends BaseController {
@Autowired
private SysRoleService sysRoleService;
// 新增角色
@PostMapping("/add")
@PreAuthorize("@ss.hasPermi('sys:role:add')")
@Log(title = "新增角色", businessType = BusinessType.INSERT)
public AjaxResult add(@RequestBody @Validated SysRole sysRole){
log.info("SysRoleController - add sysRole:{}", sysRole);
return toAjax(sysRoleService.saveOrUpdate(sysRole));
}
// 编辑角色
@PostMapping("/edit")
@PreAuthorize("@ss.hasPermi('sys:role:edit')")
@Log(title = "编辑角色", businessType = BusinessType.UPDATE)
public AjaxResult edit(@RequestBody @Validated(Update.class) SysRole sysRole){
log.info("SysRoleController - edit sysRole:{}", sysRole);
return toAjax(sysRoleService.saveOrUpdate(sysRole));
}
// 删除角色
@PostMapping("/del")
@PreAuthorize("@ss.hasPermi('sys:role:del')")
@Log(title = "删除角色", businessType = BusinessType.DELETE)
public AjaxResult del(@RequestParam Long id){
log.info("SysRoleController - del id:{}", id);
return toAjax(sysRoleService.del(id));
}
// 角色分页列表
@GetMapping("/pageList")
@PreAuthorize("@ss.hasPermi('sys:role:list')")
@Log(title = "查询角色", businessType = BusinessType.SELECT)
public TableDataInfo pageList(SysRole sysRole){
log.info("SysRoleController - pageList sysRole:{}", sysRole);
startPage();
List<SysRole> list = sysRoleService.findList(sysRole);
log.info("SysRoleController - pageList list:{}", list);
return getDataTable(list);
}
// 角色列表
@GetMapping("/list")
@PreAuthorize("@ss.hasPermi('sys:role:list')")
@Log(title = "查询角色", businessType = BusinessType.SELECT)
public AjaxResult list(){
log.info("SysRoleController - list ");
List<SysRole> list = sysRoleService.findList(new SysRole());
log.info("SysRoleController - list list:{}", list);
return AjaxResult.success(list);
}
// 查询角色拥有菜单
@PostMapping("/ownMenu")
@PreAuthorize("@ss.hasPermi('sys:role:ownMenu')")
@Log(title = "角色拥有菜单", businessType = BusinessType.SELECT)
public AjaxResult ownMenu(Long id){
log.info("SysRoleController - ownMenu id:{}", id);
return AjaxResult.success(sysRoleService.ownMenu(id));
}
// 角色授权菜单
@PostMapping("/grantMenu")
@PreAuthorize("@ss.hasPermi('sys:role:grantMenu')")
@Log(title = "角色授权菜单", businessType = BusinessType.SELECT)
public AjaxResult grantMenu(@RequestBody @Validated SysRoleGrantMenuParam sysRoleGrantMenuParam){
log.info("SysRoleController - grantMenu id:{}, grantMenuIdList{}", sysRoleGrantMenuParam.getId(), sysRoleGrantMenuParam.getGrantMenuIdList());
sysRoleService.grantMenu(sysRoleGrantMenuParam.getId(), sysRoleGrantMenuParam.getGrantMenuIdList());
return AjaxResult.success();
}
}

View File

@ -0,0 +1,69 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.entity.SysMenu;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysRoleMenuService;
import com.org.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("sys/role/menu")
public class SysRoleMenuController extends BaseController {
@Autowired
private SysRoleMenuService sysRoleMenuService;
// @PostMapping("add")
// @PreAuthorize("@ss.hasPermi('sys:role:menu:edit')")
// @Log(title = "系统角色菜单新增", businessType = BusinessType.INSERT)
// public AjaxResult add(@RequestParam Long roleId, @RequestParam String menuIds){
// log.info("SysRoleMenuController - add roleId:{}", roleId);
// log.info("SysRoleMenuController - add menuIds:{}", menuIds);
//
// if(StringUtils.isNull(roleId)) return AjaxResult.error("角色ID不能为空");
//
// List<Long> MenuIdList;
// if(StringUtils.isNotNull(menuIds))
// MenuIdList = Arrays.asList(menuIds.split(",")).stream().map(menuIdStr -> Long.parseLong(menuIdStr)).collect(Collectors.toList());
// else
// MenuIdList = new ArrayList<>();
//
// return toAjax(sysRoleMenuService.save(roleId, MenuIdList));
// }
@GetMapping("/findMenuList")
@PreAuthorize("@ss.hasPermi('sys:role:menu:list')")
@Log(title = "系统角色菜单查询-根据角色ID查询菜单", businessType = BusinessType.SELECT)
public List<SysMenu> findMenuList(@RequestParam Long roleId){
log.info("SysRoleMenuController - findMenu roleId:{}", roleId);
if(StringUtils.isNull(roleId)) return new ArrayList<>();
return sysRoleMenuService.findMenuListByRoleId(roleId);
}
// @GetMapping("/findRoleList")
// @PreAuthorize("@ss.hasPermi('sys:role:menu:list')")
// @Log(title = "系统角色菜单查询-根据菜单ID查询角色", businessType = BusinessType.SELECT)
// public List<SysRole> findRoleList(@RequestParam Long menuId){
// log.info("SysRoleMenuController - findRole menuId:{}", menuId);
//
// if(StringUtils.isNull(menuId)) return new ArrayList<>();
//
// return sysRoleMenuService.findRoleListByMenuId(menuId);
// }
}

View File

@ -0,0 +1,117 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.config.validation.Update;
import com.org.system.entity.SysUser;
import com.org.system.enums.BusinessType;
import com.org.system.params.SysUserGrantRoleParam;
import com.org.system.service.SysUserService;
import com.org.utils.AjaxResult;
import com.org.utils.StringUtils;
import com.org.utils.page.TableDataInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("sys/user")
public class SysUserController extends BaseController{
@Autowired
private SysUserService sysUserService;
@PostMapping("/add")
@PreAuthorize("@ss.hasPermi('sys:user:add')")
@Log(title = "系统用户新增", businessType = BusinessType.INSERT)
public AjaxResult add(@RequestBody @Validated SysUser sysUser, @RequestParam String password){
sysUser.setPassword(password);
log.info("SysUserController - add sysUser:{}", sysUser);
return toAjax(sysUserService.saveOrUpdate(sysUser));
}
@PostMapping("/edit")
@PreAuthorize("@ss.hasPermi('sys:user:edit')")
@Log(title = "系统用户修改", businessType = BusinessType.UPDATE)
public AjaxResult edit(@RequestBody @Validated(Update.class) SysUser sysUser){
log.info("SysUserController - edit sysUser:{}", sysUser);
return toAjax(sysUserService.saveOrUpdate(sysUser));
}
@PostMapping("/del")
@PreAuthorize("@ss.hasPermi('sys:user:del')")
@Log(title = "系统用户删除", businessType = BusinessType.DELETE)
public AjaxResult del(String ids, String deleteReason){
log.info("SysUserController - del ids:{}", ids);
log.info("SysUserController - del deleteReason:{}", deleteReason);
if(StringUtils.isEmpty(ids)) return AjaxResult.success();
List<Long> idList = Arrays.asList(ids.split(",")).stream().map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
return toAjax(sysUserService.del(idList, deleteReason));
}
@GetMapping("/pageList")
@PreAuthorize("@ss.hasPermi('sys:user:list')")
@Log(title = "系统用户查询", businessType = BusinessType.SELECT)
public TableDataInfo pageList(SysUser sysUser){
log.info("SysUserController - pageList sysUser:{}", sysUser);
startPage();
List<SysUser> list = sysUserService.findList(sysUser);
return getDataTable(list);
}
// 查询用户拥有角色
@PostMapping("/ownRole")
@PreAuthorize("@ss.hasPermi('sys:user:ownRole')")
@Log(title = "用户_拥有角色", businessType = BusinessType.SELECT)
public AjaxResult ownRole(Long id){
log.info("SysUserController - ownMenu id:{}", id);
return AjaxResult.success(sysUserService.ownRole(id));
}
// 用户授权角色
@PostMapping("/grantRole")
@PreAuthorize("@ss.hasPermi('sys:user:grantRole')")
@Log(title = "用户授权角色", businessType = BusinessType.SELECT)
public AjaxResult grantRole(@RequestBody @Validated SysUserGrantRoleParam param){
log.info("SysUserController - grantMenu id:{}, grantRoleIdList{}", param.getId(), param.getGrantRoleIdList());
sysUserService.grantRole(param.getId(), param.getGrantRoleIdList());
return AjaxResult.success();
}
// 重置密码
@GetMapping("/resetPwd")
@PreAuthorize("@ss.hasPermi('sys:user:resetPwd')")
@Log(title = "重置密码", businessType = BusinessType.SELECT)
public AjaxResult resetPwd(@RequestParam Long id) {
log.info("SysUserController - resetPwd id:{}", id);
return toAjax(sysUserService.resetPwd(id));
}
// 修改密码
@GetMapping("/changePwd")
// @PreAuthorize("@ss.hasPermi('sys:user:changePwd')")
@Log(title = "修改密码", businessType = BusinessType.SELECT)
public AjaxResult changePwd(@RequestParam String oldPassword, @RequestParam("password") String password) {
log.info("SysUserController - changePwd oldPassword:{}", oldPassword);
log.info("SysUserController - changePwd password:{}", password);
return toAjax(sysUserService.changePwd(oldPassword, password));
}
}

View File

@ -0,0 +1,82 @@
package com.org.system.controller;
import com.org.system.annotation.Log;
import com.org.system.entity.SysRole;
import com.org.system.entity.SysUser;
import com.org.system.enums.BusinessType;
import com.org.system.service.SysUserRoleService;
import com.org.utils.AjaxResult;
import com.org.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("sys/user/role")
public class SysUserRoleController extends BaseController {
@Autowired
private SysUserRoleService sysUserRoleService;
// 新增
@PostMapping("/add")
@PreAuthorize("@ss.hasPermi('sys:user:role:edit')")
@Log(title = "系统用户角色新增", businessType = BusinessType.INSERT)
public AjaxResult add(@RequestParam Long userId, @RequestParam String roleIds){
log.info("SysUserRoleController - add userId:{}", userId);
log.info("SysUserRoleController - add roleIds:{}", roleIds);
if(StringUtils.isEmpty(roleIds)) return AjaxResult.error("角色ID不能为空");
List<Long> roleIdList = Arrays.asList(roleIds.split(",")).stream().map(roleIdStr -> Long.parseLong(roleIdStr)).collect(Collectors.toList());
return toAjax(sysUserRoleService.save(userId, roleIdList));
}
// 删除
@PostMapping("/del")
@PreAuthorize("@ss.hasPermi('sys:user:role:edit')")
@Log(title = "系统用户角色删除", businessType = BusinessType.DELETE)
public AjaxResult del(@RequestParam Long userId, @RequestParam String roleIds){
log.info("SysUserRoleController - del userId:{}", userId);
log.info("SysUserRoleController - del roleIds:{}", roleIds);
if(StringUtils.isNull(roleIds)) return AjaxResult.error("角色ID不能为空");
List<Long> roleIdList = Arrays.asList(roleIds.split(",")).stream().map(roleIdStr -> Long.parseLong(roleIdStr)).collect(Collectors.toList());
return toAjax(sysUserRoleService.delByUserIdAndRoleId(userId, roleIdList));
}
// 根据用户ID查询角色信息
@GetMapping("/findRoleList")
@PreAuthorize("@ss.hasPermi('sys:user:role:list')")
@Log(title = "系统用户角色查询-根据角色ID查询角色", businessType = BusinessType.SELECT)
public List<SysRole> findRoleList(@RequestParam Long userId){
log.info("SysUserRoleController - findRoleList userId:{}", userId);
if(StringUtils.isNull(userId)) return new ArrayList<>();
return sysUserRoleService.findRoleListByUserId(userId);
}
// 根据角色ID查询用户信息
@GetMapping("/findUserList")
@PreAuthorize("@ss.hasPermi('sys:user:role:list')")
@Log(title = "系统用户角色查询-根据角色ID查询用户", businessType = BusinessType.SELECT)
public List<SysUser> findUserList(@RequestParam Long roleId){
log.info("SysUserRoleController - findUserList roleId:{}", roleId);
if(StringUtils.isNull(roleId)) return new ArrayList<>();
return sysUserRoleService.findUserListByRoleId(roleId);
}
}

View File

@ -0,0 +1,44 @@
package com.org.system.entity;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/** 创建者 **/
private Long createBy;
/** 创建时间 **/
@JsonFormat(pattern= DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
private Date createTime;
/** 更新者 **/
private Long updateBy;
/** 更新时间 **/
@JsonFormat(pattern=DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
private Date updateTime;
/** 是否删除 1-是,0-否 **/
private Integer isDelete;
/** 删除者 **/
private Long deleteBy;
/** 删除时间 **/
@JsonFormat(pattern=DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
private Date deleteTime;
/** 删除理由 **/
private String deleteReason;
/** 备注 **/
private String remark;
}

View File

@ -0,0 +1,15 @@
package com.org.system.entity;
import lombok.Data;
/** 用户登录对象 **/
@Data
public class LoginBody {
/** 帐号 **/
private String username;
/** 密码 **/
private String password;
/** 角色编码 默认平台管理员**/
private String roleCode;
}

View File

@ -0,0 +1,119 @@
package com.org.system.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.org.system.pojo.LoginMenuTreeNode;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* 登录用户身份权限
*
*/
@Data
@Accessors(chain = true)
public class LoginUser implements UserDetails {
private static final long serialVersionUID = 1L;
/** 用户唯一标识 **/
private String token;
/** 登录时间 **/
private Long loginTime;
/** 过期时间 **/
private Long expireTime;
/** 登录IP地址 **/
private String ipaddr;
/** 登录地点 **/
private String loginLocation;
/** 浏览器类型 **/
private String browser;
/** 操作系统 **/
private String os;
/** 用户信息 **/
private SysUser user;
/** 所有角色信息 **/
private List<SysRole> roleList;
/** 当前角色编码 **/
private String currentRoleCode;
/** 当前角色信息 **/
private SysRole currentRole;
/** 权限列表 **/
private Set<String> permissions;
/** 登录菜单信息AntDesign版本菜单 **/
private List<LoginMenuTreeNode> menus;
/** 是否管理员 **/
public boolean ifAdmin(){
if("admin".equals(this.user.getUserName())) return true;
return false;
}
@JsonIgnore
@Override
public String getPassword(){ return user.getPassword(); }
@Override
public String getUsername(){ return user.getUserName(); }
public String getName(){ return user.getName(); }
/** 账户是否未过期,过期无法验证 **/
@JsonIgnore
@Override
public boolean isAccountNonExpired()
{
return true;
}
/** 指定用户是否解锁,锁定的用户无法进行身份验证 **/
@JsonIgnore
@Override
public boolean isAccountNonLocked()
{
return true;
}
/** 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 **/
@JsonIgnore
@Override
public boolean isCredentialsNonExpired()
{
return true;
}
/** 是否可用 ,禁用的用户不能身份验证 **/
@JsonIgnore
@Override
public boolean isEnabled()
{
return true;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
{
return null;
}
}

View File

@ -0,0 +1,27 @@
package com.org.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.org.system.config.validation.Update;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/** 系统词典分类表 **/
@Data
public class SysDataDictionary extends BaseEntity {
/** 词典分类ID **/
@TableId(type = IdType.AUTO)
@NotNull(message = "词典分类ID不能为空", groups = {Update.class})
private Long id;
/** 词典标识(键) **/
private String dictionaryCode;
/** 词典名称 **/
@NotEmpty(message = "词典名称不能为空")
private String dictionaryName;
}

View File

@ -0,0 +1,43 @@
package com.org.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.org.system.config.validation.Update;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/** 系统词典项表 **/
@Data
public class SysDataDictionaryItem extends BaseEntity {
/** 词典项ID **/
@TableId(type = IdType.AUTO)
@NotNull(message = "词典项ID不能为空", groups = {Update.class})
private Long id;
/** 词典标识(键) **/
@NotEmpty(message = "词典标识不能为空")
private String dictionaryCode;
/** 词典项目名称 **/
@NotEmpty(message = "词典项名称不能为空")
private String name;
/** 词典项目值 **/
@NotNull(message = "词典项值不能为空")
private Integer value;
/** 所属上级值顶级默认-1 **/
@NotNull(message = "所属上级不能为空")
private Integer parentid;
/** 备注说明 **/
private String description;
/** 显示顺序 **/
@NotNull(message = "显示顺序不能为空", groups = {Update.class})
private Integer sortid;
}

View File

@ -0,0 +1,67 @@
package com.org.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.org.system.config.validation.Update;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
/** 菜单表 **/
@Data
public class SysMenu extends BaseEntity {
/** 菜单ID **/
@TableId(type = IdType.AUTO)
@NotNull(message = "菜单ID不能为空", groups = Update.class)
private Long id;
/** 菜单名称 **/
@NotEmpty(message = "菜单名称不能为空")
private String name;
/** 菜单编码 **/
@NotEmpty(message = "菜单编码不能为空")
private String code;
/** 上级菜单ID **/
@NotNull(message = "上级菜单ID不能为空")
private Long pid;
/**
* 父ids
*/
private String pids;
/** 菜单类型 0目录 1菜单 2按钮 3-服务级(待定) **/
@NotNull(message = "菜单类型不能为空")
private Integer type;
/**
* 路由地址
*/
private String router;
/**
* 组件地址
*/
private String component;
/** 权限标识 **/
private String permission;
/** 是否显示 1-是 0-否 **/
@NotNull(message = "是否显示不能为空")
private Integer visible;
/** 顺序号 **/
private Integer intCode;
@TableField(exist = false)
private List<SysMenu> children = new ArrayList<>();
}

View File

@ -0,0 +1,69 @@
package com.org.system.entity;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/** 操作日志记录表 oper_log **/
@Data
public class SysOperLog {
/** 日志主键 */
@TableId(type = IdType.AUTO)
private Long id;
/** 操作模块 */
private String title;
/** 业务类型0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据) */
private Integer businessType;
/** 业务类型数组 */
@TableField(exist = false)
private Integer[] businessTypes;
/** 请求方法 */
private String method;
/** 请求方式 */
private String requestMethod;
/** 操作类别0其它 1后台用户 2手机端用户 */
private Integer operatorType;
/** 操作人员 */
private String operName;
/** 部门名称 */
private String deptName;
/** 请求url */
private String operUrl;
/** 操作地址 */
private String operIp;
/** 操作地点 */
private String operLocation;
/** 请求参数 */
private String operParam;
/** 返回参数 */
private String jsonResult;
/** 操作状态0正常 1异常 */
private Integer status;
/** 错误消息 */
private String errorMsg;
/** 操作时间 */
@JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
private Date operTime;
}

View File

@ -0,0 +1,53 @@
package com.org.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.org.system.config.validation.Update;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/** 系统角色表 **/
@Data
public class SysRole extends BaseEntity {
public static final Long PLATFORM_MANAGER_ROLE = 2L;
// 服务人员
public static final Long SERVICE_ROLE = 3L;
// 供养人员
public static final Long SUPPORT_ROLE = 4L;
// 医养结合护理人员
public static final Long TEND_ROLE = 5L;
public static final String STUDENT_ROLE_CODE = "student";
/** 角色ID **/
@NotNull(message = "角色ID不能为空", groups = {Update.class})
@TableId(type = IdType.AUTO)
private Long id;
/** 角色名称 **/
@NotEmpty(message = "角色名称不能为空")
private String name;
/**
* 编码
*/
private String code;
/**
* 排序
*/
private Integer sort;
/** 角色所属组织ID **/
private Long orgCode;
/** 父级角色ID **/
private Long parentId;
}

View File

@ -0,0 +1,27 @@
package com.org.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/** 角色菜单 **/
@Data
@Accessors(chain = true)
public class SysRoleMenu {
/** 主键ID **/
@TableId(type = IdType.AUTO)
private Long id;
/** 角色ID **/
@NotNull(message = "角色ID不能为空")
private Long roleId;
/** 菜单ID **/
@NotNull(message = "菜单ID不能为空")
private Long menuId;
}

View File

@ -0,0 +1,88 @@
package com.org.system.entity;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdcardUtil;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.org.system.config.validation.Update;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
public class SysUser extends BaseEntity {
public static final String DEFAULT_PASSWORD = "Aqpx123456";
/** 用户ID **/
@TableId(type = IdType.AUTO)
@NotNull(message = "用户ID不能为空", groups = {Update.class})
private Long id;
/** 姓名 */
@NotEmpty(message = "姓名不能为空")
private String name;
/** 用户名称 **/
@NotEmpty(message = "用户名称不能为空")
private String userName;
/** 用户昵称 **/
private String nickName;
/** 用户邮箱 **/
private String email;
/** 手机号码 **/
private String phone;
/** 微信OpenId **/
@JsonIgnore
private String wxOpenId;
/** 用户性别 0-未知 1-男 2-女 **/
private int sex;
/** 用户头像 **/
private String avatar;
/** 用户密码 **/
@JsonIgnore
private String password;
/** 用户SALT **/
@JsonIgnore
private String salt;
/** 用户状态 0-停用 1-正常 2-注册 **/
private Integer status;
/** 最后登录IP **/
private String loginIp;
/** 最后登录时间 **/
@JsonFormat(pattern= DatePattern.NORM_DATETIME_PATTERN, timezone = "GMT+8")
private Date loginDate;
/** 登录次数 **/
private Integer loginCount;
public Integer getLoginCount(){ return this.loginCount == null ? 0 : this.loginCount; }
/** 身份证号码 **/
private String idCardNo;
/** 年龄 */
@TableField(exist = false)
private Integer age;
public int getAge() {
if(this.idCardNo == null){ return 0; }
// 通过身份证号计算年龄
return this.age = IdcardUtil.getAgeByIdCard(this.getIdCardNo());
}
}

View File

@ -0,0 +1,23 @@
package com.org.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.experimental.Accessors;
/** 系统用户角色 **/
@Data
@Accessors(chain = true)
public class SysUserRole {
/** 主键ID **/
@TableId(type = IdType.AUTO)
private Long id;
/** 用户ID **/
private Long userId;
/** 角色ID **/
private Long roleId;
}

View File

@ -0,0 +1,48 @@
package com.org.system.entity.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
@Accessors(chain = true)
public class PersonVo implements Serializable {
private static final long serialVersionUID = 1L;
/** 学员id */
private Long id;
/** 部门信息 */
private Long orgId;
private Long userId;
private Long personId;
/** 姓名 */
private String name;
/* 用户名 */
private String userName;
/** 用户性别 0-未知 1-男 2-女 **/
private int sex;
/** 是否管理员 2:否 1:是 */
private Integer isAdmin;
/* 单位信息 */
private String unit;
/* 部门信息 */
private String dept;
/** 年度学时 */
private BigDecimal yearClassHour;
/** 累计学时 */
private BigDecimal sumClassHour;
}

View File

@ -0,0 +1,10 @@
package com.org.system.enums;
/** 操作状态 **/
public enum BusinessStatus {
/** 成功 **/
SUCCESS,
/** 失败 **/
FAIL,
}

View File

@ -0,0 +1,40 @@
package com.org.system.enums;
/** 业务操作类型 **/
public enum BusinessType {
/** 其它 **/
OTHER,
/** 新增 **/
INSERT,
/** 修改 **/
UPDATE,
/** 删除 **/
DELETE,
/** 查询 **/
SELECT,
/** 授权 **/
GRANT,
/** 导出 **/
EXPORT,
/** 导入 **/
IMPORT,
/** 强退 **/
FORCE,
/** 生成代码 **/
GENCODE,
/** 清空数据 **/
CLEAN,
/** 登陆 **/
LOGIN,
}

View File

@ -0,0 +1,34 @@
package com.org.system.enums;
import lombok.Getter;
/**
* 菜单类型枚举
*/
@Getter
public enum MenuTypeEnum {
/**
* 目录
*/
DIR(0, "目录"),
/**
* 菜单
*/
MENU(1, "菜单"),
/**
* 按钮
*/
BTN(2, "按钮");
private final Integer code;
private final String message;
MenuTypeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}

View File

@ -0,0 +1,14 @@
package com.org.system.enums;
/** 操作人类别 **/
public enum OperatorType
{
/** 其它 **/
OTHER,
/** 后台用户 **/
MANAGE,
/** 手机端用户 **/
MOBILE
}

View File

@ -0,0 +1,31 @@
package com.org.system.enums;
/** 短信类型 **/
public enum SmsType {
REGISTER("register"), CHANGEMOBILE("changeMobile");
private final String value;
SmsType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
/**
* 根据value获取枚举
* @param value
* @return
*/
public static SmsType getSmsType(String value) {
SmsType[] smsTypeArr = SmsType.values();
for (int i = 0; i < smsTypeArr.length; i++) {
if (smsTypeArr[i].getValue().equals(value)) {
return smsTypeArr[i];
}
}
return null;
}
}

View File

@ -0,0 +1,15 @@
package com.org.system.enums;
/** 删除状态 **/
public enum YesOrNoState {
YES(1),NO(0);
private final int state;
YesOrNoState(int state) {
this.state = state;
}
public int getState() {
return state;
}
}

View File

@ -0,0 +1,39 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysDataDictionaryItem;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface SysDataDictionaryItemMapper extends BaseMapper<SysDataDictionaryItem> {
@Select("select max(sortid) from sys_data_dictionary_item where dictionary_code = #{dictionaryCode}")
public Integer findMaxSortidByCode(@Param("dictionaryCode") String dictionaryCode);
@Select("select max(value) from sys_data_dictionary_item where dictionary_code = #{dictionaryCode}")
public Integer findMaxValueByCode(@Param("dictionaryCode") String dictionaryCode);
/**
* 通过名称和code 查询词典项
* @param name
* @param dictionaryCode
* @return 返回一条数据
*/
@Select("SELECT * FROM sys_data_dictionary_item WHERE name=#{name} AND dictionary_code=#{dictionaryCode} ")
SysDataDictionaryItem findByNameAndCode(@Param("name") String name, String dictionaryCode);
/**
* 通过值和code 查询词典项
* @param value
* @param dictionaryCode
* @return
*/
@Select("SELECT * FROM sys_data_dictionary_item WHERE value=#{value} AND dictionary_code=#{dictionaryCode} ")
SysDataDictionaryItem findByValueAndCode(@Param("value") int value, String dictionaryCode);
@Select("select name from sys_data_dictionary_item where dictionary_code = #{dictonaryCode} and value = #{value} and is_delete=0")
String findDictonaryBydictonaryCode(@Param("dictonaryCode") String dictonaryCode, @Param("value") Integer value);
}

View File

@ -0,0 +1,10 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysDataDictionary;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysDataDictionaryMapper extends BaseMapper<SysDataDictionary> {
}

View File

@ -0,0 +1,15 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysMenu;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface SysMenuMapper extends BaseMapper<SysMenu> {
@Select("select max(int_code) from sys_menu where parent_id = #{parentId}")
public Integer findMaxIntCodeByParentId(@Param("parentId") Long parentId);
}

View File

@ -0,0 +1,11 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysOperLog;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysOperLogMapper extends BaseMapper<SysOperLog> {
}

View File

@ -0,0 +1,12 @@
//package com.xinmei.system.mapper;
//
//import com.baomidou.mybatisplus.core.mapper.BaseMapper;
//import com.xinmei.system.entity.SysOrg;
//import org.apache.ibatis.annotations.Mapper;
//
//@Mapper
//public interface SysOrgMapper extends BaseMapper<SysOrg> {
//
//
//
//}

View File

@ -0,0 +1,12 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysRole;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysRoleMapper extends BaseMapper<SysRole> {
}

View File

@ -0,0 +1,31 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysMenu;
import com.org.system.entity.SysRole;
import com.org.system.entity.SysRoleMenu;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenu> {
@Delete("delete from sys_role_menu where role_id = #{roleId}")
public Integer delByRoleId(@Param("roleId") Long roleId);
// @Delete("delete from sys_role_menu where menu_id = #{menuId}")
// public Integer delByMenuId(@Param("menuId") Long menuId);
@Delete("delete from sys_role_menu where role_id = #{roleId} and menu_id = #{menuId}")
public Integer delByRoleIdAndMenuId(@Param("roleId") Long roleId, @Param("menuId") Long menuId);
@Select("select menu.* from sys_menu menu left join sys_role_menu rm on menu.id = rm.menu_id where rm.role_id = #{roleId} and menu.is_delete = 0 order by menu.int_code")
public List<SysMenu> findMenuListByRoleId(@Param("roleId") Long roleId);
@Select("select role.* from sys_role role left join sys_role_menu rm on role.id = rm.role_id where rm.menu_id = #{menuId} and role.is_delete = 0")
public List<SysRole> findRoleListByMenuId(@Param("menuId") Long menuId);
}

View File

@ -0,0 +1,18 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
@Select("select * from sys_user where user_name = #{userName} and is_delete = 0")
public SysUser findByUserName(@Param("userName") String userName);
@Select("select * from sys_user where (user_name = #{userName} or phone = #{userName}) and is_delete = 0 order by create_time desc limit 1")
public SysUser findByUserNameOrPhone(@Param("userName") String userName);
}

View File

@ -0,0 +1,32 @@
package com.org.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.org.system.entity.SysRole;
import com.org.system.entity.SysUser;
import com.org.system.entity.SysUserRole;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
@Delete("delete from sys_user_role where user_id = #{userId}")
public Integer delByUserId(@Param("userId") Long userId);
@Delete("delete from sys_user_role where role_id = #{roleId}")
public Integer delByRoleId(@Param("roleId") Long roleId);
@Delete("delete from sys_user_role where user_id = #{userId} and role_id = #{roleId}")
public Integer delByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
@Select("select user.* from sys_user user left join sys_user_role ur on user.id = ur.user_id where ur.role_id = #{roleId} and user.is_delete = 0")
public List<SysUser> findUserListByRoleId(@Param("roleId") Long roleId);
@Select("select role.* from sys_role role left join sys_user_role ur on role.id = ur.role_id where ur.user_id = #{userid} and role.is_delete = 0")
public List<SysRole> findRoleListByUserId(@Param("userid") Long userid);
}

View File

@ -0,0 +1,26 @@
package com.org.system.params;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 系统角色分配菜单参数
*/
@Data
public class SysRoleGrantMenuParam {
/**
* 主键
*/
@NotNull(message = "id不能为空请检查id参数")
private Long id;
/**
* 授权菜单
*/
@NotNull(message = "授权菜单不能为空请检查grantMenuIdList参数")
private List<Long> grantMenuIdList;
}

View File

@ -0,0 +1,26 @@
package com.org.system.params;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 用户分配角色参数
*/
@Data
public class SysUserGrantRoleParam {
/**
* 主键
*/
@NotNull(message = "id不能为空请检查id参数")
private Long id;
/**
* 授权角色
*/
@NotNull(message = "授权角色不能为空请检查grantRoleIdList参数")
private List<Long> grantRoleIdList;
}

View File

@ -0,0 +1,88 @@
package com.org.system.pojo;
import lombok.Data;
import java.io.Serializable;
/**
* 登录菜单
*/
@Data
public class LoginMenuTreeNode implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
private Long id;
/**
* 父id
*/
private Long pid;
/**
* 路由名称, 必须设置,且不能重名
*/
private String name;
/**
* 组件
*/
private String component;
/**
* 重定向地址, 访问这个路由时, 自定进行重定向
*/
private String redirect;
/**
* 路由元信息路由附带扩展信息
*/
private Meta meta;
/**
* 路径
*/
private String path;
/**
* 控制路由和子路由是否显示在 sidebar
*/
private boolean hidden;
/**
* 路由元信息内部类
*/
@Data
public class Meta implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 路由标题, 用于显示面包屑, 页面标题 *推荐设置
*/
public String title;
/**
* 图标
*/
public String icon;
/**
* 是否可见
*/
public boolean show;
/**
* 如需外部打开增加_blank
*/
public String target;
/**
* 内链打开http链接
*/
public String link;
}
}

View File

@ -0,0 +1,50 @@
package com.org.system.service;
import com.org.system.config.security.Md5PasswordEncoder;
import com.org.system.entity.LoginUser;
import com.org.system.entity.SysUser;
import com.org.utils.exception.BaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/**
* 用户验证处理
*
*/
@Service
public class CustomUserService implements UserDetailsService {
private static final Logger log = LoggerFactory.getLogger(CustomUserService.class);
@Autowired
private SysUserService sysUserService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// SysUser user = sysUserService.findByUserName(username);
SysUser user = sysUserService.findByUserNameOrPhone(username);
if (user == null) {
log.info("登录用户:{} 不存在.", username);
// throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
throw new InternalAuthenticationServiceException("登录用户:" + username + " 不存在");
} else if (1 == user.getIsDelete()) {
log.info("登录用户:{} 已被删除.", username);
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
} else if (0 == user.getStatus()) {
log.info("登录用户:{} 已被停用.", username);
throw new BaseException("对不起,您的账号:" + username + " 已停用");
}
Md5PasswordEncoder.getInstance().setSalt(user.getSalt());
return createLoginUser(user);
}
public UserDetails createLoginUser(SysUser user) {
// 这里可以查询用户权限放入 LoginUser
return new LoginUser().setUser(user);
}
}

View File

@ -0,0 +1,153 @@
package com.org.system.service;
import com.org.system.entity.LoginUser;
import com.org.utils.HttpServletUtil;
import com.org.utils.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Set;
/** 自定义权限实现 **/
@Service("ss")
public class PermissionService {
/** 所有权限标识 **/
public static final String ALL_PERMISSION = "*:*:*";
/** 管理员角色权限标识 **/
private static final String SUPER_ADMIN = "admin";
private static final String ROLE_DELIMETER = ",";
private static final String PERMISSION_DELIMETER = ",";
@Autowired
private TokenService tokenService;
/**
* 验证用户是否具备某权限
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission) {
if (StringUtils.isEmpty(permission)) return false;
// LoginUser loginUser = tokenService.getLoginUser(HttpServletUtil.getRequest());
LoginUser loginUser = SecurityUtil.getLoginUser();
if (null == loginUser || CollectionUtils.isEmpty(loginUser.getPermissions())) return false;
return hasPermissions(loginUser.getPermissions(), permission);
}
/**
* 验证用户是否不具备某权限 hasPermi逻辑相反
*
* @param permission 权限字符串
* @return 用户是否不具备某权限
*/
public boolean lacksPermi(String permission)
{
return hasPermi(permission) != true;
}
/**
* 验证用户是否具有以下任意一个权限
*
* @param permissions PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
* @return 用户是否具有以下任意一个权限
*/
public boolean hasAnyPermi(String permissions) {
if (StringUtils.isEmpty(permissions)) return false;
LoginUser loginUser = tokenService.getLoginUser(HttpServletUtil.getRequest());
if (null == loginUser || CollectionUtils.isEmpty(loginUser.getPermissions())) return false;
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER)) {
if (permission != null && hasPermissions(authorities, permission)) return true;
}
return false;
}
/**
* 判断用户是否拥有某个角色
*
* @param role 角色字符串
* @return 用户是否具备某角色
*/
/*public boolean hasRole(String role)
{
if (StringUtils.isEmpty(role))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
}
for (SysRole sysRole : loginUser.getUser().getRoles())
{
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
{
return true;
}
}
return false;
}*/
/**
* 验证用户是否不具备某角色 isRole逻辑相反
*
* @param role 角色名称
* @return 用户是否不具备某角色
*/
/*public boolean lacksRole(String role)
{
return hasRole(role) != true;
}*/
/**
* 验证用户是否具有以下任意一个角色
*
* @param roles ROLE_NAMES_DELIMETER 为分隔符的角色列表
* @return 用户是否具有以下任意一个角色
*/
/*
public boolean hasAnyRoles(String roles)
{
if (StringUtils.isEmpty(roles))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
}
for (String role : roles.split(ROLE_DELIMETER))
{
if (hasRole(role))
{
return true;
}
}
return false;
}
*/
/**
* 判断是否包含权限
*
* @param permissions 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
private boolean hasPermissions(Set<String> permissions, String permission) {
return permissions.contains(ALL_PERMISSION) || permissions.contains(permission.trim());
}
}

View File

@ -0,0 +1,243 @@
package com.org.system.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysDataDictionaryItem;
import com.org.system.enums.YesOrNoState;
import com.org.system.mapper.SysDataDictionaryItemMapper;
import com.org.utils.SecurityUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class SysDataDictionaryItemService extends ServiceImpl<SysDataDictionaryItemMapper, SysDataDictionaryItem> {
/**
* 新增或修改词典项
*
* @param sysDataDictionaryItem
* @return
*/
public boolean saveOrUpdate(SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemService - saveOrUpdate sysDataDictionaryItem:{}", sysDataDictionaryItem);
if(StringUtils.isNull(sysDataDictionaryItem.getId())){
//校验参数检查是否存在相同的名称和值
checkParam(sysDataDictionaryItem, false);
// 新增
if(null == sysDataDictionaryItem.getSortid()) sysDataDictionaryItem.setSortid(findMaxSortidByCode(sysDataDictionaryItem.getDictionaryCode()));
sysDataDictionaryItem.setCreateBy(SecurityUtil.getUserId());
sysDataDictionaryItem.setCreateTime(new Date());
sysDataDictionaryItem.setIsDelete(YesOrNoState.NO.getState());
log.info("SysDataDictionaryItemService - saveOrUpdate save sysDataDictionaryItem:{}", sysDataDictionaryItem);
return save(sysDataDictionaryItem);
} else {
//校验参数检查是否存在相同的名称和值
checkParam(sysDataDictionaryItem, true);
// 修改
SysDataDictionaryItem sysDataDictionaryItemOld = getById(sysDataDictionaryItem.getId());
if(sysDataDictionaryItemOld == null || StringUtils.isNull(sysDataDictionaryItemOld.getId()))
throw new CustomException("未找到词典项");
sysDataDictionaryItem.setCreateBy(null);
sysDataDictionaryItem.setCreateTime(null);
sysDataDictionaryItem.setIsDelete(null);
sysDataDictionaryItem.setUpdateBy(SecurityUtil.getUserId());
sysDataDictionaryItem.setUpdateTime(new Date());
log.info("SysDataDictionaryItemService - saveOrUpdate update sysDataDictionaryItem:{}", sysDataDictionaryItem);
return updateById(sysDataDictionaryItem);
}
}
/**
* 校验参数检查是否存在相同的名称
*/
private void checkParam(SysDataDictionaryItem dictionary, boolean isExcludeSelf) {
Long id = dictionary.getId();
String name = dictionary.getName();
Integer value = dictionary.getValue();
LambdaQueryWrapper<SysDataDictionaryItem> queryWrapperByName = new LambdaQueryWrapper<>();
queryWrapperByName.eq(SysDataDictionaryItem::getName, name)
.eq(SysDataDictionaryItem::getDictionaryCode, dictionary.getDictionaryCode())
.eq(SysDataDictionaryItem::getIsDelete, YesOrNoState.NO.getState());
LambdaQueryWrapper<SysDataDictionaryItem> queryWrapperByCode = new LambdaQueryWrapper<>();
queryWrapperByCode.eq(SysDataDictionaryItem::getValue, value)
.eq(SysDataDictionaryItem::getDictionaryCode, dictionary.getDictionaryCode())
.eq(SysDataDictionaryItem::getIsDelete, YesOrNoState.NO.getState());
//是否排除自己如果排除自己则不查询自己的id
if (isExcludeSelf) {
queryWrapperByName.ne(SysDataDictionaryItem::getId, id);
queryWrapperByCode.ne(SysDataDictionaryItem::getId, id);
}
int countByName = this.count(queryWrapperByName);
int countByCode = this.count(queryWrapperByCode);
if (countByName >= 1) {
throw new CustomException("名称重复,请检查名称参数");
}
if (countByCode >= 1) {
throw new CustomException("词典项值重复,请检查词典项值参数");
}
}
/**
* 删除词典项
*
* @param idList
* @param deleteReason
* @return
*/
public boolean del(List<Long> idList, String deleteReason){
log.info("SysDataDictionaryItemService - del idList:{}", idList);
log.info("SysDataDictionaryItemService - del deleteReason:{}", deleteReason);
List<SysDataDictionaryItem> delList = new ArrayList<>();
for (Long id : idList) {
if(id == null) continue;
SysDataDictionaryItem sysDataDictionaryItem = getById(id);
if(sysDataDictionaryItem == null || sysDataDictionaryItem.getId() == null) continue;
sysDataDictionaryItem.setIsDelete(YesOrNoState.YES.getState());
sysDataDictionaryItem.setDeleteBy(SecurityUtil.getUserId());
sysDataDictionaryItem.setDeleteTime(new Date());
log.info("SysDataDictionaryItemService - del sysDataDictionaryItem:{}", sysDataDictionaryItem);
delList.add(sysDataDictionaryItem);
}
return updateBatchById(delList);
}
/**
* 词典项查询
*
* @param sysDataDictionaryItem
* @return
*/
public List<SysDataDictionaryItem> findList(SysDataDictionaryItem sysDataDictionaryItem){
log.info("SysDataDictionaryItemService - findList sysDataDictionaryItem:{}", sysDataDictionaryItem);
if(StringUtils.isEmpty(sysDataDictionaryItem.getDictionaryCode())) throw new CustomException("词典标识不能为空");
LambdaQueryWrapper<SysDataDictionaryItem> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDataDictionaryItem::getIsDelete, YesOrNoState.NO.getState())
.eq(SysDataDictionaryItem::getDictionaryCode, sysDataDictionaryItem.getDictionaryCode());
if(StringUtils.isNotEmpty(sysDataDictionaryItem.getName()))
queryWrapper.like(SysDataDictionaryItem::getName, sysDataDictionaryItem.getName());
if(StringUtils.isNotNull(sysDataDictionaryItem.getValue()))
queryWrapper.like(SysDataDictionaryItem::getValue, sysDataDictionaryItem.getValue());
//根据排序升序排列序号越小越在前
queryWrapper.orderByAsc(SysDataDictionaryItem::getSortid);
return list(queryWrapper);
}
/**
* 根据词典标识获取该标识下的词典项最大显示顺序
*
* @param dictionaryCode
* @return
*/
private Integer findMaxSortidByCode(String dictionaryCode){
log.info("SysDataDictionaryItemService - findMaxSortidByCode dictionaryCode:{}", dictionaryCode);
Integer sortid = baseMapper.findMaxSortidByCode(dictionaryCode);
log.info("SysDataDictionaryItemService - findMaxSortidByCode sortid:{}", sortid);
if(StringUtils.isNull(sortid)) sortid = 0;
sortid++;
log.info("SysDataDictionaryItemService - findMaxSortidByCode sortid:{}", sortid);
return sortid;
}
/**
* 根据词典标识获取该标识下的词典项最大词典项目值
*
* @param dictionaryCode
* @return
*/
public Integer findMaxValueByCode(String dictionaryCode){
log.info("SysDataDictionaryItemService - findMaxValueByCode dictionaryCode:{}", dictionaryCode);
Integer value = baseMapper.findMaxValueByCode(dictionaryCode);
log.info("SysDataDictionaryItemService - findMaxValueByCode value:{}", value);
if(StringUtils.isNull(value)) value = 0;
value++;
log.info("SysDataDictionaryItemService - findMaxValueByCode value:{}", value);
return value;
}
public List<Dict> listByCode(String dictionaryCode) {
//构造查询条件
LambdaQueryWrapper<SysDataDictionaryItem> queryWrapper = new LambdaQueryWrapper<SysDataDictionaryItem>();
queryWrapper.eq(SysDataDictionaryItem::getDictionaryCode, dictionaryCode)
.eq(SysDataDictionaryItem::getIsDelete, YesOrNoState.NO.getState());
//根据排序升序排列序号越小越在前
queryWrapper.orderByAsc(SysDataDictionaryItem::getSortid);
//查询dictTypeId下所有的字典项
List<SysDataDictionaryItem> results = this.list(queryWrapper);
//抽取code和value封装到map返回
List<Dict> dictList = CollectionUtil.newArrayList();
results.forEach(sysDictData -> {
Dict dict = Dict.create();
dict.put("id", sysDictData.getId());
dict.put("name", sysDictData.getName());
dict.put("value", sysDictData.getValue());
dict.put("parentid", sysDictData.getParentid());
dictList.add(dict);
});
return dictList;
}
/**
* 通过课程的
* @param dictonaryCode 字典code
* @param value 字典value
* @return
*/
public String findDictonaryBydictonaryCode(String dictonaryCode,Integer value){
log.info("SysDataDictionaryItemService - findDictonaryBydictonaryCode dictonaryCode:{}", dictonaryCode);
log.info("SysDataDictionaryItemService - findDictonaryBydictonaryCode value:{}", value);
return baseMapper.findDictonaryBydictonaryCode(dictonaryCode,value);
}
public SysDataDictionaryItem getByCodeAndName(String dictionaryCode, String name) {
LambdaQueryWrapper<SysDataDictionaryItem> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDataDictionaryItem::getDictionaryCode, dictionaryCode);
queryWrapper.eq(SysDataDictionaryItem::getName, name);
queryWrapper.eq(SysDataDictionaryItem::getIsDelete, YesOrNoState.NO.getState());
return baseMapper.selectOne(queryWrapper);
}
public SysDataDictionaryItem getByCodeAndValue(String dictionaryCode, String value) {
LambdaQueryWrapper<SysDataDictionaryItem> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDataDictionaryItem::getDictionaryCode, dictionaryCode);
queryWrapper.eq(SysDataDictionaryItem::getValue, value);
queryWrapper.eq(SysDataDictionaryItem::getIsDelete, YesOrNoState.NO.getState());
return baseMapper.selectOne(queryWrapper);
}
}

View File

@ -0,0 +1,153 @@
package com.org.system.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysDataDictionary;
import com.org.system.enums.YesOrNoState;
import com.org.system.mapper.SysDataDictionaryMapper;
import com.org.utils.SecurityUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class SysDataDictionaryService extends ServiceImpl<SysDataDictionaryMapper, SysDataDictionary> {
/**
* 新增或修改词典分类
*
* @param sysDataDictionary
* @return
*/
public boolean saveOrUpdate(SysDataDictionary sysDataDictionary){
log.info("SysDataDictionaryService - saveOrUpdate sysDataDictionary:{}", sysDataDictionary);
if(sysDataDictionary.getId() == null){
//校验参数检查是否存在相同的名称和编码
checkParam(sysDataDictionary, false);
// 新增词典分类
sysDataDictionary.setDictionaryCode(findDictionaryCode());
sysDataDictionary.setCreateBy(SecurityUtil.getUserId());
sysDataDictionary.setCreateTime(new Date());
sysDataDictionary.setIsDelete(YesOrNoState.NO.getState());
log.info("SysDataDictionaryService - saveOrUpdate save sysDataDictionary:{}", sysDataDictionary);
return save(sysDataDictionary);
}else{
//校验参数检查是否存在相同的名称和编码
checkParam(sysDataDictionary, true);
// 修改词典分类
SysDataDictionary sysDataDictionaryOld = getById(sysDataDictionary.getId());
if(sysDataDictionaryOld == null || sysDataDictionaryOld.getId() == null)
throw new CustomException("未找到词典分类");
sysDataDictionaryOld.setDictionaryName(sysDataDictionary.getDictionaryName());
sysDataDictionaryOld.setUpdateBy(SecurityUtil.getUserId());
sysDataDictionaryOld.setUpdateTime(new Date());
log.info("SysDataDictionaryService - saveOrUpdate save sysDataDictionary:{}", sysDataDictionaryOld);
return updateById(sysDataDictionaryOld);
}
}
/**
* 校验参数检查是否存在相同的名称
*/
private void checkParam(SysDataDictionary dictionary, boolean isExcludeSelf) {
Long id = dictionary.getId();
String name = dictionary.getDictionaryName();
String code = dictionary.getDictionaryCode();
LambdaQueryWrapper<SysDataDictionary> queryWrapperByName = new LambdaQueryWrapper<>();
queryWrapperByName.eq(SysDataDictionary::getDictionaryName, name)
.eq(SysDataDictionary::getIsDelete, YesOrNoState.NO.getState());
LambdaQueryWrapper<SysDataDictionary> queryWrapperByCode = new LambdaQueryWrapper<>();
queryWrapperByCode.eq(SysDataDictionary::getDictionaryCode, code)
.eq(SysDataDictionary::getIsDelete, YesOrNoState.NO.getState());
//是否排除自己如果排除自己则不查询自己的id
if (isExcludeSelf) {
queryWrapperByName.ne(SysDataDictionary::getId, id);
queryWrapperByCode.ne(SysDataDictionary::getId, id);
}
int countByName = this.count(queryWrapperByName);
int countByCode = this.count(queryWrapperByCode);
if (countByName >= 1) {
throw new CustomException("名称重复,请检查名称参数");
}
if (countByCode >= 1) {
throw new CustomException("编码重复,请检查编码参数");
}
}
/**
* 删除词典分类
*
* @param idList
* @param deleteReason
* @return
*/
public boolean del(List<Long> idList, String deleteReason){
log.info("SysDataDictionaryService - del idList:{}", idList);
log.info("SysDataDictionaryService - del deleteReason:{}", deleteReason);
List<SysDataDictionary> delList = new ArrayList<>();
for (Long id : idList) {
if(id == null) continue;
SysDataDictionary sysDataDictionary = getById(id);
if(sysDataDictionary == null || sysDataDictionary.getId() == null) continue;
sysDataDictionary.setIsDelete(YesOrNoState.YES.getState());
sysDataDictionary.setDeleteBy(SecurityUtil.getUserId());
sysDataDictionary.setDeleteTime(new Date());
log.info("SysDataDictionaryService - del sysDataDictionary:{}", sysDataDictionary);
delList.add(sysDataDictionary);
}
return updateBatchById(delList);
}
/**
* 词典分类查询
*
* @param sysDataDictionary
* @return
*/
public List<SysDataDictionary> findList(SysDataDictionary sysDataDictionary){
log.info("SysDataDictionaryService - findList sysDataDictionary:{}", sysDataDictionary);
LambdaQueryWrapper<SysDataDictionary> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDataDictionary::getIsDelete, YesOrNoState.NO.getState());
if(StringUtils.isNotEmpty(sysDataDictionary.getDictionaryCode()))
queryWrapper.like(SysDataDictionary::getDictionaryCode, sysDataDictionary.getDictionaryCode());
if(StringUtils.isNotEmpty(sysDataDictionary.getDictionaryName()))
queryWrapper.like(SysDataDictionary::getDictionaryName, sysDataDictionary.getDictionaryName());
return list(queryWrapper);
}
/**
* 获取词典标识
*
* @return
*/
private String findDictionaryCode(){
int count = count();
return String.format("%04d", count+1);
}
}

View File

@ -0,0 +1,165 @@
package com.org.system.service;
import cn.hutool.core.util.ObjectUtil;
import com.org.system.config.async.AsyncFactory;
import com.org.system.config.async.AsyncManager;
import com.org.system.entity.*;
import com.org.system.entity.vo.PersonVo;
import com.org.system.pojo.LoginMenuTreeNode;
import com.org.utils.Constants;
import com.org.utils.MessageUtil;
import com.org.utils.SecurityUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import com.org.utils.exception.UserPasswordNotMatchException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/** 登录校验方法 **/
@Slf4j
@Service
public class SysLoginService {
@Autowired
private TokenService tokenService;
@Resource
private AuthenticationManager authenticationManager;
@Autowired
private SysUserService sysUserService;
@Autowired
private SysUserRoleService sysUserRoleService;
@Autowired
private SysRoleService sysRoleService;
@Autowired
private SysRoleMenuService sysRoleMenuService;
@Autowired
private SysMenuService sysMenuService;
/**
* 登录验证
*
* @param loginBody 登陆用户实体
* @return 结果
*/
public Map<String, String> login(LoginBody loginBody, boolean isCheckState) {
// todo 这里加验证码
// todo 这里加验证码
// todo 这里加验证码
// 用户验证
Authentication authentication = null;
try {
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword()));
} catch (Exception e) {
if (e instanceof BadCredentialsException) {
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, MessageUtil.message("user.password.not.match")));
throw new UserPasswordNotMatchException();
} else {
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
throw new CustomException(e.getMessage());
}
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_SUCCESS, "登陆成功"));
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
loginUser.getUser().setLoginCount(loginUser.getUser().getLoginCount() + 1);
sysUserService.updateById(loginUser.getUser());
// 登录时校验是否存在角色
SysUserRole sysUserRole = sysUserRoleService.getByUserIdAndRoleCode(loginUser.getUser().getId(), loginBody.getRoleCode());
if(ObjectUtil.isEmpty(sysUserRole)) throw new CustomException("当前用户没有该角色");
Integer status = loginUser.getUser().getStatus();
// 登录时是否校验账号状态
if (isCheckState && status != 1) {
String msg = status == 2 ? "审核中,请稍后再试": "已停用";
throw new CustomException("您的账号" + msg);
}
loginUser.setCurrentRoleCode(loginBody.getRoleCode());
Map<String, String> result = new HashMap<>();
// 生成token
String token = tokenService.createToken(loginUser);
result.put("token", token);
return result;
}
/**
* 设置登陆用户当前角色信息
*
*/
public void setLoginUserRole(){
log.info("SysLoginService - setLoginUserRole roleCode:{}", SecurityUtil.getLoginUser().getCurrentRoleCode());
// 获取当前登录账号的所有角色信息
List<SysRole> sysRoleList = null;
if(!SecurityUtil.getLoginUser().ifAdmin()) sysRoleList = sysUserRoleService.findRoleListByUserId(SecurityUtil.getUserId());
else sysRoleList = sysRoleService.findAll();
SecurityUtil.getLoginUser().setRoleList(sysRoleList);
// 获取当前登录账号的当前角色信息
SysRole sysRole = null;
for (SysRole role : sysRoleList) { if(SecurityUtil.getLoginUser().getCurrentRoleCode().equals(role.getCode())) sysRole = role; }
if(ObjectUtil.isEmpty(sysRole)) throw new CustomException("当前用户没有该角色");
SecurityUtil.getLoginUser().setCurrentRole(sysRole);
// 获取当前登录账号当前角色的菜单
List<SysMenu> sysMenuList = null;
if(!SecurityUtil.getLoginUser().ifAdmin()) sysMenuList = sysRoleMenuService.findMenuListByRoleId(sysRole.getId());
else sysMenuList = sysMenuService.findAll();
List<LoginMenuTreeNode> loginMenuTreeNodeList = sysMenuService.convertSysMenuToLoginMenu(sysMenuList);
SecurityUtil.getLoginUser().setMenus(loginMenuTreeNodeList);
// 获取当前登录账号当前角色的权限
Set<String> permissions = new HashSet<>();
if(SecurityUtil.getLoginUser().ifAdmin()){
permissions.add(PermissionService.ALL_PERMISSION);
} else {
for (SysMenu sysMenu : sysMenuList) { if(StringUtils.isNotEmpty(sysMenu.getPermission())) permissions.add(sysMenu.getPermission()); }
}
SecurityUtil.getLoginUser().setPermissions(permissions);
tokenService.refreshToken(SecurityUtil.getLoginUser());
}
public PersonVo getUserInfo(Long userId) {
PersonVo personVo = new PersonVo();
/*XmPerson person = xmPersonService.getByUserId(userId);
if (person == null) throw new CustomException("未查询到人员信息");
PersonVo personVo = new PersonVo();
BeanUtils.copyProperties(person, personVo);
SysOrg sysOrg = sysOrgService.getById(person.getOrgId());
if (sysOrg.getType() == 1) {
// 如果组织为单位则直接返回单位名称
personVo.setUnit(sysOrg.getName());
} else {
// 先查询出部门信息再查询所属单位
SysOrg parentOrg = sysOrgService.findUnitByOrgId(sysOrg.getPid());
personVo.setUnit(parentOrg.getName());
personVo.setDept(sysOrg.getName());
}
personVo.setPersonId(person.getId());
// 学时
BigDecimal yearClassHour = studyRecordService.getBaseMapper().getYearSumStudyHours(person.getId());
personVo.setYearClassHour(yearClassHour);
BigDecimal sumClassHour = studyRecordService.getBaseMapper().getSumStudyHours(person.getId());
personVo.setSumClassHour(sumClassHour);*/
return personVo;
}
}

View File

@ -0,0 +1,339 @@
package com.org.system.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysMenu;
import com.org.system.enums.MenuTypeEnum;
import com.org.system.enums.YesOrNoState;
import com.org.system.mapper.SysMenuMapper;
import com.org.system.pojo.LoginMenuTreeNode;
import com.org.utils.SecurityUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class SysMenuService extends ServiceImpl<SysMenuMapper, SysMenu> {
@Autowired
private SysUserRoleService sysUserRoleService;
@Autowired
private SysRoleMenuService sysRoleMenuService;
@Transactional(rollbackFor = Exception.class)
public boolean add(SysMenu sysMenu) {
// 校验参数
checkParam(sysMenu, false);
// 设置新的pid
String newPids = createNewPids(sysMenu.getPid());
sysMenu.setPids(newPids);
// 设置启用状态
sysMenu.setCreateBy(SecurityUtil.getUserId());
sysMenu.setCreateTime(new Date());
sysMenu.setIsDelete(YesOrNoState.NO.getState());
return this.save(sysMenu);
}
@Transactional(rollbackFor = Exception.class)
public boolean edit(SysMenu sysMenu) {
// 校验参数
checkParam(sysMenu, true);
// 获取修改的菜单的旧数据库中的
SysMenu oldMenu = getById(sysMenu.getId());
if(oldMenu == null || oldMenu.getId() == null) throw new CustomException("未找到菜单");
// 本菜单旧的pids
Long oldPid = oldMenu.getPid();
String oldPids = oldMenu.getPids();
// 生成新的pid和pids
Long newPid = sysMenu.getPid();
String newPids = this.createNewPids(sysMenu.getPid());
// 父节点有变化,更新子节点
if (!newPid.equals(oldPid)) {
// 查找所有叶子节点包含子节点的子节点
LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(SysMenu::getPids, "[" + oldMenu.getId() + "]");
List<SysMenu> list = this.list(queryWrapper);
list.forEach(child -> {
String oldParentCodesPrefix = oldPids + "[" + oldMenu.getId() + "]" + ",";
String oldParentCodesSuffix = child.getPids().substring(oldParentCodesPrefix.length());
// 子节点pids组成 = 当前菜单新pids + 当前菜单id + 子节点自己的pids后缀
String menuParentCodes = newPids + "[" + oldMenu.getId() + "]" + "," + oldParentCodesSuffix;
child.setPids(menuParentCodes);
});
this.updateBatchById(list);
}
// 设置新的pids
sysMenu.setPids(newPids);
return this.updateById(sysMenu);
}
/**
* 校验参数
*/
private void checkParam(SysMenu sysMenu, boolean isExcludeSelf) {
//菜单类型字典 0目录 1菜单 2按钮
Integer type = sysMenu.getType();
String router = sysMenu.getRouter();
String permission = sysMenu.getPermission();
if (!MenuTypeEnum.BTN.getCode().equals(type) && ObjectUtil.isEmpty(router)) {
throw new CustomException("路由地址为空请检查router参数");
}
if (MenuTypeEnum.BTN.getCode().equals(type)) {
if (ObjectUtil.isEmpty(permission)) {
throw new CustomException("权限标识为空请检查permission参数");
}
}
// 如果是编辑菜单时候pid和id不能一致一致会导致无限递归
if (isExcludeSelf) {
if (sysMenu.getId().equals(sysMenu.getPid())) {
throw new CustomException("父级菜单不能为当前节点,请重新选择父级菜单");
}
// 如果是编辑父id不能为自己的子节点
List<Long> childIdListById = this.getChildIdListById(sysMenu.getId());
if(ObjectUtil.isNotEmpty(childIdListById)) {
if(childIdListById.contains(sysMenu.getPid())) {
throw new CustomException("父节点不能为本节点的子节点,请重新选择父节点");
}
}
}
Long id = sysMenu.getId();
String name = sysMenu.getName();
String code = sysMenu.getCode();
LambdaQueryWrapper<SysMenu> queryWrapperByName = new LambdaQueryWrapper<>();
queryWrapperByName.eq(SysMenu::getName, name)
.eq(SysMenu::getIsDelete, YesOrNoState.NO.getState());
LambdaQueryWrapper<SysMenu> queryWrapperByCode = new LambdaQueryWrapper<>();
queryWrapperByCode.eq(SysMenu::getCode, code)
.eq(SysMenu::getIsDelete, YesOrNoState.NO.getState());
if (isExcludeSelf) {
queryWrapperByName.ne(SysMenu::getId, id);
queryWrapperByCode.ne(SysMenu::getId, id);
}
int countByName = this.count(queryWrapperByName);
int countByCode = this.count(queryWrapperByCode);
if (countByName >= 1) {
throw new CustomException("菜单名称重复请检查name参数");
}
if (countByCode >= 1) {
throw new CustomException("菜单编码重复请检查code参数");
}
}
/**
* 创建pids的值
* <p>
* 如果pid是0顶级节点pids就是 [0],
* <p>
* 如果pid不是顶级节点pids就是 pid菜单的pids + [pid] + ,
*/
private String createNewPids(Long pid) {
if (pid.equals(0L)) {
return "[" + 0 + "]"
+ ",";
} else {
//获取父菜单
SysMenu parentMenu = this.getById(pid);
return parentMenu.getPids()
+ "[" + pid + "]"
+ ",";
}
}
/**
* 根据菜单ID删除菜单
*
* @param id
* @return
*/
@Transactional
public boolean del(Long id, String deleteReason){
log.info("SysMenuService - del - id:{}", id);
//级联删除子节点
List<Long> childIdList = this.getChildIdListById(id);
childIdList.add(id);
LambdaUpdateWrapper<SysMenu> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.in(SysMenu::getId, childIdList)
.set(SysMenu::getIsDelete, YesOrNoState.YES.getState())
.set(SysMenu::getDeleteBy, SecurityUtil.getUserId())
.set(SysMenu::getDeleteTime, new Date())
.set(SysMenu::getDeleteReason, deleteReason);
boolean flag = this.update(updateWrapper);
// 删除角色菜单引用
sysRoleMenuService.deleteRoleMenuListByMenuIdList(childIdList);
return flag;
}
/**
* 根据节点id获取所有子节点id集合
*/
private List<Long> getChildIdListById(Long id) {
List<Long> childIdList = CollectionUtil.newArrayList();
LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(SysMenu::getPids, "[" + id + "]");
this.list(queryWrapper).forEach(sysMenu -> childIdList.add(sysMenu.getId()));
return childIdList;
}
/**
* 查询菜单列表
* @param sysMenu
* @return
*/
public List<SysMenu> queryList(SysMenu sysMenu) {
LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysMenu::getIsDelete, YesOrNoState.NO.getState());
//根据菜单名称模糊查询
if (StringUtils.isNotEmpty(sysMenu.getName())) {
queryWrapper.like(SysMenu::getName, sysMenu.getName());
}
//根据排序升序排列序号越小越在前
queryWrapper.orderByAsc(SysMenu::getIntCode);
List<SysMenu> sysMenuList = this.list(queryWrapper);
return sysMenuList;
}
public List<SysMenu> findAll(){
log.info("SysMenuService - findAll userid:{}", SecurityUtil.getUserId());
LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysMenu::getIsDelete, YesOrNoState.NO.getState()).orderByAsc(SysMenu::getIntCode);
return this.list(queryWrapper);
}
/**
* 查出并组装树形结构
* @param list 所有节点菜单
* @param pid 父级id
* @return
*/
public List<SysMenu> buildMenuTree(List<SysMenu> list, Long pid){
//组装数据
List<SysMenu> collect = list.stream().filter(sysMenu -> {
return pid.equals(sysMenu.getPid());
}).map(sysMenu -> {
sysMenu.setChildren(getChildren(sysMenu, list));
return sysMenu;
}).collect(Collectors.toList());
return collect;
}
/**
* 在所有列表中查询当前项的子项
* @param o 当前节点
* @param all 所有数据
*/
private List<SysMenu> getChildren(SysMenu o, List<SysMenu> all){
List<SysMenu> children = all.stream().filter((sysMenu) -> {
return o.getId().equals(sysMenu.getPid());
}).map(sysMenu -> {
sysMenu.setChildren(getChildren(sysMenu, all));
return sysMenu;
}).collect(Collectors.toList());
return children;
}
/**
* 获取系统菜单树用于新增编辑时选择上级节点
* @return
*/
public List<SysMenu> tree() {
LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysMenu::getIsDelete, YesOrNoState.NO.getState());
List<SysMenu> allMenu = list(queryWrapper);
allMenu = this.buildMenuTree(allMenu, 0L);
return allMenu;
}
/**
* 获取系统菜单树用于给角色授权时选择
*/
public List<SysMenu> treeForGrant() {
LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysMenu::getIsDelete, YesOrNoState.NO.getState());
//如果是超级管理员给角色授权菜单时可选择所有菜单
if (SecurityUtil.getLoginUser().ifAdmin()) {
// 不加任何判断条件
} else {
//非超级管理员则获取自己拥有的菜单分配给人员防止越级授权
Long userId = SecurityUtil.getUserId();
List<Long> roleIdList = sysUserRoleService.getUserRoleIdList(userId);
if (ObjectUtil.isNotEmpty(roleIdList)) {
List<Long> menuIdList = sysRoleMenuService.getRoleMenuIdList(roleIdList);
if (ObjectUtil.isNotEmpty(menuIdList)) {
queryWrapper.in(SysMenu::getId, menuIdList);
} else {
//如果角色的菜单为空则查不到菜单
return CollectionUtil.newArrayList();
}
} else {
//如果角色为空则根本没菜单
return CollectionUtil.newArrayList();
}
}
queryWrapper.orderByAsc(SysMenu::getIntCode);
List<SysMenu> allMenu = list(queryWrapper);
allMenu = this.buildMenuTree(allMenu, 0L);
return allMenu;
}
/**
* 将SysMenu格式菜单转换为LoginMenuTreeNode菜单
*/
public List<LoginMenuTreeNode> convertSysMenuToLoginMenu(List<SysMenu> sysMenuList) {
List<LoginMenuTreeNode> antDesignMenuTreeNodeList = CollectionUtil.newArrayList();
sysMenuList.forEach(sysMenu -> {
if(sysMenu.getType() != MenuTypeEnum.BTN.getCode()) {
LoginMenuTreeNode loginMenuTreeNode = new LoginMenuTreeNode();
loginMenuTreeNode.setComponent(sysMenu.getComponent());
loginMenuTreeNode.setId(sysMenu.getId());
loginMenuTreeNode.setName(sysMenu.getCode());
loginMenuTreeNode.setPath(sysMenu.getRouter());
loginMenuTreeNode.setPid(sysMenu.getPid());
LoginMenuTreeNode.Meta mateItem = new LoginMenuTreeNode().new Meta();
mateItem.setTitle(sysMenu.getName());
//是否可见
mateItem.setShow(YesOrNoState.YES.getState() == sysMenu.getVisible());
loginMenuTreeNode.setMeta(mateItem);
antDesignMenuTreeNodeList.add(loginMenuTreeNode);
}
});
return antDesignMenuTreeNodeList;
}
}

View File

@ -0,0 +1,23 @@
package com.org.system.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysOperLog;
import com.org.system.mapper.SysOperLogMapper;
import com.org.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class SysOperLogService extends ServiceImpl<SysOperLogMapper, SysOperLog> {
public List<SysOperLog> queryList(SysOperLog sysOperLog) {
log.info("SysOperLogService - queryList sysOperLog:{}", sysOperLog);
LambdaQueryWrapper<SysOperLog> queryWrapper = new LambdaQueryWrapper<>();
if(StringUtils.isNotEmpty(sysOperLog.getTitle())) queryWrapper.like(SysOperLog::getTitle, sysOperLog.getTitle());
return list(queryWrapper);
}
}

View File

@ -0,0 +1,64 @@
package com.org.system.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysMenu;
import com.org.system.entity.SysRoleMenu;
import com.org.system.mapper.SysRoleMenuMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class SysRoleMenuService extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> {
public List<Long> getRoleMenuIdList(List<Long> roleIdList) {
if(ObjectUtil.isNotEmpty(roleIdList)) {
LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysRoleMenu::getRoleId, roleIdList);
return this.list(queryWrapper).stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
}
return CollectionUtil.newArrayList();
}
public void grantMenu(Long roleId, List<Long> grantMenuIdList) {
//删除所拥有菜单
LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysRoleMenu::getRoleId, roleId);
this.remove(queryWrapper);
//授权菜单
grantMenuIdList.forEach(menuId -> {
SysRoleMenu sysRoleMenu = new SysRoleMenu();
sysRoleMenu.setRoleId(roleId);
sysRoleMenu.setMenuId(menuId);
this.save(sysRoleMenu);
});
}
public void deleteRoleMenuListByMenuIdList(List<Long> menuIdList) {
LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysRoleMenu::getMenuId, menuIdList);
this.remove(queryWrapper);
}
public void deleteRoleMenuListByRoleId(Long roleId) {
LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysRoleMenu::getRoleId, roleId);
this.remove(queryWrapper);
}
/**
* 根据角色ID获取菜单
* @param roleId
* @return
*/
public List<SysMenu> findMenuListByRoleId(Long roleId) {
return baseMapper.findMenuListByRoleId(roleId);
}
}

View File

@ -0,0 +1,178 @@
package com.org.system.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysRole;
import com.org.system.enums.YesOrNoState;
import com.org.system.mapper.SysRoleMapper;
import com.org.utils.SecurityUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class SysRoleService extends ServiceImpl<SysRoleMapper, SysRole> {
@Autowired
private SysRoleMenuService sysRoleMenuService;
@Autowired
private SysUserRoleService sysUserRoleService;
/**
* 新增或修改
*
* @param sysRole
* @return
*/
public boolean saveOrUpdate(SysRole sysRole){
log.info("SysRoleService - saveOrUpdate sysRole:{}", sysRole);
if(StringUtils.isNull(sysRole.getId())){
//校验参数检查是否存在相同的名称和编码
checkParam(sysRole, false);
// 新增
sysRole.setParentId(sysRole.getParentId() == null ? -1 : sysRole.getParentId());
sysRole.setCreateBy(SecurityUtil.getUserId());
sysRole.setCreateTime(new Date());
sysRole.setIsDelete(YesOrNoState.NO.getState());
log.info("SysRoleService - saveOrUpdate save sysRole:{}", sysRole);
return save(sysRole);
} else {
//校验参数检查是否存在相同的名称和编码
checkParam(sysRole, true);
// 修改
SysRole sysRoleOld = querySysRole(sysRole.getId());
sysRoleOld.setName(sysRole.getName());
sysRoleOld.setCode(sysRole.getCode());
sysRoleOld.setSort(sysRole.getSort());
sysRoleOld.setOrgCode(sysRole.getOrgCode());
sysRoleOld.setParentId(sysRole.getParentId());
sysRoleOld.setUpdateBy(SecurityUtil.getUserId());
sysRoleOld.setUpdateTime(new Date());
log.info("SysRoleService - saveOrUpdate update sysRole:{}", sysRoleOld);
return updateById(sysRoleOld);
}
}
/**
* 校验参数检查是否存在相同的名称
*/
private void checkParam(SysRole sysRole, boolean isExcludeSelf) {
Long id = sysRole.getId();
String name = sysRole.getName();
String code = sysRole.getCode();
LambdaQueryWrapper<SysRole> queryWrapperByName = new LambdaQueryWrapper<>();
queryWrapperByName.eq(SysRole::getName, name)
.eq(SysRole::getIsDelete, YesOrNoState.NO.getState());
LambdaQueryWrapper<SysRole> queryWrapperByCode = new LambdaQueryWrapper<>();
queryWrapperByCode.eq(SysRole::getCode, code)
.eq(SysRole::getIsDelete, YesOrNoState.NO.getState());
//是否排除自己如果排除自己则不查询自己的id
if (isExcludeSelf) {
queryWrapperByName.ne(SysRole::getId, id);
queryWrapperByCode.ne(SysRole::getId, id);
}
int countByName = this.count(queryWrapperByName);
int countByCode = this.count(queryWrapperByCode);
if (countByName >= 1) {
throw new CustomException("角色名称重复请检查name参数");
}
if (countByCode >= 1) {
throw new CustomException("角色编码重复请检查code参数");
}
}
/**
* 获取系统角色
*/
private SysRole querySysRole(Long id) {
SysRole sysRole = this.getById(id);
if (ObjectUtil.isNull(sysRole)) {
throw new CustomException("角色不存在");
}
return sysRole;
}
/**
* 删除
*/
@Transactional
public boolean del(Long id){
SysRole sysRole = querySysRole(id);
// 删除角色菜单引用
sysRoleMenuService.deleteRoleMenuListByRoleId(sysRole.getId());
// 删除用户角色引用
sysUserRoleService.delByRoleId(sysRole.getId());
sysRole.setIsDelete(YesOrNoState.YES.getState());
sysRole.setDeleteBy(SecurityUtil.getUserId());
sysRole.setDeleteTime(new Date());
return updateById(sysRole);
}
/**
* 查询角色
*
* @param sysRole
* @return
*/
public List<SysRole> findList(SysRole sysRole){
log.info("SysRoleService - findList - sysRole:{}", sysRole);
if(sysRole.getParentId() == null) sysRole.setParentId(-1L);
LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysRole::getParentId, sysRole.getParentId())
.eq(SysRole::getIsDelete, YesOrNoState.NO.getState());
if(StringUtils.isNotEmpty(sysRole.getName())) queryWrapper.like(SysRole::getName, sysRole.getName());
if(StringUtils.isNotNull(sysRole.getOrgCode())) queryWrapper.eq(SysRole::getOrgCode, sysRole.getOrgCode());
return list(queryWrapper);
}
/**
* 查询所有角色信息
* @return
*/
public List<SysRole> findAll(){
log.info("SysRoleService - findAll - userId:{}", SecurityUtil.getUserId());
LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysRole::getIsDelete, YesOrNoState.NO.getState());
return list(queryWrapper);
}
public List<Long> ownMenu(Long id) {
SysRole sysRole = querySysRole(id);
return sysRoleMenuService.getRoleMenuIdList(CollectionUtil.newArrayList(sysRole.getId()));
}
@Transactional(rollbackFor = Exception.class)
public void grantMenu(Long id, List<Long> grantMenuIdList) {
this.querySysRole(id);
sysRoleMenuService.grantMenu(id, grantMenuIdList);
}
}

View File

@ -0,0 +1,157 @@
package com.org.system.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.entity.SysRole;
import com.org.system.entity.SysUser;
import com.org.system.entity.SysUserRole;
import com.org.system.mapper.SysUserRoleMapper;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class SysUserRoleService extends ServiceImpl<SysUserRoleMapper, SysUserRole> {
/**
* 新能用户角色
*
* @param userId
* @param roleIdList
* @return
*/
@Transactional
public boolean save(Long userId, List<Long> roleIdList){
log.info("SysUserRoleService - save userId:{}", userId);
log.info("SysUserRoleService - save roleIdList:{}", roleIdList);
if(StringUtils.isNull(userId)) throw new CustomException("用户ID不能为空");
if(StringUtils.isNull(roleIdList) || roleIdList.size() == 0) throw new CustomException("角色ID不能为空");
List<SysUserRole> sysUserRoleList = new ArrayList<>();
for (Long roleId : roleIdList) {
if(StringUtils.isNull(roleId)) continue;
sysUserRoleList.add(new SysUserRole().setUserId(userId).setRoleId(roleId));
}
return saveBatch(sysUserRoleList);
}
/**
* 根据用户ID删除
*
* @param userId
* @return
*/
public boolean delByUserId(Long userId){
log.info("SysUserRoleService - delByUserId userId:{}", userId);
if(StringUtils.isNull(userId)) throw new CustomException("用户ID不能为空");
return baseMapper.delByUserId(userId) > 0;
}
/**
* 根据角色ID删除
*
* @param roleId
* @return
*/
public boolean delByRoleId(Long roleId){
log.info("SysUserRoleService - delByRoleId roleId:{}", roleId);
if(StringUtils.isNull(roleId)) throw new CustomException("角色ID不能为空");
return baseMapper.delByRoleId(roleId) > 0;
}
/**
* 根据用户ID和角色ID删除
*
* @param userId
* @param roleIdList
* @return
*/
@Transactional
public boolean delByUserIdAndRoleId(Long userId, List<Long> roleIdList){
log.info("SysUserRoleService - delByUserIdAndRoleId userId:{}", userId);
log.info("SysUserRoleService - delByUserIdAndRoleId roleIdList:{}", roleIdList);
if(StringUtils.isNull(userId)) throw new CustomException("用户ID不能为空");
if(StringUtils.isNull(roleIdList) || roleIdList.size() == 0) throw new CustomException("角色ID不能为空");
for (Long roleId : roleIdList) {
baseMapper.delByUserIdAndRoleId(userId, roleId);
}
return true;
}
/**
* 根据角色ID获取用户
*
* @param roleId
* @return
*/
public List<SysUser> findUserListByRoleId(Long roleId){
log.info("SysUserRoleService - findUserListByRoleId roleId:{}", roleId);
if(StringUtils.isNull(roleId)) return new ArrayList<>();
return baseMapper.findUserListByRoleId(roleId);
}
/**
* 根据用户ID获取角色
*
* @param userid
* @return
*/
public List<SysRole> findRoleListByUserId(Long userid){
log.info("SysUserRoleService - findRoleListByUserId roleId:{}", userid);
if(StringUtils.isNull(userid)) return new ArrayList<>();
return baseMapper.findRoleListByUserId(userid);
}
/* 2021-08-28 新增方法*/
public List<Long> getUserRoleIdList(Long userId) {
LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUserRole::getUserId, userId);
return this.list(queryWrapper).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
}
public void grantRole(Long userId, List<Long> grantRoleIdList) {
//删除所拥有角色
LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUserRole::getUserId, userId);
this.remove(queryWrapper);
//授权角色
grantRoleIdList.forEach(roleId -> {
SysUserRole sysUserRole = new SysUserRole();
sysUserRole.setUserId(userId);
sysUserRole.setRoleId(roleId);
this.save(sysUserRole);
});
}
public SysUserRole getByUserIdAndRoleCode(Long userId, String roleCode) {
LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUserRole::getUserId, userId);
queryWrapper.inSql(SysUserRole::getRoleId, "select id from sys_role where is_delete = 0 and code = '" + roleCode + "'");
queryWrapper.last("limit 1");
return this.getOne(queryWrapper);
}
}

View File

@ -0,0 +1,234 @@
package com.org.system.service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.org.system.config.security.Md5PasswordEncoder;
import com.org.system.entity.SysUser;
import com.org.system.enums.YesOrNoState;
import com.org.system.mapper.SysUserMapper;
import com.org.utils.SecurityUtil;
import com.org.utils.SpringUtil;
import com.org.utils.StringUtils;
import com.org.utils.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {
@Autowired
private SysUserRoleService sysUserRoleService;
/**
* 新增或修改系统用户
*
* @param sysUser
* @return
*/
public boolean saveOrUpdate(SysUser sysUser){
log.info("SysUserService - saveOrUpdate sysUser:{}", sysUser);
if(StringUtils.isNull(sysUser.getId())){
// 新增
checkParam(sysUser, false);
sysUser.setSalt(DigestUtil.md5Hex(sysUser.getUserName()));
Md5PasswordEncoder md5PasswordEncoder = Md5PasswordEncoder.getInstance();
md5PasswordEncoder.setSalt(sysUser.getSalt());
sysUser.setPassword(md5PasswordEncoder.encode(sysUser.getPassword()));
sysUser.setStatus(1);
sysUser.setCreateBy(SecurityUtil.getUserId());
sysUser.setCreateTime(new Date());
sysUser.setIsDelete(YesOrNoState.NO.getState());
log.info("SysUserService - saveOrUpdate save sysUser:{}", sysUser);
return save(sysUser);
} else {
// 修改
checkParam(sysUser, true);
SysUser sysUserOld = getById(sysUser.getId());
if(StringUtils.isNull(sysUserOld) || StringUtils.isNull(sysUserOld.getId()))
throw new CustomException("未找到要修改的用户");
// 禁止修改的内容
sysUser.setSalt(null);
sysUser.setPassword(null);
sysUser.setWxOpenId(null);
sysUser.setUpdateBy(SecurityUtil.getUserId());
sysUser.setUpdateTime(new Date());
log.info("SysUserService - saveOrUpdate update sysUser:{}", sysUser);
return updateById(sysUser);
}
}
/**
* 校验参数检查是否存在相同的账号
*/
private void checkParam(SysUser sysUser, boolean isExcludeSelf) {
Long id = sysUser.getId();
String userName = sysUser.getUserName();
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUserName, userName)
.eq(SysUser::getIsDelete, YesOrNoState.NO.getState());
//是否排除自己如果是则查询条件排除自己id
if (isExcludeSelf) {
queryWrapper.ne(SysUser::getId, id);
}
int countByAccount = this.count(queryWrapper);
//大于等于1个则表示重复
if (countByAccount >= 1) {
throw new CustomException("用户名:" + sysUser.getUserName() + "已存在");
}
}
/**
* 根据用户ID删除用户
*
* @param idList
* @param deleteReason
* @return
*/
public boolean del(List<Long> idList, String deleteReason){
log.info("SysUserService - del idList:{}", idList);
log.info("SysUserService - del deleteReason:{}", deleteReason);
if(StringUtils.isNull(idList) || idList.size() == 0) return true;
List<SysUser> sysUserList = new ArrayList<>();
for (Long id : idList) {
SysUser sysUser = getById(id);
if(StringUtils.isNull(sysUser) || StringUtils.isNull(sysUser.getId())) continue;
// 删除用户角色引用
SpringUtil.getBean(SysUserRoleService.class).delByUserId(sysUser.getId());
sysUser.setIsDelete(YesOrNoState.YES.getState());
sysUser.setDeleteBy(SecurityUtil.getUserId());
sysUser.setDeleteTime(new Date());
sysUser.setDeleteReason(deleteReason);
log.info("SysUserService - del sysUser:{}", sysUser);
sysUserList.add(sysUser);
}
return updateBatchById(sysUserList);
}
/**
* 系统用户查询
*
* @param sysUser
* @return
*/
public List<SysUser> findList(SysUser sysUser){
log.info("SysUserService - findList sysUser:{}", sysUser);
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getIsDelete, YesOrNoState.NO.getState());
if(StringUtils.isNotEmpty(sysUser.getName())) queryWrapper.like(SysUser::getName, sysUser.getName());
if(StringUtils.isNotEmpty(sysUser.getUserName())) queryWrapper.like(SysUser::getUserName, sysUser.getUserName());
if(StringUtils.isNotEmpty(sysUser.getPhone())) queryWrapper.like(SysUser::getPhone, sysUser.getPhone());
return list(queryWrapper);
}
/**
* 根据登录名查询系统用户
*
* @param userName
* @return
*/
public SysUser findByUserName(String userName){
log.info("SysUserService - findByUserName userName:{}", userName);
return baseMapper.findByUserName(userName);
}
/**
* 根据登录名或电话查询系统用户
*
* @param userName
* @return
*/
public SysUser findByUserNameOrPhone(String userName) {
log.info("SysUserService - findByUserNameOrPhone userName:{}", userName);
return baseMapper.findByUserNameOrPhone(userName);
}
/**
* 获取系统用户
*/
private SysUser querySysUser(Long id) {
SysUser sysUser = this.getById(id);
if (ObjectUtil.isNull(sysUser)) {
throw new CustomException("用户不存在");
}
return sysUser;
}
public List<Long> ownRole(Long id) {
SysUser sysUser = this.querySysUser(id);
return sysUserRoleService.getUserRoleIdList(sysUser.getId());
}
@Transactional(rollbackFor = Exception.class)
public void grantRole(Long id, List<Long> grantRoleIdList) {
this.querySysUser(id);
sysUserRoleService.grantRole(id, grantRoleIdList);
}
// 重置密码
@Transactional
public boolean resetPwd(Long id) {
// 修改用户密码
SysUser sysUser = this.getById(id);
if (ObjectUtil.isNull(sysUser)) {
throw new CustomException("未查询到用户信息");
}
sysUser.setSalt(DigestUtil.md5Hex(sysUser.getUserName()));
Md5PasswordEncoder md5PasswordEncoder = Md5PasswordEncoder.getInstance();
md5PasswordEncoder.setSalt(sysUser.getSalt());
sysUser.setPassword(md5PasswordEncoder.encode(SysUser.DEFAULT_PASSWORD));
return updateById(sysUser);
}
// 修改密码
@Transactional
public boolean changePwd(String oldPassword, String password) {
// 修改用户密码
SysUser sysUser = this.getById(SecurityUtil.getUserId());
if (ObjectUtil.isNull(sysUser)) {
throw new CustomException("未查询到用户信息");
}
Md5PasswordEncoder.getInstance().setSalt(sysUser.getSalt());
if(!Md5PasswordEncoder.getInstance().matches(oldPassword, sysUser.getPassword())){
throw new CustomException("原密码不正确!");
}
Md5PasswordEncoder md5PasswordEncoder = Md5PasswordEncoder.getInstance();
md5PasswordEncoder.setSalt(sysUser.getSalt());
sysUser.setPassword(md5PasswordEncoder.encode(password));
sysUser.setUpdateBy(sysUser.getId());
sysUser.setUpdateTime(new Date());
return updateById(sysUser);
}
}

View File

@ -0,0 +1,190 @@
package com.org.system.service;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.org.system.entity.LoginUser;
import com.org.system.config.redis.RedisCache;
import com.org.utils.Constants;
import com.org.utils.HttpServletUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/** token验证处理 **/
@Service
public class TokenService
{
// 令牌自定义标识
@Value("${token.header}")
private String header;
// 令牌秘钥
@Value("${token.secret}")
private String secret;
// 令牌有效期默认30分钟
@Value("${token.expireTime}")
private int expireTime;
protected static final long MILLIS_SECOND = 1000;
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
@Autowired
private RedisCache redisCache;
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public LoginUser getLoginUser(HttpServletRequest request) {
// 获取请求携带的令牌
String token = getToken(request);
if (StringUtils.isNotEmpty(token)) {
Claims claims = parseToken(token);
// 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
}
return null;
}
/**
* 设置用户身份信息
*/
public void setLoginUser(LoginUser loginUser) {
if (null != loginUser && StringUtils.isNotEmpty(loginUser.getToken())) refreshToken(loginUser);
}
/**
* 删除用户身份信息
*/
public void delLoginUser(String token) {
if (StringUtils.isNotEmpty(token)) {
String userKey = getTokenKey(token);
redisCache.deleteObject(userKey);
}
}
/**
* 创建令牌
*
* @param loginUser 用户信息
* @return 令牌
*/
public String createToken(LoginUser loginUser) {
String token = IdUtil.fastUUID();
loginUser.setToken(token);
setUserAgent(loginUser);
refreshToken(loginUser);
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims);
}
/**
* 验证令牌有效期相差不足20分钟自动刷新缓存
*
* @param loginUser
* @return 令牌
*/
public void verifyToken(LoginUser loginUser) {
long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) refreshToken(loginUser);
}
/**
* 刷新令牌有效期
*
* @param loginUser 登录信息
*/
public void refreshToken(LoginUser loginUser) {
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}
/**
* 设置用户代理信息
*
* @param loginUser 登录信息
*/
public void setUserAgent(LoginUser loginUser) {
UserAgent userAgent = UserAgentUtil.parse(HttpServletUtil.getRequest().getHeader("User-Agent"));
String ip = ServletUtil.getClientIP(HttpServletUtil.getRequest(), "");
loginUser.setIpaddr(ip);
loginUser.setLoginLocation("");
loginUser.setBrowser(userAgent.getBrowser().getName());
loginUser.setOs(userAgent.getOs().getName());
}
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
private String createToken(Map<String, Object> claims) {
String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
private Claims parseToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
/**
* 从令牌中获取用户名
*
* @param token 令牌
* @return 用户名
*/
public String getUsernameFromToken(String token) {
Claims claims = parseToken(token);
return claims.getSubject();
}
/**
* 获取请求token
*
* @param request
* @return token
*/
private String getToken(HttpServletRequest request) {
String token = request.getHeader(header);
if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
token = token.replace(Constants.TOKEN_PREFIX, "");
}
return token;
}
private String getTokenKey(String uuid) {
return Constants.LOGIN_TOKEN_KEY + uuid;
}
}

View File

@ -0,0 +1,46 @@
package com.org.ueditor.controller;
import com.org.oss.service.SysOssService;
import com.org.system.annotation.Log;
import com.org.system.enums.BusinessType;
import com.org.ueditor.domain.UeditorConfig;
import com.org.ueditor.domain.UeditorConfigJson;
import com.org.utils.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Slf4j
@RestController
@RequestMapping("sys/ueditor")
public class UeditorContorller {
@Autowired
private SysOssService sysOssService;
@Log(title = "富文本上传", businessType = BusinessType.INSERT)
@RequestMapping("/config")
public Object ueditorConfig(MultipartFile upfile, String action) throws IOException {
log.info("UeditorContorller - ueditorConfig action:{}", action);
switch (action) {
case "config":
log.info("UeditorContorller - ueditorConfig get config json");
return new UeditorConfigJson();
case "uploadimage":
log.info("UeditorContorller - ueditorConfig uploadimage");
AjaxResult upload = sysOssService.upload(upfile, "ueditor", "ueditor");
String url = upload.get("zoomUrl") != null ? upload.get("zoomUrl").toString() : upload.get("url").toString();
url = String.format("%s?width=1024", url);
return new UeditorConfig("SUCCESS", url, upfile.getSize(), upfile.getContentType(), upfile.getOriginalFilename(), upfile.getOriginalFilename());
}
return "请求失败";
}
}

View File

@ -0,0 +1,29 @@
package com.org.ueditor.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UeditorConfig {
/* 状态 */
private String state;
/* 回显路径 */
private String url;
/* 大小 */
private long size;
/* 类型 */
private String type;
/* 文件title */
private String title;
/* 名称 */
private String original;
}

View File

@ -0,0 +1,140 @@
package com.org.ueditor.domain;
import lombok.Data;
@Data
public class UeditorConfigJson {
/* 上传图片配置项 */
/* 执行上传图片的action名称 */
private String imageActionName = "uploadimage";
/* 提交的图片表单名称 */
private String imageFieldName = "upfile";
/* 上传大小限制单位B */
private long imageMaxSize = 2048000;
/* 上传图片格式显示 */
private String[] imageAllowFiles = new String[]{".png", ".jpg", ".jpeg", ".gif", ".bmp"};
/* 是否压缩图片;默认是true */
private boolean imageCompressEnable = true;
/* 图片压缩最长边限制 */
private long imageCompressBorder = 1600;
/* 插入的图片浮动方式 */
private String imageInsertAlign = "none";
/* 图片访问路径前缀 */
private String imageUrlPrefix = "";
/* 上传保存路径;可以自定义保存路径和文件名格式 */
/* {filename} 会替换成原文件名;配置这项需要注意中文乱码问题 */
/* {rand:6} 会替换成随机数;后面的数字是随机数的位数 */
/* {time} 会替换成时间戳 */
/* {yyyy} 会替换成四位年份 */
/* {yy} 会替换成两位年份 */
/* {mm} 会替换成两位月份 */
/* {dd} 会替换成两位日期 */
/* {hh} 会替换成两位小时 */
/* {ii} 会替换成两位分钟 */
/* {ss} 会替换成两位秒 */
/* 非法字符 \ : * ? " < > | */
/* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
private String imagePathFormat = "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
/* 涂鸦图片上传配置项 */
/* 执行上传涂鸦的action名称 */
private String scrawlActionName = "uploadscrawl";
/* 提交的图片表单名称 */
private String scrawlFieldName = "upfile";
/* 上传保存路径;可以自定义保存路径和文件名格式 */
private String scrawlPathFormat = "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
/* 上传大小限制单位B */
private long scrawlMaxSize = 2048000;
/* 图片访问路径前缀 */
private String scrawlUrlPrefix = "";
private String scrawlInsertAlign = "none";
/* 截图工具上传 */
/* 执行上传截图的action名称 */
private String snapscreenActionName = "uploadimage";
/* 上传保存路径;可以自定义保存路径和文件名格式 */
private String snapscreenPathFormat = "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
/* 图片访问路径前缀 */
private String snapscreenUrlPrefix = "";
/* 插入的图片浮动方式 */
private String snapscreenInsertAlign = "none";
/* 抓取远程图片配置 */
private String[] catcherLocalDomain = new String[]{"127.0.0.1", "localhost", "img.baidu.com"};
/* 执行抓取远程图片的action名称 */
private String catcherActionName = "catchimage";
/* 提交的图片列表表单名称 */
private String catcherFieldName = "source";
/* 上传保存路径;可以自定义保存路径和文件名格式 */
private String catcherPathFormat = "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}";
/* 图片访问路径前缀 */
private String catcherUrlPrefix = "";
/* 上传大小限制单位B */
private long catcherMaxSize = 2048000;
/* 抓取图片格式显示 */
private String[] catcherAllowFiles = new String[]{".png", ".jpg", ".jpeg", ".gif", ".bmp"};
/* 上传视频配置 */
/* 执行上传视频的action名称 */
private String videoActionName = "uploadvideo";
/* 提交的视频表单名称 */
private String videoFieldName = "upfile";
/* 上传保存路径;可以自定义保存路径和文件名格式 */
private String videoPathFormat = "/ueditor/jsp/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}";
/* 视频访问路径前缀 */
private String videoUrlPrefix = "";
/* 上传大小限制单位B默认100MB */
private long videoMaxSize = 102400000;
/* 上传视频格式显示 */
private String[] videoAllowFiles = new String[]{".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"};
/* 上传文件配置 */
/* controller里;执行上传视频的action名称 */
private String fileActionName = "uploadfile";
/* 提交的文件表单名称 */
private String fileFieldName = "upfile";
/* 上传保存路径;可以自定义保存路径和文件名格式 */
private String filePathFormat = "/ueditor/jsp/upload/file/{yyyy}{mm}{dd}/{time}{rand:6}";
/* 文件访问路径前缀 */
private String fileUrlPrefix = "";
/* 上传大小限制单位B默认50MB */
private long fileMaxSize = 51200000;
/* 上传文件格式显示 */
private String[] fileAllowFiles = new String[]{ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv",
".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav",
".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx",
".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"};
/* 列出指定目录下的图片 */
/* 执行图片管理的action名称 */
private String imageManagerActionName = "listimage";
/* 指定要列出图片的目录 */
private String imageManagerListPath = "/ueditor/jsp/upload/image/";
/* 每次列出文件数量 */
private long imageManagerListSize = 20;
/* 图片访问路径前缀 */
private String imageManagerUrlPrefix = "";
/* 插入的图片浮动方式 */
private String imageManagerInsertAlign = "none";
/* 列出的文件类型 */
private String[] imageManagerAllowFiles = new String[]{".png", ".jpg", ".jpeg", ".gif", ".bmp"};
/* 列出指定目录下的文件 */
/* 执行文件管理的action名称 */
private String fileManagerActionName = "listfile";
/* 指定要列出文件的目录 */
private String fileManagerListPath = "/ueditor/jsp/upload/file/";
/* 文件访问路径前缀 */
private String fileManagerUrlPrefix = "";
/* 每次列出文件数量 */
private long fileManagerListSize = 20;
/* 列出的文件类型 */
private String[] fileManagerAllowFiles = new String[]{".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf",
".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3",
".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls",
".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"};
}

View File

@ -0,0 +1,119 @@
package com.org.utils;
import org.springframework.http.HttpStatus;
import java.util.HashMap;
/** 操作消息提醒 **/
public class AjaxResult extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
/** 状态码 */
public static final String CODE_TAG = "code";
/** 返回内容 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/** 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息 **/
public AjaxResult() { }
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
*/
public AjaxResult(int code, String msg){
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResult(int code, String msg, Object data){
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (data != null) super.put(DATA_TAG, data);
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static AjaxResult success() { return AjaxResult.success("操作成功"); }
/**
* 返回成功数据
*
* @return 成功消息
*/
public static AjaxResult success(Object data) { return AjaxResult.success("操作成功", data); }
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResult success(String msg) { return AjaxResult.success(msg, null); }
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResult success(String msg, Object data) { return new AjaxResult(HttpStatus.OK.value(), msg, data); }
/**
* 返回错误消息
*
* @return
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(String msg) { return AjaxResult.error(msg, null); }
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult error(String msg, Object data) { return new AjaxResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, data); }
/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(int code, String msg) { return new AjaxResult(code, msg, null); }
@Override
public AjaxResult put(String key, Object value) {
super.put(key, value);
return this;
}
}

View File

@ -0,0 +1,140 @@
package com.org.utils;
/** 通用常量信息 **/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 通用成功标识
*/
public static final String SUCCESS = "0";
/**
* 通用失败标识
*/
public static final String FAIL = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 验证码有效期分钟
*/
public static final Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
public static final String TOKEN = "token";
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
/**
* 用户ID
*/
public static final String JWT_USERID = "userid";
/**
* 用户名称
*/
public static final String JWT_USERNAME = "sub";
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
/**
* app版本管理 cache key
*/
public static final String SYS_APP_VERSION_KEY = "sys_app_version:";
/**
* app版本强制升级版本号 cache key
*/
public static final String SYS_APP_VERSION_FORCE_KEY = "sys_app_version_force:";
/**
* app版本强制升级版本号 cache key
*/
public static final String SYS_APP_VERSION_NOTICE_KEY = "sys_app_version_notice:";
}

View File

@ -0,0 +1,82 @@
package com.org.utils;
import cn.hutool.core.convert.Convert;
import com.org.utils.exception.CustomException;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpServletUtil {
public static ServletRequestAttributes getServletRequestAttributes(){
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if(requestAttributes == null) throw new CustomException("获取 RequestAttributes 异常");
return (ServletRequestAttributes) requestAttributes;
}
/**
* 获取 HttpServletRequest
*
* @return
*/
public static HttpServletRequest getRequest(){
return getServletRequestAttributes().getRequest();
}
/**
* 获取 HttpServletResponse
*
* @return
*/
public static HttpServletResponse getResponse(){
return getServletRequestAttributes().getResponse();
}
/**
* 获取String参数
*
* @param name
* @return
*/
public static String getParameter(String name) {
return getRequest().getParameter(name);
}
/**
* 获取String参数
*
* @param name
* @param defaultValue
* @return
*/
public static String getParameter(String name, String defaultValue) {
return Convert.toStr(getRequest().getParameter(name), defaultValue);
}
/**
* 获取Integer参数
*
* @param name
* @return
*/
public static Integer getParameterToInt(String name) {
return Convert.toInt(getRequest().getParameter(name));
}
/**
* 获取Integer参数
*
* @param name
* @param defaultValue
* @return
*/
public static Integer getParameterToInt(String name, Integer defaultValue) {
return Convert.toInt(getRequest().getParameter(name), defaultValue);
}
}

View File

@ -0,0 +1,113 @@
package com.org.utils;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.lang.Validator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.*;
@Slf4j
public class ImagePicUtil {
// 缩放至的宽度
public static int zoomWidth = 1024;
// 缩略图的宽度
public static int thumbnailWidth = 400;
/**
* 图片缩放
* @param filePath
* @param width
* @param fileName
* @return
*/
public static MultipartFile getImagePic(String filePath, int width, String fileName){
log.info("ImagePicUtil - getImagePic filePath:{}", filePath);
log.info("ImagePicUtil - getImagePic width:{}", width);
log.info("ImagePicUtil - getImagePic fileName:{}", fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
Image image = ImageIO.read(new File(filePath));
int image_width = image.getWidth(null);
log.info("ImagePicUtil - getImagePic image_width:{}", image_width);
if(image_width <= width){
log.info("ImagePicUtil - getImagePic not scale");
return null;
}
float scale = Float.parseFloat(String.valueOf(width)) / Float.parseFloat(String.valueOf(image_width));
log.info("ImagePicUtil - getImagePic scale:{}", scale);
// 等比缩放图片
Image scaleImage = ImgUtil.scale(image, scale);
// Image BufferedImage
BufferedImage bufferedImage = new BufferedImage(scaleImage.getWidth(null), scaleImage.getHeight(null), BufferedImage.TYPE_3BYTE_BGR);
Graphics g = bufferedImage.getGraphics();
g.drawImage(scaleImage, 0, 0, null);
// 获取文件后缀
String suffix = filePath.substring(filePath.lastIndexOf(".")+1);
//将newImage写入字节数组输出流
ImageIO.write( bufferedImage, suffix, baos );
} catch (IOException e) {
log.error("{}", e);
} finally {
try {
baos.flush();
baos.close();
} catch (IOException e) {
log.error("PDFUtil - imgToPdf error {}", e);
}
}
MockMultipartFile mockMultipartFile = new MockMultipartFile(fileName, fileName, "image/jpeg", baos.toByteArray());
log.info("ImagePicUtil - getImagePic ok ...");
return mockMultipartFile;
}
/**
* 通过文件路径
* @param path
* @return true-支持 false-不支持
*/
public static boolean checkImageByPath(String path) {
log.info("ImagePicUtil - checkImageByPath path:{}", path);
// 文本课件没有封面
if (Validator.isEmpty(path)) return true;
// 获取文件后缀并且转换小写
String suffix = path.substring(path.lastIndexOf(".")+1).toLowerCase();
log.info("ImagePicUtil - checkImageByPath suffix:{}", suffix);
String str = constMap1.get(suffix);
log.info("ImagePicUtil - checkImageByPath str:{}", str);
if (Validator.isNotEmpty(str)) return true;
return false;
}
/**
* 支持的图片
*/
private static final Map<String, String> constMap1 = new HashMap<String, String>() {
{
put("jpg", "jpg");
put("jpeg", "jpeg");
put("png", "png");
}
};
}

View File

@ -0,0 +1,19 @@
package com.org.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
/** 获取i18n资源文件 **/
public class MessageUtil {
/**
* 根据消息键和参数 获取消息 委托给spring messageSource
*
* @param code 消息键
* @param args 参数
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args) {
MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}

View File

@ -0,0 +1,53 @@
package com.org.utils;
import com.org.system.entity.LoginUser;
import com.org.utils.exception.CustomException;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
/** 安全服务工具类 **/
public class SecurityUtil {
/** 获取Authentication **/
public static Authentication getAuthentication() { return SecurityContextHolder.getContext().getAuthentication(); }
/**
* 当前是否登录
*
* @return
*/
public static boolean isLogin(){
String principal = getAuthentication().getPrincipal().toString();
if("anonymousUser".equals(principal)) return false;
return true;
}
/** 获取用户 **/
public static LoginUser getLoginUser() {
try {
return (LoginUser) getAuthentication().getPrincipal();
} catch (Exception e) {
throw new CustomException("获取用户信息异常", HttpStatus.UNAUTHORIZED.value());
}
}
/** 获取用户ID **/
public static Long getUserId() {
try {
return getLoginUser().getUser().getId();
} catch (Exception e) {
throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED.value());
}
}
/** 获取用户账户 **/
public static String getUsername() {
try {
return getLoginUser().getUsername();
} catch (Exception e) {
throw new CustomException("获取用户账户异常", HttpStatus.UNAUTHORIZED.value());
}
}
}

View File

@ -0,0 +1,111 @@
package com.org.utils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/** spring工具类 方便在非spring管理环境中获取bean **/
@Component
public final class SpringUtil implements BeanFactoryPostProcessor, ApplicationContextAware
{
/** Spring应用上下文环境 */
private static ConfigurableListableBeanFactory beanFactory;
private static ApplicationContext applicationContext;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { SpringUtil.beanFactory = beanFactory; }
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringUtil.applicationContext = applicationContext; }
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException { return (T) beanFactory.getBean(name); }
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException { return (T) beanFactory.getBean(clz); }
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name) { return beanFactory.containsBean(name); }
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype 如果与给定名字相应的bean定义没有被找到将会抛出一个异常NoSuchBeanDefinitionException
*
* @param name
* @return boolean
* @throws NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { return beanFactory.isSingleton(name); }
/**
* @param name
* @return Class 注册对象的类型
* @throws NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException { return beanFactory.getType(name); }
/**
* 如果给定的bean名字在bean定义中有别名则返回这些别名
*
* @param name
* @return
* @throws NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { return beanFactory.getAliases(name); }
/**
* 获取aop代理对象
*
* @param invoker
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker) { return (T) AopContext.currentProxy(); }
/**
* 获取当前的环境配置无配置返回null
*
* @return 当前的环境配置
*/
public static String[] getActiveProfiles() { return applicationContext.getEnvironment().getActiveProfiles(); }
/**
* 获取当前的环境配置当有多个环境配置时只获取第一个
*
* @return 当前的环境配置
*/
public static String getActiveProfile() {
final String[] activeProfiles = getActiveProfiles();
if(activeProfiles == null || activeProfiles.length == 0) return null;
return activeProfiles[0];
}
}

View File

@ -0,0 +1,32 @@
package com.org.utils;
import com.org.utils.exception.BaseException;
/** sql操作工具类 **/
public class SqlUtil {
/** 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) **/
public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
/**
* 检查字符防止注入绕过
*
* @param value
* @return
*/
public static String escapeOrderBySql(String value) {
if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
throw new BaseException("参数不符合规范,不能进行查询");
return value;
}
/**
* 验证 order by 语法是否符合规范
*
* @param value
* @return
*/
public static boolean isValidOrderBySql(String value) {
return value.matches(SQL_PATTERN);
}
}

View File

@ -0,0 +1,370 @@
package com.org.utils;
import cn.hutool.core.text.StrFormatter;
import java.util.*;
/** 字符串工具类 **/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
/** 空字符串 */
private static final String NULLSTR = "";
/** 下划线 */
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll) {
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll) {
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
** @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects) {
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects) {
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map) {
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str) {
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object) {
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object) {
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object) {
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str) {
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start) {
if (str == null) return NULLSTR;
if (start < 0) start = str.length() + start;
if (start < 0) start = 0;
if (start > str.length()) return NULLSTR;
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end) {
if (str == null) return NULLSTR;
if (end < 0) end = str.length() + end;
if (start < 0) start = str.length() + start;
if (end > str.length()) end = str.length();
if (start > end) return NULLSTR;
if (start < 0) start = 0;
if (end < 0) end = 0;
return str.substring(start, end);
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params) {
if (isEmpty(params) || isEmpty(template)) return template;
return StrFormatter.format(template, params);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static final Set<String> str2Set(String str, String sep) {
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
List<String> list = new ArrayList<String>();
if (StringUtils.isEmpty(str)) return list;
// 过滤空白字符串
if (filterBlank && StringUtils.isBlank(str)) return list;
String[] split = str.split(sep);
for (String string : split) {
if (filterBlank && StringUtils.isBlank(string)) continue;
if (trim) string = string.trim();
list.add(string);
}
return list;
}
/**
* 下划线转驼峰命名
*/
public static String toUnderScoreCase(String str) {
if (str == null) return null;
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (i > 0) preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
else preCharIsUpperCase = false;
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1)) nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) sb.append(SEPARATOR);
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) sb.append(SEPARATOR);
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs) {
if (str != null && strs != null) {
for (String s : strs) {
if (str.equalsIgnoreCase(trim(s))) return true;
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name) {
StringBuilder result = new StringBuilder();
if (name == null || name.isEmpty()) return "";
else if (!name.contains("_")) return name.substring(0, 1).toUpperCase() + name.substring(1);
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头结尾的下换线或双重下划线
if (camel.isEmpty()) continue;
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法 例如user_name->userName
*/
public static String toCamelCase(String s) {
if (s == null) return null;
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == SEPARATOR) {
upperCase = true;
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* 获取固定长度的随机数字字符串
*
* @param strLength
* 长度
* @return 指定长度的随机数字字符串
*
*/
public static String getFixLenNumString(int strLength) {
StringBuilder result = new StringBuilder();
Random random = new Random();
for (int i = 0; i < strLength; i++) {
result.append(random.nextInt(10));
}
return result.toString();
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj) {
return (T) obj;
}
}

View File

@ -0,0 +1,71 @@
package com.org.utils;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
/** 线程相关工具类 **/
@Slf4j
public class Threads {
/** sleep等待,单位为毫秒 **/
public static void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
log.error("{}", e);
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍人超時則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool) {
if (pool != null && !pool.isShutdown()) {
pool.shutdown();
try {
if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
log.info("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
log.error("{}", ie);
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t) {
if (t == null && r instanceof Future<?>) {
try {
Future<?> future = (Future<?>) r;
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
log.error("{}", ce);
t = ce;
} catch (ExecutionException ee) {
log.error("{}", ee);
t = ee.getCause();
} catch (InterruptedException ie) {
log.error("{}", ie);
Thread.currentThread().interrupt();
}
}
if (t != null) {
log.error("{}", t);
}
}
}

View File

@ -0,0 +1,19 @@
package com.org.utils.core;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* Id请求参数对象
*/
@Data
public class IdParams {
/**
* 主键
*/
@NotNull(message = "ID不能为空")
private Long id;
}

View File

@ -0,0 +1,29 @@
package com.org.utils.core;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* 分页参数对象
*/
@Data
public class PageParams {
/**
* 页码默认为1
*/
@NotNull(message = "页码不能为空")
@Min(value = 1, message ="页码不能小于1")
private Integer pageNum = 1;
/**
* 分页大小
*/
@NotNull(message = "分页大小不能为空")
@Min(value = 1, message = "分页大小不能小于1")
@Max(value = 100, message = "分页大小不能大于100")
private Integer pageSize = 10;
}

View File

@ -0,0 +1,80 @@
package com.org.utils.exception;
import cn.hutool.core.util.StrUtil;
import com.org.utils.MessageUtil;
/** 基础异常 **/
public class BaseException extends RuntimeException {
private static final long serialVersionUID = 1L;
/** 所属模块 **/
private String module;
/** 错误码 **/
private String code;
/** 错误码对应的参数 **/
private Object[] args;
/** 错误消息 **/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage) {
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args)
{
this(module, code, args, null);
}
public BaseException(String module, String defaultMessage)
{
this(module, null, null, defaultMessage);
}
public BaseException(String code, Object[] args)
{
this(null, code, args, null);
}
public BaseException(String defaultMessage)
{
this(null, null, null, defaultMessage);
}
@Override
public String getMessage() {
String message = null;
if (!StrUtil.isEmpty(code)) {
message = MessageUtil.message(code, args);
}
if (message == null) {
message = defaultMessage;
}
return message;
}
public String getModule()
{
return module;
}
public String getCode()
{
return code;
}
public Object[] getArgs()
{
return args;
}
public String getDefaultMessage()
{
return defaultMessage;
}
}

View File

@ -0,0 +1,39 @@
package com.org.utils.exception;
/** 自定义异常 **/
public class CustomException extends RuntimeException
{
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
public CustomException(String message)
{
this.message = message;
}
public CustomException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public CustomException(String message, Throwable e)
{
super(message, e);
this.message = message;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
}

Some files were not shown because too many files have changed in this diff Show More