From 1a001fb59924ef450dbdc5ffeda8a0e5af6ea184 Mon Sep 17 00:00:00 2001 From: ArgonarioD Date: Tue, 12 Jul 2022 12:01:04 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8D=E4=BA=86Task=E6=96=B0?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84=EF=BC=8C=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E4=BA=86=E9=99=90=E6=B5=81=E6=8E=A7=E5=88=B6=E5=B9=B6?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E4=BA=86=E6=B5=8B=E8=AF=95=EF=BC=8C=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E4=BA=86=E5=A4=9A=E6=AC=A1=E7=99=BB=E5=BD=95=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5banIP=EF=BC=8C=E4=B8=BAMybatisPlus=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BA=86=E9=98=B2=E5=85=A8=E8=A1=A8=E6=9B=B4=E6=96=B0=E5=8F=8A?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=9A=84=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++- .../advice/ExceptionHandlerAdvice.java | 7 ++- .../annotation/RateLimit.java | 1 + .../projectmanagement/aop/RateLimitAOP.java | 1 - .../config/MybatisPlusConfig.java | 2 + .../controller/ProjectController.java | 2 + .../controller/ProjectGroupController.java | 1 + .../controller/StaffController.java | 9 +++- .../controller/TaskController.java | 21 ++++++-- .../projectmanagement/entity/dto/TaskDTO.java | 3 +- .../service/IStaffService.java | 2 +- .../service/impl/StaffServiceImpl.java | 44 +++++++++++++---- .../service/impl/TaskServiceImpl.java | 8 +++- .../projectmanagement/utils/BeanUtils.java | 3 ++ .../projectmanagement/utils/TimeUtils.java | 18 +++++++ .../utils/http/HttpUtils.java | 48 +++++++++++++++++++ src/main/resources/mapper/TaskMapper.xml | 6 +-- .../rmdjzz/projectmanagement/RedisTests.java | 2 +- 18 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java diff --git a/README.md b/README.md index ce9260f..1747905 100644 --- a/README.md +++ b/README.md @@ -22,4 +22,8 @@ group /project/{projectId}/group 项目日志 项目统计 克隆项目 项目公告 --- -导入账户 大权限 \ No newline at end of file +导入账户 大权限 + +工作进度统计 +个人/项目工作项具体完成统计 +工作项时间进度统计 diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/advice/ExceptionHandlerAdvice.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/advice/ExceptionHandlerAdvice.java index 2ce4e01..0683ab5 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/advice/ExceptionHandlerAdvice.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/advice/ExceptionHandlerAdvice.java @@ -26,26 +26,28 @@ public class ExceptionHandlerAdvice { @ResponseStatus(HttpStatus.UNAUTHORIZED) public ResponseMap handleUnauthorizedException(Exception e) { // log.error(ExceptionUtils.getStackTrace(e)); - // log.error(e.getMessage()); + log.error(e.getMessage(), e); return ResponseMap.of(HttpStatus.UNAUTHORIZED.value(), e.getMessage()); } @ExceptionHandler(BadRequestException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseMap handleBadRequestException(BadRequestException e) { - // log.error(e.getMessage()); + log.error(e.getMessage(), e); return ResponseMap.of(HttpStatus.BAD_REQUEST.value(), e.getMessage()); } @ExceptionHandler(ForbiddenException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public ResponseMap handleForbiddenException(ForbiddenException e) { + log.error(e.getMessage(), e); return ResponseMap.of(HttpStatus.FORBIDDEN.value(), e.getMessage()); } @ExceptionHandler(BindException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ResponseMap handleBindException(BindException e) { + log.error(e.getMessage(), e); return ResponseMap.of(HttpStatus.BAD_REQUEST.value(), e.getAllErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) @@ -56,6 +58,7 @@ public class ExceptionHandlerAdvice { @ExceptionHandler(TooManyRequestException.class) @ResponseStatus(HttpStatus.TOO_MANY_REQUESTS) public ResponseMap handleTooManyRequestException(TooManyRequestException e) { + log.error(e.getMessage(), e); return ResponseMap.of(HttpStatus.TOO_MANY_REQUESTS.value(), e.getMessage()); } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/annotation/RateLimit.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/annotation/RateLimit.java index a971953..dee4e58 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/annotation/RateLimit.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/annotation/RateLimit.java @@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit; * @author 佘语殊 * @since 2022/7/11 16:57 */ +//TODO: 加到代码里 @Retention(RetentionPolicy.RUNTIME) @Documented @Target({ElementType.METHOD}) diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/RateLimitAOP.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/RateLimitAOP.java index 84f0470..2f0e388 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/RateLimitAOP.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/aop/RateLimitAOP.java @@ -38,7 +38,6 @@ public class RateLimitAOP { if (limiter == null) { limiter = RateLimiter.create(limit.permitsPerSecond()); Class clazz = limiter.getClass(); - //TODO: DEBUG TEST Field burstSecondsField = clazz.getDeclaredField("maxBurstSeconds"); burstSecondsField.setAccessible(true); burstSecondsField.set(limiter, limit.maxBurstSeconds()); diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/MybatisPlusConfig.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/MybatisPlusConfig.java index cf60c2e..341c1ed 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/MybatisPlusConfig.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/config/MybatisPlusConfig.java @@ -2,6 +2,7 @@ package cn.edu.hfut.rmdjzz.projectmanagement.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; @@ -23,6 +24,7 @@ public class MybatisPlusConfig { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); return interceptor; } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectController.java index 02a2c19..21efb7b 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectController.java @@ -1,5 +1,6 @@ package cn.edu.hfut.rmdjzz.projectmanagement.controller; +import cn.edu.hfut.rmdjzz.projectmanagement.annotation.RateLimit; import cn.edu.hfut.rmdjzz.projectmanagement.entity.Project; import cn.edu.hfut.rmdjzz.projectmanagement.entity.dto.ProjectDTO; import cn.edu.hfut.rmdjzz.projectmanagement.exception.BadRequestException; @@ -33,6 +34,7 @@ public class ProjectController { private IProjectGroupService projectGroupService; @Operation(summary = "根据Token获取该员工的ProjectList") + //@RateLimit(permitsPerSecond = 1, maxBurstSeconds = 5) @SneakyThrows @GetMapping public ResponseList getProjectListOfStaff( diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java index 7a25712..5d5ab02 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java @@ -111,6 +111,7 @@ public class ProjectGroupController { return ResponseMap.ofSuccess(projectGroupService.collectStatsForGroupPositions(token, projectId)); } + //FIXME: DELETE @SneakyThrows @GetMapping("/{staffId}/stats") public ResponseList getProjectProcessOfStaff( diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java index 0d3ceb6..a111f9a 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java @@ -7,6 +7,7 @@ import cn.edu.hfut.rmdjzz.projectmanagement.exception.TokenException; import cn.edu.hfut.rmdjzz.projectmanagement.service.IStaffService; import cn.edu.hfut.rmdjzz.projectmanagement.utils.FileUtils; import cn.edu.hfut.rmdjzz.projectmanagement.utils.TokenUtils; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.HttpUtils; import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.ResponseMap; import io.swagger.v3.oas.annotations.Parameter; import lombok.SneakyThrows; @@ -15,6 +16,7 @@ import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Objects; @@ -32,9 +34,12 @@ public class StaffController { @PostMapping("/login") public ResponseMap login( @Parameter(description = "只需要传入staffUsername和staffPassword两个属性即可,staffPassword需要md5加密后传输") - @RequestBody Staff staff + @RequestBody Staff staff, + HttpServletRequest request ) { - return ResponseMap.ofSuccess("登录成功", staffService.login(staff.getStaffUsername(), staff.getStaffPassword())); + String requestIpAddress = HttpUtils.getRequestIpAddress(request); + return ResponseMap.ofSuccess("登录成功", + staffService.login(requestIpAddress, staff.getStaffUsername(), staff.getStaffPassword())); } @SneakyThrows diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/TaskController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/TaskController.java index 3c3e718..99dc4db 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/TaskController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/TaskController.java @@ -25,6 +25,7 @@ public class TaskController { private ITaskService taskService; @Autowired private IProjectService projectService; + @SneakyThrows @GetMapping("/{fatherId}/subtask") public ResponseList getSubTaskList( @@ -61,7 +62,7 @@ public class TaskController { @PathVariable("projectId") Integer projectId, @RequestBody Task task ) { - if(!projectService.checkOpenStatus(projectId)) + if (!projectService.checkOpenStatus(projectId)) throw new BadRequestException(IProjectService.PROJECT_UNOPENED); task.setTaskProjectId(projectId); taskService.insertTask(token, task); @@ -76,7 +77,7 @@ public class TaskController { @PathVariable("taskId") Long taskId, @RequestBody Task task ) { - if(!projectService.checkOpenStatus(projectId)) + if (!projectService.checkOpenStatus(projectId)) throw new BadRequestException(IProjectService.PROJECT_UNOPENED); task.setTaskProjectId(projectId); task.setTaskId(taskId); @@ -91,22 +92,32 @@ public class TaskController { @PathVariable("projectId") Integer projectId, @PathVariable("taskId") Long taskId ) { - if(!projectService.checkOpenStatus(projectId)) + if (!projectService.checkOpenStatus(projectId)) throw new BadRequestException(IProjectService.PROJECT_UNOPENED); taskService.deleteTaskAndSubTask(token, projectId, taskId); return ResponseMap.ofSuccess(); } @SneakyThrows - @GetMapping("/stats") + @GetMapping("/stats/trend") public ResponseMap getTaskTrend( @RequestHeader(TokenUtils.HEADER_TOKEN) String token, @PathVariable Integer projectId ) { - if(!projectService.checkOpenStatus(projectId)) { + if (!projectService.checkOpenStatus(projectId)) { throw new BadRequestException(IProjectService.PROJECT_UNOPENED); } return ResponseMap.ofSuccess("查询成功", taskService.getProjectTaskTrend(token, projectId)); } + //TODO: + @GetMapping({"/stats", "/stats/{staffId}"}) + public ResponseMap getProjectStatistics( + @RequestHeader(TokenUtils.HEADER_TOKEN) String token, + @PathVariable Integer projectId, + @PathVariable(required = false) Integer staffId + ) { + return ResponseMap.ofSuccess(); + } + } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/TaskDTO.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/TaskDTO.java index a3b09cf..e3fe5b4 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/TaskDTO.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/dto/TaskDTO.java @@ -27,7 +27,6 @@ public class TaskDTO { private LocalDateTime taskClosedTime; private Integer taskPriority; private String taskDescription; - @TableField(typeHandler = JacksonTypeHandler.class) private Map attachedInfo; - private Boolean hasChildren; + private Integer childrenCount; } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IStaffService.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IStaffService.java index 56525ff..965eb06 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IStaffService.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/IStaffService.java @@ -17,7 +17,7 @@ public interface IStaffService extends IService { String STAFF_DOES_NOT_EXIST = "用户不存在"; - Map login(String username, String password) throws BadRequestException, TokenException; + Map login(String requestIpAddress, String username, String password) throws BadRequestException, TokenException, ForbiddenException; Boolean logout(String token) throws TokenException; diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/StaffServiceImpl.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/StaffServiceImpl.java index ae5ee78..90b98b1 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/StaffServiceImpl.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/StaffServiceImpl.java @@ -7,6 +7,7 @@ import cn.edu.hfut.rmdjzz.projectmanagement.mapper.StaffMapper; import cn.edu.hfut.rmdjzz.projectmanagement.service.IStaffService; import cn.edu.hfut.rmdjzz.projectmanagement.utils.BeanUtils; import cn.edu.hfut.rmdjzz.projectmanagement.utils.MapBuilder; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.TimeUtils; import cn.edu.hfut.rmdjzz.projectmanagement.utils.TokenUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -35,26 +36,44 @@ import java.util.concurrent.TimeUnit; @Service public class StaffServiceImpl extends ServiceImpl implements IStaffService { private static final Long tokenDuration = 5 * 60 * 60L; + private static final int LOGIN_TRY_COUNT_TIMEOUT = 15; //minutes + private static final int LOGIN_MAX_TRY_COUNT = 5; @Autowired private RedisTemplate redisTemplate; - //TODO: ban掉多次登录失败的IP + @SuppressWarnings("ConstantConditions") @Override - public Map login(String staffUsername, String password) throws BadRequestException { + public Map login(String requestIpAddress, String staffUsername, String password) throws BadRequestException, ForbiddenException { + if (Boolean.FALSE.equals(redisTemplate.hasKey(requestIpAddress))) { + redisTemplate.opsForValue().set(requestIpAddress, 0, LOGIN_TRY_COUNT_TIMEOUT, TimeUnit.MINUTES); + } + int loginCount = (int) redisTemplate.opsForValue().get(requestIpAddress); + + if (loginCount >= LOGIN_MAX_TRY_COUNT) { + throw new ForbiddenException(String.format("还需要等待%s才能登录" + , TimeUtils.secondsFormat(redisTemplate.getExpire(requestIpAddress)))); + } + if (staffUsername == null || staffUsername.strip().length() == 0) - throw new BadRequestException("用户名为空"); - else if (!staffUsername.equals(staffUsername.replaceAll("[^a-zA-Z0-9]", ""))) - throw new BadRequestException("用户名格式错误"); - else if (password == null || password.trim().length() != 32) - throw new BadRequestException("密码格式错误"); + //throw new BadRequestException("用户名为空"); + throwLoginException(requestIpAddress, loginCount); + if (!staffUsername.equals(staffUsername.replaceAll("[^a-zA-Z0-9]", ""))) + //throw new BadRequestException("用户名格式错误"); + throwLoginException(requestIpAddress, loginCount); + if (password == null || password.trim().length() != 32) + //throw new BadRequestException("密码格式错误"); + throwLoginException(requestIpAddress, loginCount); Staff staff = getOne(Wrappers.lambdaQuery().eq(Staff::getStaffUsername, staffUsername)); if (staff == null) - throw new BadRequestException(STAFF_DOES_NOT_EXIST); + //throw new BadRequestException(STAFF_DOES_NOT_EXIST); + throwLoginException(requestIpAddress, loginCount); + password = DigestUtils.md5DigestAsHex((password + staff.getStaffSalt()).getBytes()); - if (!staff.getStaffPassword().equals(password)) - throw new BadRequestException("密码错误"); + if (!staff.getStaffPassword().equals(password)) { + throwLoginException(requestIpAddress, loginCount); + } String token = TokenUtils.getToken(staff.getStaffUsername(), staff.getStaffId(), staff.getStaffGlobalLevel(), tokenDuration); redisTemplate.opsForValue().set( Objects.requireNonNull(TokenUtils.getStaffId(token)), @@ -67,6 +86,11 @@ public class StaffServiceImpl extends ServiceImpl implements .build(); } + private void throwLoginException(String requestIpAddress, int loginCount) throws BadRequestException { + redisTemplate.opsForValue().set(requestIpAddress, ++loginCount, LOGIN_TRY_COUNT_TIMEOUT, TimeUnit.MINUTES); + throw new BadRequestException(String.format("登录失败,%d分钟内还有%d次登录机会", LOGIN_TRY_COUNT_TIMEOUT, LOGIN_MAX_TRY_COUNT - loginCount)); + } + @Override public Boolean logout(String token) { Integer staffId = TokenUtils.getStaffId(token); diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java index 5cb5459..13be26c 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java @@ -286,10 +286,14 @@ public class TaskServiceImpl extends ServiceImpl implements IT task.setTaskStatus(Task.STATUS_WAITING); task.setChildrenCount(0); task.setTaskClosedTime(null); - if (baseMapper.insert(task) == 0) { + if (baseMapper.insert(task) == 0 || + baseMapper.update(null, + Wrappers.lambdaUpdate() + .eq(Task::getTaskId, task.getTaskFatherId()) + .setSql("children_count = children_count + 1")) != 1 + ) { throw new BadRequestException(BadRequestException.OPERATE_FAILED); } - baseMapper.update(null, Wrappers.lambdaUpdate().setSql("children_count = children_count + 1")); } catch (Exception e) { log.error(e.getMessage(), e); throw new BadRequestException(BadRequestException.OPERATE_FAILED); diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/BeanUtils.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/BeanUtils.java index 28a2312..066f08f 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/BeanUtils.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/BeanUtils.java @@ -84,6 +84,9 @@ public class BeanUtils { return false; } + /** + * 检查object是否在set中 + */ public static boolean checkInSet(Object object, Object... set) { return Arrays.asList(set).contains(object); } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TimeUtils.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TimeUtils.java index 2a19b0e..8fb31f8 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TimeUtils.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/TimeUtils.java @@ -63,4 +63,22 @@ public class TimeUtils { } return true; } + + /** + * 最大格式化单位为分钟,有需求再改 + */ + public static String secondsFormat(long seconds) { + long minutes = 0; + if ((minutes = seconds / 60) > 0) { + seconds %= 60; + } + StringBuilder sb = new StringBuilder(); + if (minutes > 0) { + sb.append(minutes).append("分"); + } + if (seconds > 0) { + sb.append(seconds).append("秒"); + } + return sb.toString(); + } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java new file mode 100644 index 0000000..da75e61 --- /dev/null +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/HttpUtils.java @@ -0,0 +1,48 @@ +package cn.edu.hfut.rmdjzz.projectmanagement.utils.http; + +import javax.servlet.http.HttpServletRequest; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * @author 佘语殊 + * @since 2022/7/12 10:57 + */ +public class HttpUtils { + public static String getRequestIpAddress(HttpServletRequest request) { + String ipAddress = null; + try { + ipAddress = request.getHeader("x-forwarded-for"); + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + if (ipAddress.equals("127.0.0.1")) { + // 根据网卡取本机配置的IP + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + ipAddress = inet.getHostAddress(); + } + } + // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 + if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length() + // = 15 + if (ipAddress.indexOf(",") > 0) { + ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); + } + } + } catch (Exception e) { + ipAddress = ""; + } + // ipAddress = this.getRequest().getRemoteAddr(); + return ipAddress; + } +} diff --git a/src/main/resources/mapper/TaskMapper.xml b/src/main/resources/mapper/TaskMapper.xml index 092d166..100ac45 100644 --- a/src/main/resources/mapper/TaskMapper.xml +++ b/src/main/resources/mapper/TaskMapper.xml @@ -11,7 +11,7 @@ task_name, task_project_id, task_holder_id, - s.staff_fullname AS task_holder_name, + s.staff_fullname AS task_holder_name, task_status, task_type, t.task_father_id, @@ -22,11 +22,9 @@ task_priority, task_description, attached_info, - judge.task_father_id IS NOT NULL AS has_children + children_count FROM task AS t JOIN (SELECT staff_id, staff_fullname FROM staff) AS s ON t.task_holder_id = s.staff_id - LEFT JOIN (SELECT DISTINCT task_father_id FROM task WHERE is_deleted = 0) AS judge - ON t.task_id = judge.task_father_id WHERE is_deleted = 0 AND task_project_id = #{projectId} AND t.task_father_id = #{fatherId} diff --git a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java index 71cf4b7..7b3db89 100644 --- a/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java +++ b/src/test/java/cn/edu/hfut/rmdjzz/projectmanagement/RedisTests.java @@ -18,7 +18,7 @@ public class RedisTests { @Test void test() { - redisTemplate.opsForList().rightPush(123456, 89); + System.out.println(redisTemplate.opsForValue().get("l1")); } @Test