提交 8c7217eb 编写于 作者: E Elune

代码优化

上级 7d22178f
......@@ -9,13 +9,15 @@
</div>
#### 项目简介
eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前后端分离的后台管理系统, 权限控制的方式为RBAC,项目支持数据字典与数据权限管理,支持一键生成前后端代码,支持前端菜单动态路由
一个基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统
**开发文档** [https://docs.auauz.net/](https://docs.auauz.net)
**项目开发文档:** [https://docs.auauz.net/](https://docs.auauz.net)
**体验地址** [https://auauz.net/](https://auauz.net/)
**稳定版本体验地址:** [https://auauz.net/](https://auauz.net/)
**账号密码** ```admin/123456```(默认密码都是123456)
**开发版本体验地址:** [http://dev.auauz.net/](http://dev.auauz.net/)
**账号密码:** `admin/123456` (默认密码都是123456)
#### 项目源码
......@@ -24,22 +26,30 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-web |
| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-web |
#### 主要特性
- 使用最新技术栈,社区资源丰富。
- 项目按功能模块化,提升开发,测试效率。
- 高效率开发,使用代码生成器可以一键生成前后端代码
- 支持数据字典,可方便的对一些状态进行管理
- 支持接口限流,避免恶意请求导致服务层压力过大
- 支持接口级别的功能权限与数据权限,可自定义操作
- 自定义权限注解与匿名接口注解,可快速对某一接口拦截与放行
- 对一些常用的前端组件封装:表格数据请求、数据字典等
- 前后端统一异常拦截处理,统一输出异常,避免繁琐的判断
#### 系统功能
- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456
- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
- 部门管理:可配置系统组织架构,树形表格展示
- 岗位管理:配置各个部门的职位
- 字典管理:应广大码友的要求加入字典管理,可维护常用一些固定的数据,如:状态,性别等
- 字典管理:可维护常用一些固定的数据,如:状态,性别等
- 操作日志:记录用户操作的日志
- 异常日志:记录异常日志,方便开发人员定位错误
- 系统缓存:使用jedis将缓存操作可视化,并提供对redis的基本操作,可根据需求自行扩展
- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456
- 服务器监控:被监控服务器运行eladmin-monitor信息收集工具后,可以在页面上看到CPU内存以及磁盘使用情况
- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然
- 代码生成:高灵活度一键生成前后端代码,减少百分之80左右的工作任务
- 邮件工具:配合富文本,发送html格式的邮件
- 免费图床:使用sm.ms图床,用作公共图片上传使用
- 免费图床:使用sm.ms图床,用作公共图片上传使用,该图床不怎么稳定,不太建议使用
- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
......@@ -47,20 +57,19 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
项目采用按功能分模块开发方式,将通用的配置放在公共模块,```system```模块为系统核心模块也是项目入口模块,```logging``` 模块为系统的日志模块,```tools``` 为第三方工具模块,包含了图床、邮件、七牛云、支付宝,```generator``` 为系统的代码生成模块
- eladmin-common 公共模块
- annotation 为系统自定义注解
- aspect 自定义注解的切面
- base 提供了Entity、DTO基类和mapstruct的通用mapper
- config 自定义权限实现、redis配置、swagger配置
- exception 项目统一异常的处理
- utils 系统通用工具类
- annotation 为系统自定义注解
- aspect 自定义注解的切面
- base 提供了Entity、DTO基类和mapstruct的通用mapper
- config 自定义权限实现、redis配置、swagger配置
- exception 项目统一异常的处理
- utils 系统通用工具类
- eladmin-system 系统核心模块(系统启动入口)
- config 配置跨域与静态资源,与数据权限
- thread 线程池相关
- modules 系统相关模块(登录授权、系统监控、定时任务等)
- config 配置跨域与静态资源,与数据权限
- thread 线程池相关
- modules 系统相关模块(登录授权、系统监控、定时任务等)
- eladmin-logging 系统日志模块
- eladmin-tools 系统第三方工具模块
- config 文件上传临时路径配置
- modules 工具相关模块(第三方工具、代码生成工具)
- eladmin-generator 系统代码生成模块
#### 系统预览
......@@ -83,6 +92,6 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
</table>
#### 项目捐赠
项目的发展离不开你的支持,请作者喝杯咖啡吧!ps:辣条也行 ☕! [Donate](https://docs.auauz.net/#/jz)
项目的发展离不开你的支持,请作者喝杯咖啡吧 [Donate](https://docs.auauz.net/#/jz)
#### 反馈交流
- QQ交流群:891137268
......@@ -13,6 +13,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Set;
/**
* @author Zhang houying
* @date 2019-11-03
......@@ -53,12 +55,12 @@ public class ServerController {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@DeleteMapping(value = "/{id}")
@DeleteMapping
@Log("删除服务监控")
@ApiOperation("删除服务监控")
@PreAuthorize("@el.check('server:del')")
public ResponseEntity delete(@PathVariable Integer id){
serverService.delete(id);
return new ResponseEntity(HttpStatus.OK);
public ResponseEntity<Object> delete(@RequestBody Set<Integer> ids){
serverService.delete(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
}
......@@ -7,6 +7,7 @@ import org.springframework.data.domain.Pageable;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Zhang houying
......@@ -53,6 +54,6 @@ public interface ServerService {
* 删除
* @param id /
*/
void delete(Integer id);
void delete(Set<Integer> id);
}
......@@ -18,6 +18,7 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Zhang houying
......@@ -91,8 +92,10 @@ public class ServerServiceImpl implements ServerService {
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Integer id) {
serverRepository.deleteById(id);
public void delete(Set<Integer> ids) {
for (Integer id : ids) {
serverRepository.deleteById(id);
}
}
}
......@@ -48,7 +48,7 @@ public class AuthController {
private Long expiration;
@Value("${rsa.private_key}")
private String privateKey;
@Value("${single.login:true}")
@Value("${single.login:false}")
private Boolean singleLogin;
private final SecurityProperties properties;
private final RedisUtils redisUtils;
......
......@@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;
/**
* @author Zheng Jie
......@@ -43,10 +44,12 @@ public class OnlineController {
}
@ApiOperation("踢出用户")
@DeleteMapping(value = "/{key}")
@DeleteMapping
@PreAuthorize("@el.check()")
public ResponseEntity<Object> delete(@PathVariable String key) throws Exception {
onlineUserService.kickOut(key);
public ResponseEntity<Object> delete(@RequestBody Set<String> keys) throws Exception {
for (String key : keys) {
onlineUserService.kickOut(key);
}
return new ResponseEntity<>(HttpStatus.OK);
}
}
......@@ -51,7 +51,6 @@ public class TokenFilter extends GenericFilterBean {
} else {
log.debug("no valid JWT token found, uri: {}", requestRri);
}
filterChain.doFilter(servletRequest, servletResponse);
}
......
......@@ -4,6 +4,7 @@ import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
......@@ -44,7 +45,7 @@ public class User implements Serializable {
private UserAvatar userAvatar;
@NotBlank
@Pattern(regexp = "([a-z0-9A-Z]+[-|.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}",message = "格式错误")
@Email
private String email;
@NotBlank
......
package me.zhengjie.modules.system.rest;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
......@@ -9,6 +11,7 @@ import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.dto.DeptDto;
import me.zhengjie.modules.system.service.dto.DeptQueryCriteria;
import me.zhengjie.utils.RedisUtils;
import me.zhengjie.utils.ThrowableUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
......@@ -17,7 +20,9 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
......@@ -80,13 +85,21 @@ public class DeptController {
@Log("删除部门")
@ApiOperation("删除部门")
@DeleteMapping(value = "/{id}")
@DeleteMapping
@PreAuthorize("@el.check('dept:del')")
public ResponseEntity<Object> delete(@PathVariable Long id){
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
Set<DeptDto> deptDtos = new HashSet<>();
for (Long id : ids) {
List<Dept> deptList = deptService.findByPid(id);
deptDtos.add(deptService.findById(id));
if(CollectionUtil.isNotEmpty(deptList)){
deptDtos = deptService.getDeleteDepts(deptList, deptDtos);
}
}
try {
deptService.delete(id);
deptService.delete(deptDtos);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该部门存在岗位或者角色关联,请取消关联后再试");
ThrowableUtil.throwForeignKeyException(e, "所选部门中存在岗位或者角色关联,请取消关联后再试");
}
return new ResponseEntity<>(HttpStatus.OK);
}
......
......@@ -15,10 +15,9 @@ import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
......@@ -80,13 +79,13 @@ public class JobController {
@Log("删除岗位")
@ApiOperation("删除岗位")
@DeleteMapping(value = "/{id}")
@DeleteMapping
@PreAuthorize("@el.check('job:del')")
public ResponseEntity<Object> delete(@PathVariable Long id){
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
try {
jobService.delete(id);
jobService.delete(ids);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "岗位存在用户关联,请取消关联后再试");
ThrowableUtil.throwForeignKeyException(e, "所选岗位存在用户关联,请取消关联后再试");
}
return new ResponseEntity<>(HttpStatus.OK);
}
......
......@@ -103,13 +103,15 @@ public class MenuController {
@Log("删除菜单")
@ApiOperation("删除菜单")
@DeleteMapping(value = "/{id}")
@DeleteMapping
@PreAuthorize("@el.check('menu:del')")
public ResponseEntity<Object> delete(@PathVariable Long id){
List<Menu> menuList = menuService.findByPid(id);
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
Set<Menu> menuSet = new HashSet<>();
menuSet.add(menuService.findOne(id));
menuSet = menuService.getDeleteMenus(menuList, menuSet);
for (Long id : ids) {
List<Menu> menuList = menuService.findByPid(id);
menuSet.add(menuService.findOne(id));
menuSet = menuService.getDeleteMenus(menuList, menuSet);
}
menuService.delete(menuSet);
return new ResponseEntity<>(HttpStatus.OK);
}
......
......@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
......@@ -116,14 +117,10 @@ public class RoleController {
@Log("删除角色")
@ApiOperation("删除角色")
@DeleteMapping(value = "/{id}")
@DeleteMapping
@PreAuthorize("@el.check('roles:del')")
public ResponseEntity<Object> delete(@PathVariable Long id){
try {
roleService.delete(id);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该角色存在用户关联,请取消关联后再试");
}
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
roleService.delete(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
}
......@@ -138,17 +138,18 @@ public class UserController {
@Log("删除用户")
@ApiOperation("删除用户")
@DeleteMapping(value = "/{id}")
@DeleteMapping
@PreAuthorize("@el.check('user:del')")
public ResponseEntity<Object> delete(@PathVariable Long id){
public ResponseEntity<Object> delete(@RequestBody Set<Long> ids){
UserDto user = userService.findByName(SecurityUtils.getUsername());
Integer currentLevel = Collections.min(roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
for (Long id : ids) {
Integer currentLevel = Collections.min(roleService.findByUsersId(user.getId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足,不能删除:" + userService.findByName(SecurityUtils.getUsername()).getUsername());
}
}
userService.delete(id);
userService.delete(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
......
......@@ -44,9 +44,10 @@ public interface DeptService {
/**
* 删除
* @param id /
* @param deptDtos /
*
*/
void delete(Long id);
void delete(Set<DeptDto> deptDtos);
/**
* 构建树形数据
......@@ -76,4 +77,12 @@ public interface DeptService {
* @throws IOException /
*/
void download(List<DeptDto> queryAll, HttpServletResponse response) throws IOException;
/**
* 获取待删除的部门
* @param deptList /
* @param deptDtos /
* @return /
*/
Set<DeptDto> getDeleteDepts(List<Dept> deptList, Set<DeptDto> deptDtos);
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Zheng Jie
......@@ -38,9 +39,9 @@ public interface JobService {
/**
* 删除
* @param id /
* @param ids /
*/
void delete(Long id);
void delete(Set<Long> ids);
/**
* 分页查询
......
......@@ -5,7 +5,6 @@ import me.zhengjie.modules.system.service.dto.RoleDto;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDto;
import me.zhengjie.modules.system.service.dto.UserDto;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.GrantedAuthority;
......@@ -43,9 +42,9 @@ public interface RoleService {
/**
* 删除
* @param id /
* @param ids /
*/
void delete(Long id);
void delete(Set<Long> ids);
/**
* 根据用户ID查询
......
......@@ -8,6 +8,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
......@@ -37,9 +38,9 @@ public interface UserService {
/**
* 删除用户
* @param id /
* @param ids /
*/
void delete(Long id);
void delete(Set<Long> ids);
/**
* 根据用户名查询
......
......@@ -17,7 +17,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
......@@ -129,8 +128,10 @@ public class DeptServiceImpl implements DeptService {
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
deptRepository.deleteById(id);
public void delete(Set<DeptDto> deptDtos) {
for (DeptDto deptDto : deptDtos) {
deptRepository.deleteById(deptDto.getId());
}
}
@Override
......@@ -145,4 +146,16 @@ public class DeptServiceImpl implements DeptService {
}
FileUtil.downloadExcel(list, response);
}
@Override
public Set<DeptDto> getDeleteDepts(List<Dept> menuList, Set<DeptDto> deptDtos) {
for (Dept dept : menuList) {
deptDtos.add(deptMapper.toDto(dept));
List<Dept> depts = deptRepository.findByPid(dept.getId());
if(depts!=null && depts.size()!=0){
getDeleteDepts(depts, deptDtos);
}
}
return deptDtos;
}
}
\ No newline at end of file
......@@ -22,10 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author Zheng Jie
......@@ -94,8 +91,10 @@ public class JobServiceImpl implements JobService {
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
jobRepository.deleteById(id);
public void delete(Set<Long> ids) {
for (Long id : ids) {
jobRepository.deleteById(id);
}
}
@Override
......
......@@ -125,8 +125,14 @@ public class RoleServiceImpl implements RoleService {
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
roleRepository.deleteById(id);
public void delete(Set<Long> ids) {
for (Long id : ids) {
try {
roleRepository.deleteById(id);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该角色存在用户关联,请取消关联后再试");
}
}
}
@Override
......
......@@ -138,8 +138,10 @@ public class UserServiceImpl implements UserService {
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
userRepository.deleteById(id);
public void delete(Set<Long> ids) {
for (Long id : ids) {
userRepository.deleteById(id);
}
}
@Override
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册