diff --git a/lab-22/pom.xml b/lab-22/pom.xml new file mode 100644 index 000000000..aa9ce8700 --- /dev/null +++ b/lab-22/pom.xml @@ -0,0 +1,15 @@ + + + + labs-parent + cn.iocoder.springboot.labs + 1.0-SNAPSHOT + + 4.0.0 + + lab-22 + + + diff --git a/lab-23/lab-springmvc-23-01/pom.xml b/lab-23/lab-springmvc-23-01/pom.xml new file mode 100644 index 000000000..0cba57362 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/pom.xml @@ -0,0 +1,31 @@ + + + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + 4.0.0 + + lab-springmvc-23-01 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + diff --git a/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/Application.java b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/Application.java new file mode 100644 index 000000000..212310ef2 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/Application.java @@ -0,0 +1,13 @@ +package cn.iocoder.springboot.lab21.springmvc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController.java b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController.java new file mode 100644 index 000000000..0a06b5469 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController.java @@ -0,0 +1,91 @@ +package cn.iocoder.springboot.lab21.springmvc.controller; + +import cn.iocoder.springboot.lab21.springmvc.dto.UserAddDTO; +import cn.iocoder.springboot.lab21.springmvc.dto.UserUpdateDTO; +import cn.iocoder.springboot.lab21.springmvc.vo.UserVO; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用户 Controller + */ +@RestController +@RequestMapping("/users") +public class UserController { + + /** + * 查询用户列表 + * + * @return 用户列表 + */ + @GetMapping("") + public List list() { + // 查询列表 + List result = new ArrayList<>(); + result.add(new UserVO().setId(1).setUsername("yudaoyuanma")); + result.add(new UserVO().setId(2).setUsername("woshiyutou")); + result.add(new UserVO().setId(3).setUsername("chifanshuijiao")); + // 返回列表 + return result; + } + + /** + * 获得指定用户编号的用户 + * + * @param id 用户编号 + * @return 用户 + */ + @GetMapping("/{id}") + public UserVO get(@PathVariable("id") Integer id) { + // 查询并返回用户 + return new UserVO().setId(id).setUsername("username:" + id); + } + + /** + * 添加用户 + * + * @param addDTO 添加用户信息 DTO + * @return 添加成功的用户编号 + */ + @PostMapping("") + public Integer add(UserAddDTO addDTO) { + // 插入用户记录,返回编号 + Integer returnId = 1; + // 返回用户编号 + return returnId; + } + + /** + * 更新指定用户编号的用户 + * + * @param id 用户编号 + * @param updateDTO 更新用户信息 DTO + * @return 是否修改成功 + */ + @PutMapping("/{id}") + public Boolean update(@PathVariable("id") Integer id, UserUpdateDTO updateDTO) { + // 将 id 设置到 updateDTO 中 + updateDTO.setId(id); + // 更新用户记录 + Boolean success = true; + // 返回更新是否成功 + return success; + } + + /** + * 删除指定用户编号的用户 + * + * @param id 用户编号 + * @return 是否删除成功 + */ + @DeleteMapping("/{id}") + public Boolean delete(@PathVariable("id") Integer id) { + // 删除用户记录 + Boolean success = false; + // 返回是否更新成功 + return success; + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController2.java b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController2.java new file mode 100644 index 000000000..ab2a89bc8 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController2.java @@ -0,0 +1,89 @@ +package cn.iocoder.springboot.lab21.springmvc.controller; + +import cn.iocoder.springboot.lab21.springmvc.dto.UserAddDTO; +import cn.iocoder.springboot.lab21.springmvc.dto.UserUpdateDTO; +import cn.iocoder.springboot.lab21.springmvc.vo.UserVO; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * 用户2 Controller + */ +@RestController +@RequestMapping("/users2") +public class UserController2 { + + /** + * 查询用户列表 + * + * @return 用户列表 + */ + @GetMapping("/list") // URL 修改成 /list + public List list() { + // 查询列表 + List result = new ArrayList<>(); + result.add(new UserVO().setId(1).setUsername("yudaoyuanma")); + result.add(new UserVO().setId(2).setUsername("woshiyutou")); + result.add(new UserVO().setId(3).setUsername("chifanshuijiao")); + // 返回列表 + return result; + } + + /** + * 获得指定用户编号的用户 + * + * @param id 用户编号 + * @return 用户 + */ + @GetMapping("/get") // URL 修改成 /get + public UserVO get(@RequestParam("id") Integer id) { + // 查询并返回用户 + return new UserVO().setId(id).setUsername(UUID.randomUUID().toString()); + } + + /** + * 添加用户 + * + * @param addDTO 添加用户信息 DTO + * @return 添加成功的用户编号 + */ + @PostMapping("add") // URL 修改成 /add + public Integer add(UserAddDTO addDTO) { + // 插入用户记录,返回编号 + Integer returnId = UUID.randomUUID().hashCode(); + // 返回用户编号 + return returnId; + } + + /** + * 更新指定用户编号的用户 + * + * @param updateDTO 更新用户信息 DTO + * @return 是否修改成功 + */ + @PostMapping("/update") // URL 修改成 /update ,RequestMethod 改成 POST + public Boolean update(UserUpdateDTO updateDTO) { + // 更新用户记录 + Boolean success = true; + // 返回更新是否成功 + return success; + } + + /** + * 删除指定用户编号的用户 + * + * @param id 用户编号 + * @return 是否删除成功 + */ + @DeleteMapping("/delete") // URL 修改成 /delete ,RequestMethod 改成 DELETE + public Boolean delete(@RequestParam("id") Integer id) { + // 删除用户记录 + Boolean success = false; + // 返回是否更新成功 + return success; + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/dto/UserAddDTO.java b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/dto/UserAddDTO.java new file mode 100644 index 000000000..c70ffd434 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/dto/UserAddDTO.java @@ -0,0 +1,35 @@ +package cn.iocoder.springboot.lab21.springmvc.dto; + +/** + * 用户添加 DTO + */ +public class UserAddDTO { + + /** + * 账号 + */ + private String username; + /** + * 密码 + */ + private String password; + + public String getUsername() { + return username; + } + + public UserAddDTO setUsername(String username) { + this.username = username; + return this; + } + + public String getPassword() { + return password; + } + + public UserAddDTO setPassword(String password) { + this.password = password; + return this; + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/dto/UserUpdateDTO.java b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/dto/UserUpdateDTO.java new file mode 100644 index 000000000..1995d4f41 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/dto/UserUpdateDTO.java @@ -0,0 +1,45 @@ +package cn.iocoder.springboot.lab21.springmvc.dto; + +public class UserUpdateDTO { + + /** + * 编号 + */ + private Integer id; + /** + * 账号 + */ + private String username; + /** + * 密码 + */ + private String password; + + public Integer getId() { + return id; + } + + public UserUpdateDTO setId(Integer id) { + this.id = id; + return this; + } + + public String getUsername() { + return username; + } + + public UserUpdateDTO setUsername(String username) { + this.username = username; + return this; + } + + public String getPassword() { + return password; + } + + public UserUpdateDTO setPassword(String password) { + this.password = password; + return this; + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/vo/UserVO.java b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/vo/UserVO.java new file mode 100644 index 000000000..c5033fcb5 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/main/java/cn/iocoder/springboot/lab21/springmvc/vo/UserVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.springboot.lab21.springmvc.vo; + +/** + * 用户 VO + */ +public class UserVO { + + /** + * 编号 + */ + private Integer id; + /** + * 账号 + */ + private String username; + + public Integer getId() { + return id; + } + + public UserVO setId(Integer id) { + this.id = id; + return this; + } + + public String getUsername() { + return username; + } + + public UserVO setUsername(String username) { + this.username = username; + return this; + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/test/java/cn/iocoder/springboot/lab21/springmvc/controller/UserControllerTest.java b/lab-23/lab-springmvc-23-01/src/test/java/cn/iocoder/springboot/lab21/springmvc/controller/UserControllerTest.java new file mode 100644 index 000000000..f45d52270 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/test/java/cn/iocoder/springboot/lab21/springmvc/controller/UserControllerTest.java @@ -0,0 +1,96 @@ +package cn.iocoder.springboot.lab21.springmvc.controller; + +import cn.iocoder.springboot.lab21.springmvc.Application; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class UserControllerTest { + + private MockMvc mvc; + + @Autowired + private UserController userController; + + @Before + public void setUp() { + mvc = MockMvcBuilders.standaloneSetup(userController).build(); +// mvc = MockMvcBuilders.standaloneSetup(new UserController()).build(); + } + + @Test + public void testList() throws Exception { + // 查询用户列表 + ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.get("/users")); + // 校验结果 + resultActions.andExpect(MockMvcResultMatchers.status().isOk()); // 响应状态码 200 + resultActions.andExpect(MockMvcResultMatchers.content().json("[\n" + + " {\n" + + " \"id\": 1,\n" + + " \"username\": \"yudaoyuanma\"\n" + + " },\n" + + " {\n" + + " \"id\": 2,\n" + + " \"username\": \"woshiyutou\"\n" + + " },\n" + + " {\n" + + " \"id\": 3,\n" + + " \"username\": \"chifanshuijiao\"\n" + + " }\n" + + "]")); // 响应结果 + } + + @Test + public void testGet() throws Exception { + // 获得指定用户编号的用户 + ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.get("/users/1")); + // 校验结果 + resultActions.andExpect(MockMvcResultMatchers.status().isOk()); // 响应状态码 200 + resultActions.andExpect(MockMvcResultMatchers.content().json("{\n" + + "\"id\": 1,\n" + + "\"username\": \"username:1\"\n" + + "}")); // 响应结果 + } + + @Test + public void testAdd() throws Exception { + // 获得指定用户编号的用户 + ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.post("/users") + .param("username", "yudaoyuanma") + .param("passowrd", "nicai")); + // 校验结果 + resultActions.andExpect(MockMvcResultMatchers.status().isOk()); // 响应状态码 200 + resultActions.andExpect(MockMvcResultMatchers.content().string("1")); // 响应结果 + } + + @Test + public void testUpdate() throws Exception { + // 获得指定用户编号的用户 + ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.put("/users/1") + .param("username", "yudaoyuanma") + .param("passowrd", "nicai")); + // 校验结果 + resultActions.andExpect(MockMvcResultMatchers.status().isOk()); // 响应状态码 200 + resultActions.andExpect(MockMvcResultMatchers.content().string("true")); // 响应结果 + } + + @Test + public void testDelete() throws Exception { + // 获得指定用户编号的用户 + ResultActions resultActions = mvc.perform(MockMvcRequestBuilders.delete("/users/1")); + // 校验结果 + resultActions.andExpect(MockMvcResultMatchers.status().isOk()); // 响应状态码 200 + resultActions.andExpect(MockMvcResultMatchers.content().string("false")); // 响应结果 + } + +} diff --git a/lab-23/lab-springmvc-23-01/src/test/java/cn/iocoder/springboot/lab21/springmvc/package-info.java b/lab-23/lab-springmvc-23-01/src/test/java/cn/iocoder/springboot/lab21/springmvc/package-info.java new file mode 100644 index 000000000..4a93fffd9 --- /dev/null +++ b/lab-23/lab-springmvc-23-01/src/test/java/cn/iocoder/springboot/lab21/springmvc/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.springboot.lab21.springmvc; diff --git a/lab-23/lab-springmvc-23-02/pom.xml b/lab-23/lab-springmvc-23-02/pom.xml new file mode 100644 index 000000000..f222c0f93 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/pom.xml @@ -0,0 +1,31 @@ + + + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + 4.0.0 + + lab-springmvc-23-02 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/Application.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/Application.java new file mode 100644 index 000000000..212310ef2 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/Application.java @@ -0,0 +1,13 @@ +package cn.iocoder.springboot.lab21.springmvc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/constants/ServiceExceptionEnum.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/constants/ServiceExceptionEnum.java new file mode 100644 index 000000000..4e7b036c4 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/constants/ServiceExceptionEnum.java @@ -0,0 +1,52 @@ +package cn.iocoder.springboot.lab21.springmvc.constants; + +/** + * 业务异常枚举 + */ +public enum ServiceExceptionEnum { + // ========== 系统级别 ========== + SUCCESS(0, "成功"), + SYS_ERROR(2001001000, "服务端发生异常"), + MISSING_REQUEST_PARAM_ERROR(2001001001, "参数缺失"), + + // ========== 用户模块 ========== + USER_NOT_FOUND(1001002000, "用户不存在"), + + // ========== 订单模块 ========== + + // ========== 商品模块 ========== + ; + + /** + * 错误码 + */ + private int code; + /** + * 错误提示 + */ + private String message; + + ServiceExceptionEnum(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public ServiceExceptionEnum setCode(int code) { + this.code = code; + return this; + } + + public String getMessage() { + return message; + } + + public ServiceExceptionEnum setMessage(String message) { + this.message = message; + return this; + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController.java new file mode 100644 index 000000000..4567a1e43 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller/UserController.java @@ -0,0 +1,67 @@ +package cn.iocoder.springboot.lab21.springmvc.controller; + +import cn.iocoder.springboot.lab21.springmvc.constants.ServiceExceptionEnum; +import cn.iocoder.springboot.lab21.springmvc.core.exception.ServiceException; +import cn.iocoder.springboot.lab21.springmvc.core.vo.CommonResult; +import cn.iocoder.springboot.lab21.springmvc.vo.UserVO; +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.UUID; + +/** + * 用户 Controller + */ +@RestController +@RequestMapping("/users") +public class UserController { + + /** + * 获得指定用户编号的用户 + * + * 提供不使用 CommonResult 包装 + * + * @param id 用户编号 + * @return 用户 + */ + @GetMapping("/get") + public UserVO get(@RequestParam("id") Integer id) { + // 查询并返回用户 + return new UserVO().setId(id).setUsername(UUID.randomUUID().toString()); + } + + /** + * 获得指定用户编号的用户 + * + * 提供使用 CommonResult 包装 + * + * @param id 用户编号 + * @return 用户 + */ + @GetMapping("/get2") + public CommonResult get2(@RequestParam("id") Integer id) { + // 查询用户 + UserVO user = new UserVO().setId(id).setUsername(UUID.randomUUID().toString()); + // 返回结果 + return CommonResult.success(user); + } + + /** + * 测试抛出 NullPointerException 异常 + */ + @GetMapping("/exception-01") + public UserVO exception01() { + throw new NullPointerException("没有粗面鱼丸"); + } + + /** + * 测试抛出 ServiceException 异常 + */ + @GetMapping("/exception-02") + public UserVO exception02() { + throw new ServiceException(ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR); + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller2/TestController.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller2/TestController.java new file mode 100644 index 000000000..766f0669c --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/controller2/TestController.java @@ -0,0 +1,29 @@ +package cn.iocoder.springboot.lab21.springmvc.controller2; + +import cn.iocoder.springboot.lab21.springmvc.vo.UserVO; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.UUID; + +/** + * 测试 Controller + * + * 这个类的目的,主要是为了测试 {@link cn.iocoder.springboot.lab21.springmvc.core.web.GlobalResponseBodyHandler} ,不拦截处理这个包 + */ +@RestController +@RequestMapping("/test") +public class TestController { + + /** + * 获得指定用户编号的用户 + * + * @return 用户 + */ + @GetMapping("/get") + public UserVO get() { + return new UserVO().setId(1).setUsername(UUID.randomUUID().toString()); + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/exception/ServiceException.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/exception/ServiceException.java new file mode 100644 index 000000000..226096b4c --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/exception/ServiceException.java @@ -0,0 +1,50 @@ +package cn.iocoder.springboot.lab21.springmvc.core.exception; + +import cn.iocoder.springboot.lab21.springmvc.constants.ServiceExceptionEnum; + +/** + * 服务异常 + * + * 参考 https://www.kancloud.cn/onebase/ob/484204 文章 + * + * 一共 10 位,分成四段 + * + * 第一段,1 位,类型 + * 1 - 业务级别异常 + * 2 - 系统级别异常 + * 第二段,3 位,系统类型 + * 001 - 用户系统 + * 002 - 商品系统 + * 003 - 订单系统 + * 004 - 支付系统 + * 005 - 优惠劵系统 + * ... - ... + * 第三段,3 位,模块 + * 不限制规则。 + * 一般建议,每个系统里面,可能有多个模块,可以再去做分段。以用户系统为例子: + * 001 - OAuth2 模块 + * 002 - User 模块 + * 003 - MobileCode 模块 + * 第四段,3 位,错误码 + * 不限制规则。 + * 一般建议,每个模块自增。 + */ +public final class ServiceException extends RuntimeException { + + /** + * 错误码 + */ + private final Integer code; + + public ServiceException(ServiceExceptionEnum serviceExceptionEnum) { + // 使用父类的 message 字段 + super(serviceExceptionEnum.getMessage()); + // 设置错误码 + this.code = serviceExceptionEnum.getCode(); + } + + public Integer getCode() { + return code; + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/package-info.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/package-info.java new file mode 100644 index 000000000..2df882fa5 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 提供核心封装 + */ +package cn.iocoder.springboot.lab21.springmvc.core; diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/vo/CommonResult.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/vo/CommonResult.java new file mode 100644 index 000000000..143a4b52b --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/vo/CommonResult.java @@ -0,0 +1,102 @@ +package cn.iocoder.springboot.lab21.springmvc.core.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.springframework.util.Assert; + +import java.io.Serializable; + +/** + * 通用返回结果 + * + * @param 结果泛型 + */ +public class CommonResult implements Serializable { + + public static Integer CODE_SUCCESS = 0; + + /** + * 错误码 + */ + private Integer code; + /** + * 错误提示 + */ + private String message; + /** + * 返回数据 + */ + private T data; + + /** + * 将传入的 result 对象,转换成另外一个泛型结果的对象 + * + * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。 + * + * @param result 传入的 result 对象 + * @param 返回的泛型 + * @return 新的 CommonResult 对象 + */ + public static CommonResult error(CommonResult result) { + return error(result.getCode(), result.getMessage()); + } + + public static CommonResult error(Integer code, String message) { + Assert.isTrue(!CODE_SUCCESS.equals(code), "code 必须是错误的!"); + CommonResult result = new CommonResult<>(); + result.code = code; + result.message = message; + return result; + } + + public static CommonResult success(T data) { + CommonResult result = new CommonResult<>(); + result.code = CODE_SUCCESS; + result.data = data; + result.message = ""; + return result; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + @JsonIgnore + public boolean isSuccess() { + return CODE_SUCCESS.equals(code); + } + + @JsonIgnore + public boolean isError() { + return !isSuccess(); + } + + @Override + public String toString() { + return "CommonResult{" + + "code=" + code + + ", message='" + message + '\'' + + ", data=" + data + + '}'; + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/web/GlobalExceptionHandler.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/web/GlobalExceptionHandler.java new file mode 100644 index 000000000..04a6644f8 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/web/GlobalExceptionHandler.java @@ -0,0 +1,58 @@ +package cn.iocoder.springboot.lab21.springmvc.core.web; + +import cn.iocoder.springboot.lab21.springmvc.constants.ServiceExceptionEnum; +import cn.iocoder.springboot.lab21.springmvc.core.exception.ServiceException; +import cn.iocoder.springboot.lab21.springmvc.core.vo.CommonResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; + +@ControllerAdvice +public class GlobalExceptionHandler { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * 处理 ServiceException 异常 + */ + @ResponseBody + @ExceptionHandler(value = ServiceException.class) + public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) { + logger.debug("[serviceExceptionHandler]", ex); + // 包装 CommonResult 结果 + return CommonResult.error(ex.getCode(), ex.getMessage()); + } + + /** + * 处理 MissingServletRequestParameterException 异常 + * + * SpringMVC 参数不正确 + */ + @ResponseBody + @ExceptionHandler(value = MissingServletRequestParameterException.class) + public CommonResult missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) { + logger.debug("[missingServletRequestParameterExceptionHandler]", ex); + // 包装 CommonResult 结果 + return CommonResult.error(ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), + ServiceExceptionEnum.MISSING_REQUEST_PARAM_ERROR.getMessage()); + } + + /** + * 处理其它 Exception 异常 + */ + @ResponseBody + @ExceptionHandler(value = Exception.class) + public CommonResult exceptionHandler(HttpServletRequest req, Exception e) { + // 记录异常日志 + logger.error("[exceptionHandler]", e); + // 返回 ERROR CommonResult + return CommonResult.error(ServiceExceptionEnum.SYS_ERROR.getCode(), + ServiceExceptionEnum.SYS_ERROR.getMessage()); + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/web/GlobalResponseBodyHandler.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/web/GlobalResponseBodyHandler.java new file mode 100644 index 000000000..c4ab3a538 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/core/web/GlobalResponseBodyHandler.java @@ -0,0 +1,31 @@ +package cn.iocoder.springboot.lab21.springmvc.core.web; + +import cn.iocoder.springboot.lab21.springmvc.core.vo.CommonResult; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +// 只拦截我们的 Controller 所在包,避免其它类似 swagger 提供的 API 被切面拦截 +@ControllerAdvice(basePackages = "cn.iocoder.springboot.lab21.springmvc.controller") +public class GlobalResponseBodyHandler implements ResponseBodyAdvice { + + @Override + public boolean supports(MethodParameter returnType, Class converterType) { + return true; + } + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, + ServerHttpRequest request, ServerHttpResponse response) { + // 如果已经是 CommonResult 类型,则直接返回 + if (body instanceof CommonResult) { + return body; + } + // 如果不是,则包装成 CommonResult 类型 + return CommonResult.success(body); + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/vo/UserVO.java b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/vo/UserVO.java new file mode 100644 index 000000000..c5033fcb5 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/main/java/cn/iocoder/springboot/lab21/springmvc/vo/UserVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.springboot.lab21.springmvc.vo; + +/** + * 用户 VO + */ +public class UserVO { + + /** + * 编号 + */ + private Integer id; + /** + * 账号 + */ + private String username; + + public Integer getId() { + return id; + } + + public UserVO setId(Integer id) { + this.id = id; + return this; + } + + public String getUsername() { + return username; + } + + public UserVO setUsername(String username) { + this.username = username; + return this; + } + +} diff --git a/lab-23/lab-springmvc-23-02/src/test/java/cn/iocoder/springboot/lab21/springmvc/package-info.java b/lab-23/lab-springmvc-23-02/src/test/java/cn/iocoder/springboot/lab21/springmvc/package-info.java new file mode 100644 index 000000000..4a93fffd9 --- /dev/null +++ b/lab-23/lab-springmvc-23-02/src/test/java/cn/iocoder/springboot/lab21/springmvc/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.springboot.lab21.springmvc; diff --git a/lab-23/pom.xml b/lab-23/pom.xml new file mode 100644 index 000000000..04dbe5aa1 --- /dev/null +++ b/lab-23/pom.xml @@ -0,0 +1,22 @@ + + + + labs-parent + cn.iocoder.springboot.labs + 1.0-SNAPSHOT + + 4.0.0 + + lab-23 + pom + + lab-23-01 + lab-springmvc-23 + lab-springmvc-23-01 + lab-springmvc-23-02 + + + + diff --git a/pom.xml b/pom.xml index 3e948a30d..ac6a6f057 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,8 @@ lab-19 lab-20 lab-21 + lab-22 + lab-23