修改提交

master
cheney 2 years ago
parent c403a5b7f2
commit c4292172ed
  1. 17
      src/main/java/com/huoran/iasf/common/aop/annotation/NoRepeatSubmit.java
  2. 86
      src/main/java/com/huoran/iasf/common/aop/aspect/NoRepeatSubmitAop.java
  3. 228
      src/main/java/com/huoran/iasf/common/aop/aspect/RedisServiceAop.java
  4. 3
      src/main/java/com/huoran/iasf/controller/DeptController.java
  5. 3
      src/main/java/com/huoran/iasf/controller/RoleController.java
  6. 30
      src/main/java/com/huoran/iasf/controller/SysColumnController.java
  7. 2
      src/main/java/com/huoran/iasf/controller/SysContentController.java
  8. 5
      src/main/java/com/huoran/iasf/controller/SysContentFileController.java
  9. 6
      src/main/java/com/huoran/iasf/controller/SysFilesController.java
  10. 12
      src/main/java/com/huoran/iasf/controller/UserController.java
  11. 5
      src/main/java/com/huoran/iasf/controller/UserGroupController.java
  12. 2
      src/main/java/com/huoran/iasf/controller/UserRoleController.java
  13. 5
      src/main/java/com/huoran/iasf/entity/SysFilesEntity.java
  14. 3
      src/main/java/com/huoran/iasf/vo/req/FileParameters.java
  15. 8
      src/main/resources/application-dev.yml

@ -0,0 +1,17 @@
package com.huoran.iasf.common.aop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Description 不重复提交注解
*/
@Target(ElementType.METHOD) // 作用到方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
public @interface NoRepeatSubmit {
String name() default "name:";
}

@ -0,0 +1,86 @@
package com.huoran.iasf.common.aop.aspect;
import javax.servlet.http.HttpServletRequest;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.exception.BusinessException;
import com.huoran.iasf.common.exception.code.BaseResponseCode;
import com.huoran.iasf.common.utils.Constant;
import com.huoran.iasf.common.utils.R;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.Synchronized;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.concurrent.TimeUnit;
import static com.huoran.iasf.service.HttpApiSessionService.APP_SECRET;
/**
* @Description aop解析注解
*/
@Aspect
@Component
public class NoRepeatSubmitAop {
private Log logger = LogFactory.getLog(getClass());
@Autowired
private RedisServiceAop redisService;
@Synchronized
@Around("execution(* com.huoran.*.controller.*.*(..)) && @annotation(noRepeatSubmit)")
public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String token = request.getHeader(Constant.ACCESS_TOKEN);
//如果header中不存在token,则从参数中获取token
if (StringUtils.isEmpty(token)) {
token = request.getParameter(Constant.ACCESS_TOKEN);
}
if (StringUtils.isEmpty(token)) {
throw new BusinessException(BaseResponseCode.TOKEN_ERROR);
}
// 校验并解析token,如果token过期或者篡改,则会返回null
Claims claims = checkJWT(token);
if (null == claims) {
throw new BusinessException(BaseResponseCode.TOKEN_ERROR);
}
String key = token + "-" + request.getServletPath();
if ( !redisService.haskey(key) ) {// 如果缓存中有这个url视为重复提交
Object o = pjp.proceed();
redisService.setCacheObject(key, 0, 1, TimeUnit.SECONDS);
return o;
} else {
redisService.setCacheObject(key, 0, 1, TimeUnit.SECONDS);//点了同样的URL继续限制,直到2次点击中间间隔超过了限制
return R.fail("请勿重复提交或者操作过于频繁!");
}
}
/**
* 校验token
*/
public Claims checkJWT(String token) {
try {
final Claims claims = Jwts.parser().setSigningKey(APP_SECRET).
parseClaimsJws(token).getBody();
return claims;
} catch (Exception e) {
return null;
}
}
}

