diff --git a/README.md b/README.md index 0e3a167..fbd48fb 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ### 项目介绍 1. RESTful API -2. Maven集成Mybatis Geneator(逆向工程) +2. Maven集成Mybatis Generator(逆向工程) 3. Shiro + Java-JWT实现无状态鉴权机制(Token) 4. 密码加密(采用AES-128 + Base64的方式) 5. 集成Redis(Jedis) @@ -77,7 +77,7 @@ AccessToken认证,Redis的RefreshToken也可以用来判断用户是否在线 ### 使用说明 -#### Mybatis Geneator使用 +#### Mybatis Generator使用(推荐快速生成代码:[https://github.com/wang926454/SpringBootGenerator](https://github.com/wang926454/SpringBootGenerator)) ##### 先配置src\main\resources\generator\generatorConfig.xml文件(默认配置都在原来包的下一级reverse包下),在pom.xml这一级目录(即项目根目录下)的命令行窗口执行(前提是配置了mvn)(IDEA可以直接在Maven窗口Plugins中双击执行) ``` diff --git a/src/main/java/com/wang/controller/ExceptionController.java b/src/main/java/com/wang/config/ExceptionAdvice.java similarity index 77% rename from src/main/java/com/wang/controller/ExceptionController.java rename to src/main/java/com/wang/config/ExceptionAdvice.java index 8ca1c00..f44c23d 100644 --- a/src/main/java/com/wang/controller/ExceptionController.java +++ b/src/main/java/com/wang/config/ExceptionAdvice.java @@ -1,4 +1,4 @@ -package com.wang.controller; +package com.wang.config; import com.wang.exception.CustomException; import com.wang.exception.CustomUnauthorizedException; @@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.NoHandlerFoundException; + import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.HashMap; @@ -25,7 +27,7 @@ * @date 2018/8/30 14:02 */ @RestControllerAdvice -public class ExceptionController { +public class ExceptionAdvice { /** * 捕捉所有Shiro异常 * @param e @@ -34,7 +36,7 @@ public class ExceptionController { @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(ShiroException.class) public ResponseBean handle401(ShiroException e) { - return new ResponseBean(401, "无权访问(Unauthorized):" + e.getMessage(), null); + return new ResponseBean(HttpStatus.UNAUTHORIZED.value(), "无权访问(Unauthorized):" + e.getMessage(), null); } /** @@ -46,7 +48,7 @@ public ResponseBean handle401(ShiroException e) { @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(UnauthorizedException.class) public ResponseBean handle401(UnauthorizedException e) { - return new ResponseBean(401, "无权访问(Unauthorized):当前Subject没有此请求所需权限(" + e.getMessage() + ")", null); + return new ResponseBean(HttpStatus.UNAUTHORIZED.value(), "无权访问(Unauthorized):当前Subject没有此请求所需权限(" + e.getMessage() + ")", null); } /** @@ -58,7 +60,7 @@ public ResponseBean handle401(UnauthorizedException e) { @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(UnauthenticatedException.class) public ResponseBean handle401(UnauthenticatedException e) { - return new ResponseBean(401, "无权访问(Unauthorized):当前Subject是匿名Subject,请先登录(This subject is anonymous.)", null); + return new ResponseBean(HttpStatus.UNAUTHORIZED.value(), "无权访问(Unauthorized):当前Subject是匿名Subject,请先登录(This subject is anonymous.)", null); } /** @@ -68,7 +70,7 @@ public ResponseBean handle401(UnauthenticatedException e) { @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(CustomUnauthorizedException.class) public ResponseBean handle401(CustomUnauthorizedException e) { - return new ResponseBean(401, "无权访问(Unauthorized):" + e.getMessage(), null); + return new ResponseBean(HttpStatus.UNAUTHORIZED.value(), "无权访问(Unauthorized):" + e.getMessage(), null); } /** @@ -80,7 +82,7 @@ public ResponseBean handle401(CustomUnauthorizedException e) { public ResponseBean validException(BindException e) { List fieldErrors = e.getBindingResult().getFieldErrors(); Map result = this.getValidError(fieldErrors); - return new ResponseBean(400, result.get("errorMsg").toString(), result.get("errorList")); + return new ResponseBean(HttpStatus.BAD_REQUEST.value(), result.get("errorMsg").toString(), result.get("errorList")); } /** @@ -92,7 +94,7 @@ public ResponseBean validException(BindException e) { public ResponseBean validException(MethodArgumentNotValidException e) { List fieldErrors = e.getBindingResult().getFieldErrors(); Map result = this.getValidError(fieldErrors); - return new ResponseBean(400, result.get("errorMsg").toString(), result.get("errorList")); + return new ResponseBean(HttpStatus.BAD_REQUEST.value(), result.get("errorMsg").toString(), result.get("errorList")); } /** @@ -102,7 +104,17 @@ public ResponseBean validException(MethodArgumentNotValidException e) { @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(CustomException.class) public ResponseBean handle(CustomException e) { - return new ResponseBean(500, e.getMessage(), null); + return new ResponseBean(HttpStatus.BAD_REQUEST.value(), e.getMessage(), null); + } + + /** + * 捕捉404异常 + * @return + */ + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(NoHandlerFoundException.class) + public ResponseBean handle(NoHandlerFoundException e) { + return new ResponseBean(HttpStatus.NOT_FOUND.value(), e.getMessage(), null); } /** @@ -111,7 +123,7 @@ public ResponseBean handle(CustomException e) { * @param ex * @return */ - @ResponseStatus(HttpStatus.BAD_REQUEST) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Exception.class) public ResponseBean globalException(HttpServletRequest request, Throwable ex) { return new ResponseBean(this.getStatus(request).value(), ex.toString() + ": " + ex.getMessage(), null); diff --git a/src/main/java/com/wang/config/shiro/jwt/JwtFilter.java b/src/main/java/com/wang/config/shiro/jwt/JwtFilter.java index 85ccbcf..bc05a01 100644 --- a/src/main/java/com/wang/config/shiro/jwt/JwtFilter.java +++ b/src/main/java/com/wang/config/shiro/jwt/JwtFilter.java @@ -161,13 +161,13 @@ private boolean refreshToken(ServletRequest request, ServletResponse response) { */ private void response401(ServletRequest req, ServletResponse resp, String msg) { HttpServletResponse httpServletResponse = (HttpServletResponse) resp; - httpServletResponse.setStatus(401); + httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); httpServletResponse.setCharacterEncoding("UTF-8"); httpServletResponse.setContentType("application/json; charset=utf-8"); PrintWriter out = null; try { out = httpServletResponse.getWriter(); - String data = JsonConvertUtil.objectToJson(new ResponseBean(401, "无权访问(Unauthorized):" + msg, null)); + String data = JsonConvertUtil.objectToJson(new ResponseBean(HttpStatus.UNAUTHORIZED.value(), "无权访问(Unauthorized):" + msg, null)); out.append(data); } catch (IOException e) { logger.error(e.getMessage()); diff --git a/src/main/java/com/wang/controller/UserController.java b/src/main/java/com/wang/controller/UserController.java index 4328bbe..1aec6e9 100644 --- a/src/main/java/com/wang/controller/UserController.java +++ b/src/main/java/com/wang/controller/UserController.java @@ -23,11 +23,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; +import org.springframework.http.HttpStatus; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; -import java.text.SimpleDateFormat; import java.util.*; /** @@ -63,6 +63,10 @@ public UserController(IUserService userService) { @GetMapping @RequiresPermissions(logical = Logical.AND, value = {"user:view"}) public ResponseBean user(@Validated BaseDto baseDto){ + if(baseDto.getPage() == null || baseDto.getRows() == null){ + baseDto.setPage(1); + baseDto.setRows(10); + } PageHelper.startPage(baseDto.getPage(), baseDto.getRows()); List userDtos = userService.selectAll(); PageInfo selectPage = new PageInfo(userDtos); @@ -72,7 +76,7 @@ public ResponseBean user(@Validated BaseDto baseDto){ Map result = new HashMap(16); result.put("count", selectPage.getTotal()); result.put("data", selectPage.getList()); - return new ResponseBean(200, "查询成功(Query was successful)", result); + return new ResponseBean(HttpStatus.OK.value(), "查询成功(Query was successful)", result); } /** @@ -103,7 +107,7 @@ public ResponseBean online(){ if(userDtos == null || userDtos.size() <= 0){ throw new CustomException("查询失败(Query Failure)"); } - return new ResponseBean(200, "查询成功(Query was successful)", userDtos); + return new ResponseBean(HttpStatus.OK.value(), "查询成功(Query was successful)", userDtos); } /** @@ -137,7 +141,7 @@ public ResponseBean login(@Validated(UserLoginValidGroup.class) @RequestBody Use String token = JwtUtil.sign(userDto.getAccount(), currentTimeMillis); httpServletResponse.setHeader("Authorization", token); httpServletResponse.setHeader("Access-Control-Expose-Headers", "Authorization"); - return new ResponseBean(200, "登录成功(Login Success.)", null); + return new ResponseBean(HttpStatus.OK.value(), "登录成功(Login Success.)", null); } else { throw new CustomUnauthorizedException("帐号或密码错误(Account or Password Error.)"); } @@ -155,9 +159,9 @@ public ResponseBean article() { Subject subject = SecurityUtils.getSubject(); // 登录了返回true if (subject.isAuthenticated()) { - return new ResponseBean(200, "您已经登录了(You are already logged in)", null); + return new ResponseBean(HttpStatus.OK.value(), "您已经登录了(You are already logged in)", null); } else { - return new ResponseBean(200, "你是游客(You are guest)", null); + return new ResponseBean(HttpStatus.OK.value(), "你是游客(You are guest)", null); } } @@ -171,7 +175,7 @@ public ResponseBean article() { @GetMapping("/article2") @RequiresAuthentication public ResponseBean requireAuth() { - return new ResponseBean(200, "您已经登录了(You are already logged in)", null); + return new ResponseBean(HttpStatus.OK.value(), "您已经登录了(You are already logged in)", null); } /** @@ -188,7 +192,7 @@ public ResponseBean findById(@PathVariable("id") Integer id){ if(userDto == null){ throw new CustomException("查询失败(Query Failure)"); } - return new ResponseBean(200, "查询成功(Query was successful)", userDto); + return new ResponseBean(HttpStatus.OK.value(), "查询成功(Query was successful)", userDto); } /** @@ -219,7 +223,7 @@ public ResponseBean add(@Validated(UserEditValidGroup.class) @RequestBody UserDt if(count <= 0){ throw new CustomException("新增失败(Insert Failure)"); } - return new ResponseBean(200, "新增成功(Insert Success)", userDto); + return new ResponseBean(HttpStatus.OK.value(), "新增成功(Insert Success)", userDto); } /** @@ -254,7 +258,7 @@ public ResponseBean update(@Validated(UserEditValidGroup.class) @RequestBody Use if(count <= 0){ throw new CustomException("更新失败(Update Failure)"); } - return new ResponseBean(200, "更新成功(Update Success)", userDto); + return new ResponseBean(HttpStatus.OK.value(), "更新成功(Update Success)", userDto); } /** @@ -271,7 +275,7 @@ public ResponseBean delete(@PathVariable("id") Integer id){ if(count <= 0){ throw new CustomException("删除失败,ID不存在(Deletion Failed. ID does not exist.)"); } - return new ResponseBean(200, "删除成功(Delete Success)", null); + return new ResponseBean(HttpStatus.OK.value(), "删除成功(Delete Success)", null); } /** @@ -287,7 +291,7 @@ public ResponseBean deleteOnline(@PathVariable("id") Integer id){ UserDto userDto = userService.selectByPrimaryKey(id); if(JedisUtil.exists(Constant.PREFIX_SHIRO_REFRESH_TOKEN + userDto.getAccount())){ if(JedisUtil.delKey(Constant.PREFIX_SHIRO_REFRESH_TOKEN + userDto.getAccount()) > 0){ - return new ResponseBean(200, "剔除成功(Delete Success)", null); + return new ResponseBean(HttpStatus.OK.value(), "剔除成功(Delete Success)", null); } } throw new CustomException("剔除失败,Account不存在(Deletion Failed. Account does not exist.)"); diff --git a/src/main/java/com/wang/model/common/BaseDto.java b/src/main/java/com/wang/model/common/BaseDto.java index 5babfca..e1af10b 100644 --- a/src/main/java/com/wang/model/common/BaseDto.java +++ b/src/main/java/com/wang/model/common/BaseDto.java @@ -17,13 +17,11 @@ public class BaseDto implements Serializable { /** 当前页数 */ @Transient - @NotNull(message = "当前页数不能为空") @Min(value = 1, message = "当前页数不能小于1") private Integer page; /** 每页条数 */ @Transient - @NotNull(message = "每页条数不能为空") @Min(value = 1, message = "每页条数不能小于1") @Max(value = 50, message = "每页条数不能大于50") private Integer rows; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 125a417..ea4f1e4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,7 +7,7 @@ spring: url: jdbc:mysql://127.0.0.1:3306/shirojwt?useSSL=false&useUnicode=true&characterEncoding=UTF-8 username: root password: root - # 使用druid数据源 + # 使用Druid数据源 type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver filters: stat @@ -23,19 +23,31 @@ spring: testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 + # 404交给异常处理器处理 + mvc: + throw-exception-if-no-handler-found: true + # 404交给异常处理器处理 + resources: + add-mappings: false mybatis: + # Mybatis配置Mapper路径 mapper-locations: classpath:mapper/*.xml + # Mybatis配置Model类对应 type-aliases-package: com.wang.model.entity pagehelper: params: count=countSql + # 指定分页插件使用哪种方言 helper-dialect: mysql + # 分页合理化参数 pageNum<=0时会查询第一页 pageNum>pages(超过总数时) 会查询最后一页 reasonable: 'true' support-methods-arguments: 'true' mapper: + # 通用Mapper的insertSelective和updateByPrimaryKeySelective中是否判断字符串类型!='' not-empty: true logging: - level.com.wang.mapper: debug \ No newline at end of file + # Debug打印SQL + level.com.wang.mapper: debug \ No newline at end of file