@ -0,0 +1,228 @@
package com.huoran.iasf.common.aop.aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @Description RedisService
*/
@Component
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisServiceAop {
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @return 缓存的对象
*/
public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value);
return operation;
}
/**
* 缓存基本的对象IntegerString实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
* @return 缓存的对象
*/
public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, value, timeout, timeUnit);
return operation;
}
/**
* 获得缓存的基本对象
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public void deleteObject(String key) {
redisTemplate.delete(key);
}
/**
* 删除集合对象
*
* @param collection
*/
public void deleteObject(Collection collection) {
redisTemplate.delete(collection);
}
/**
* 缓存List数据
*
* @param key 缓存的键值
* @param dataList 待缓存的List数据
* @return 缓存的对象
*/
public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
ListOperations listOperation = redisTemplate.opsForList();
if (null != dataList) {
int size = dataList.size();
for (int i = 0; i < size; i++) {
listOperation.leftPush(key, dataList.get(i));
}
}
return listOperation;
}
/**
* 获得缓存的list对象
*
* @param key 缓存的键值
* @return 缓存键值对应的数据
*/
public <T> List<T> getCacheList(String key) {
List<T> dataList = new ArrayList<T>();
ListOperations<String, T> listOperation = redisTemplate.opsForList();
Long size = listOperation.size(key);
for (int i = 0; i < size; i++) {
dataList.add(listOperation.index(key, i));
}
return dataList;
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
Iterator<T> it = dataSet.iterator();
while (it.hasNext()) {
setOperation.add(it.next());
}
return setOperation;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(String key) {
Set<T> dataSet = new HashSet<T>();
BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
dataSet = operation.members();
return dataSet;
}
/**
* 缓存Map
*
* @param key
* @param dataMap
* @return
*/
public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
HashOperations hashOperations = redisTemplate.opsForHash();
if (null != dataMap) {
for (Map.Entry<String, T> entry : dataMap.entrySet()) {
hashOperations.put(key, entry.getKey(), entry.getValue());
}
}
return hashOperations;
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(String key) {
Map<String, T> map = redisTemplate.opsForHash().entries(key);
return map;
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(String pattern) {
return redisTemplate.keys(pattern);
}
/**
*
* @param key
* @return
*/
public boolean haskey(String key){
return redisTemplate.hasKey(key);
}
public Long getExpire(String key){
return redisTemplate.getExpire(key);
}
public <T> ValueOperations<String, T> setBillObject(String key, List<Map<String, Object>> value) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key, (T) value);
return operation;
}
/**
* 缓存list<Map<String, Object>>
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
* @return 缓存的对象
*/
public <T> ValueOperations<String, T> setBillObject(String key, List<Map<String, Object>> value, Integer timeout, TimeUnit timeUnit) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
operation.set(key,(T)value, timeout, timeUnit);
return operation;
}
/**
* 缓存Map
*
* @param key
* @param dataMap
* @return
*/
public <T> HashOperations<String, String, T> setCKdBillMap(String key, Map<String, T> dataMap) {
HashOperations hashOperations = redisTemplate.opsForHash();
if (null != dataMap) {
for (Map.Entry<String, T> entry : dataMap.entrySet()) {
hashOperations.put(key, entry.getKey(), entry.getValue());
}
}
return hashOperations;
}
}

@ -1,6 +1,7 @@
package com.huoran.iasf.controller;
import com.huoran.iasf.common.aop.annotation.LogAnnotation;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.entity.SysDept;
import com.huoran.iasf.service.DeptService;
@ -29,7 +30,7 @@ import javax.validation.Valid;
public class DeptController {
@Resource
private DeptService deptService;
@NoRepeatSubmit
@PostMapping("/dept")
@ApiOperation(value = "新增组织接口")
@LogAnnotation(title = "机构管理", action = "新增组织")

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huoran.iasf.common.aop.annotation.LogAnnotation;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.entity.SysRole;
import com.huoran.iasf.entity.SysRolePermission;
@ -42,7 +43,7 @@ public class RoleController {
private RolePermissionService rolePermissionService;
@Resource
private HttpSessionService httpSessionService;
@NoRepeatSubmit
@PostMapping("/role")
@ApiOperation(value = "新增角色接口")
@LogAnnotation(title = "角色管理", action = "新增角色")

@ -2,11 +2,9 @@ package com.huoran.iasf.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.Constant;
import com.huoran.iasf.entity.ColumnEntity;
import com.huoran.iasf.entity.SysColumn;
import com.huoran.iasf.entity.SysContent;
import com.huoran.iasf.entity.SysTemplateStyle;
import com.huoran.iasf.entity.*;
import com.huoran.iasf.service.*;
import com.huoran.iasf.vo.req.ColumnWeightReqVO;
import com.huoran.iasf.vo.req.PaginationColumnReqVO;
@ -53,9 +51,13 @@ public class SysColumnController {
@Autowired
public SysTemplateStyleService styleService;
@Autowired
public SysTemplateStyleConfigurationService templateStyleConfigurationService;
@Autowired
public SysFilesService sysFilesService;
@PostMapping("/listWithTree")
@ApiOperation(value = "栏目树结构", response = SysColumn.class)
public R listWithTree(@RequestBody @Validated PaginationColumnReqVO sysColumn) {
@ -82,7 +84,7 @@ public class SysColumnController {
return R.success(sysColumn);
}
@NoRepeatSubmit
@PostMapping("/save")
@ApiOperation(value = "新增", response = SysColumn.class)
public R save(@RequestBody @Valid SysColumn sysColumn) {
@ -100,10 +102,16 @@ public class SysColumnController {
boolean updateState = service.updateById(sysColumn);
return updateState ? R.success() : R.fail("编辑失败");
}
@NoRepeatSubmit
@PostMapping("/delete")
@ApiOperation(value = "删除", response = SysContent.class)
public R delete(@ApiParam(name = "id", value = "主键", required = true) @RequestParam Integer id) {
UpdateWrapper<SysFilesEntity> filesEntityUpdateWrapper = new UpdateWrapper<>();
filesEntityUpdateWrapper.eq("quote_id",id);
filesEntityUpdateWrapper.eq("quote_type",1);
filesEntityUpdateWrapper.set("is_del",1);
sysFilesService.update(filesEntityUpdateWrapper);
boolean delState = service.removeById(id);
QueryWrapper<SysContent> queryWrapper = new QueryWrapper<>();
@ -114,10 +122,18 @@ public class SysColumnController {
return delState ? R.success() : R.fail("删除失败");
}
@NoRepeatSubmit
@PostMapping("/batchDeletion")
@ApiOperation(value = "批量删除栏目", response = SysColumn.class)
public R batchDeletion(@ApiParam(name = "ids", value = "主键", required = true) @RequestParam List<Integer> ids) {
for (Integer id : ids) {
UpdateWrapper<SysFilesEntity> filesEntityUpdateWrapper = new UpdateWrapper<>();
filesEntityUpdateWrapper.eq("quote_id",id);
filesEntityUpdateWrapper.eq("quote_type",1);
filesEntityUpdateWrapper.set("is_del",1);
sysFilesService.update(filesEntityUpdateWrapper);
}
boolean delState = service.removeByIds(ids);
QueryWrapper<SysContent> queryWrapper = new QueryWrapper<>();
queryWrapper.in("column_id", ids);

@ -99,6 +99,7 @@ public class SysContentController {
public R delete(@ApiParam(name = "id", value = "主键", required = true) @RequestParam Integer id) {
UpdateWrapper<SysFilesEntity> queryWrapper = new UpdateWrapper<>();
queryWrapper.eq("quote_id",id);
queryWrapper.eq("quote_type",0);
queryWrapper.set("is_del",1);
sysFilesService.update(queryWrapper);
boolean delState = service.removeById(id);
@ -112,6 +113,7 @@ public class SysContentController {
for (Integer id : ids) {
UpdateWrapper<SysFilesEntity> queryWrapper = new UpdateWrapper<>();
queryWrapper.eq("quote_id",id);
queryWrapper.eq("quote_type",0);
queryWrapper.set("is_del",1);
sysFilesService.update(queryWrapper);
}

@ -1,6 +1,7 @@
package com.huoran.iasf.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.entity.SysContentFile;
import com.huoran.iasf.service.SysContentFileService;
@ -47,7 +48,7 @@ public class SysContentFileController {
return R.success(sysContentFile);
}
@NoRepeatSubmit
@PostMapping("/save")
@ApiOperation(value = "新增", response = SysContentFile.class)
public R save(@RequestBody @ApiParam(name = "文章附件管理表对象", value = "传入json格式", required = true) SysContentFile sysContentFile) {
@ -63,7 +64,7 @@ public class SysContentFileController {
return updateState ? R.success() : R.fail("编辑失败");
}
@NoRepeatSubmit
@PostMapping("/delete")
@ApiOperation(value = "删除", response = SysContentFile.class)
public R delete(@ApiParam(name = "id", value = "主键", required = true) @RequestParam Integer id) {

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.config.NonStaticResourceHttpRequestConfig;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.entity.SysFilesEntity;
@ -59,7 +60,7 @@ public class SysFilesController {
result.put("imageFieldName", "file");
return result.toJSONString();
}
@NoRepeatSubmit
@ApiOperation(value = "新增")
@PostMapping("/upload")
// @RequiresPermissions(value = {"sysFiles:add", "sysContent:update", "sysContent:add"}, logical = Logical.OR)
@ -88,13 +89,12 @@ public class SysFilesController {
eq("id", fileParameters.getId());
return sysFilesService.update(updateWrapper) ? R.success() : R.fail("更新失败");
}
@ApiOperation(value = "文件预览")
@GetMapping("/preview/{id}")
public void preview(@PathVariable String id, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
sysFilesService.preview(id, req, res);
}
@NoRepeatSubmit
@ApiOperation(value = "文件下载")
@GetMapping("/download/{id}")
public void download(@PathVariable String id, HttpServletRequest req, HttpServletResponse res) {

@ -3,6 +3,7 @@ package com.huoran.iasf.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huoran.iasf.common.aop.annotation.LogAnnotation;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.entity.SysUser;
import com.huoran.iasf.service.HttpSessionService;
@ -23,6 +24,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.naming.Name;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
@ -138,7 +140,7 @@ public class UserController {
}
return R.success();
}
@NoRepeatSubmit
@ApiOperation(value = "密码重置", notes = "密码重置")
@GetMapping("/resetPwd")
public R resetPwd(@RequestParam("userId") String userId) {
@ -154,7 +156,7 @@ public class UserController {
subject.logout();
return R.success();
}
@NoRepeatSubmit
@PutMapping("/user/pwd")
@ApiOperation(value = "修改密码接口")
@LogAnnotation(title = "用户管理", action = "更新密码")
@ -167,7 +169,7 @@ public class UserController {
userService.updatePwd(vo);
return R.success();
}
@NoRepeatSubmit
@DeleteMapping("/user")
@ApiOperation(value = "删除用户接口")
@LogAnnotation(title = "用户管理", action = "删除用户")
@ -196,13 +198,13 @@ public class UserController {
public void exportFailureRecord(HttpServletResponse response, @ApiParam(name = "exportCode", value = "importQuestion接口返回的exportCode", required = true) @RequestParam String exportCode) throws Exception {
userService.exportFailureRecord(response, exportCode);
}
@NoRepeatSubmit
@ApiOperation(value = "更换手机号或邮箱--发送验证码")
@PostMapping("/sendPhoneOrEmailCode")
public R sendPhoneOrEmailCode(@RequestBody CheckVo checkVo) {
return userService.sendCheckPhoneCode(checkVo);
}
@NoRepeatSubmit
@ApiOperation(value = "更新手机号或邮箱")
@PostMapping("/updatePhoneOrEmail")
public R updatePhoneOrEmail(@RequestBody UpdatePhoneOrEmailReq updatePhoneOrEmailReq) {

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huoran.iasf.common.aop.annotation.LogAnnotation;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.entity.SysFilesEntity;
import com.huoran.iasf.entity.UserGroup;
@ -35,7 +36,7 @@ public class UserGroupController {
@Autowired
private UserGroupService userGroupService;
@NoRepeatSubmit
@PostMapping("/add")
@ApiOperation(value = "新增用户组")
@LogAnnotation(title = "用户组管理", action = "新增用户组")
@ -49,7 +50,7 @@ public class UserGroupController {
userGroupService.save(userGroup);
return R.success();
}
@NoRepeatSubmit
@DeleteMapping("/delete/{id}")
@ApiOperation(value = "删除用户组")
@LogAnnotation(title = "用户组管理", action = "删除用户组")

@ -1,6 +1,7 @@
package com.huoran.iasf.controller;
import com.huoran.iasf.common.aop.annotation.LogAnnotation;
import com.huoran.iasf.common.aop.annotation.NoRepeatSubmit;
import com.huoran.iasf.common.utils.R;
import com.huoran.iasf.service.UserRoleService;
import com.huoran.iasf.vo.req.UserRoleOperationReqVO;
@ -27,7 +28,6 @@ import javax.validation.Valid;
public class UserRoleController {
@Resource
private UserRoleService userRoleService;
@PostMapping("/user/role")
@ApiOperation(value = "修改或者新增用户角色接口")
@LogAnnotation(title = "用户和角色关联接口", action = "修改或者新增用户角色")

@ -65,9 +65,12 @@ public class SysFilesEntity extends BaseEntity implements Serializable {
@ApiModelProperty(value = "文章是否删除")
private Integer isDel;
@ApiModelProperty(value = "引用文章id")
@ApiModelProperty(value = "引用id")
private Integer quoteId;
@ApiModelProperty(value = "0为文章,1为栏目")
private Integer quoteType;
@TableField(value = "create_date", fill = FieldFill.INSERT)
@ApiModelProperty(value = "创建时间")
private Date createDate;

@ -29,4 +29,7 @@ public class FileParameters {
@ApiModelProperty(value = "是否发布(默认0未发布,1已发布)")
private Integer isRelease;
@ApiModelProperty(value = "0为文章,1为栏目")
private Integer quoteType;
}

@ -6,11 +6,11 @@ spring:
datasource:
master:
username: root
# password: 123456
password: iasf#2022
password: 123456
# password: iasf#2022
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8
# url: jdbc:mysql://192.168.31.136:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8
# url: jdbc:mysql://127.0.0.1:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8
url: jdbc:mysql://192.168.31.136:3306/iasf?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2b8
cache:
type: redis
redis:

Loading…
Cancel
Save