├── .gitignore
├── README.md
├── images
└── swagger.png
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── yisu
│ │ ├── ApiApplication.java
│ │ ├── common
│ │ ├── constant
│ │ │ └── FwCommonConstants.java
│ │ ├── exception
│ │ │ ├── ControllerExceptionHandler.java
│ │ │ └── ValidateException.java
│ │ ├── result
│ │ │ └── FwResult.java
│ │ └── validate
│ │ │ ├── aop
│ │ │ └── FwValidate.java
│ │ │ └── aspect
│ │ │ └── FwValidateAsprct.java
│ │ ├── config
│ │ └── swagger2
│ │ │ └── SwaggerConfig.java
│ │ └── restful
│ │ ├── controller
│ │ └── UserController.java
│ │ ├── data
│ │ └── DataMock.java
│ │ ├── entity
│ │ └── User.java
│ │ └── service
│ │ ├── UserService.java
│ │ └── impl
│ │ └── UserServiceImpl.java
└── resources
│ ├── application.yml
│ └── logback-spring.xml
└── test
└── java
└── com
└── yisu
└── mock
└── UserControllerTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | /.classpath
2 | /.factorypath
3 | /.project
4 | /.settings/
5 | /target/
6 | /log/
7 | /.idea/
8 | .idea/*
9 | *.iml
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 项目名restfu-api-demo
2 |
3 | #### 基于 Spring Boot 2.1.6.RELEASE
4 |
5 | ## 介绍
6 |
7 |
8 | >RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务使能接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源
9 |
10 | # 注意事项
11 | ### 1.maven 依赖
12 | ```maven
13 |
14 |
15 | org.springframework.cloud
16 | spring-cloud-dependencies
17 | ${spring-cloud.version}
18 | pom
19 | import
20 |
21 |
22 |
23 | org.apache.commons
24 | commons-lang3
25 | ${commons-lang3.version}
26 |
27 |
28 | org.projectlombok
29 | lombok
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-test
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-aop
42 |
43 |
44 | org.springframework.data
45 | spring-data-commons
46 | ${data-commons.version}
47 |
48 |
49 |
50 | commons-io
51 | commons-io
52 | ${commons-io.version}
53 |
54 |
55 | commons-lang
56 | commons-lang
57 | ${commons-lang.version}
58 |
59 |
60 | commons-collections
61 | commons-collections
62 | ${commons-collections.version}
63 |
64 |
65 | commons-beanutils
66 | commons-beanutils
67 | ${commons-beanutils.version}
68 |
69 |
70 |
71 |
72 | io.springfox
73 | springfox-swagger2
74 | ${swagger.version}
75 |
76 |
77 | io.springfox
78 | springfox-swagger-ui
79 | ${swagger.version}
80 |
81 |
82 |
83 | cn.hutool
84 | hutool-all
85 | ${hutool.version}
86 |
87 | ```
88 |
89 | ### 2.分组校验
90 | 实体类定义如下:
91 | ```java
92 | public class User implements Serializable {
93 | private static final long serialVersionUID = 1838417777538323571L;
94 |
95 | //主键
96 | @NotNull(message = "主键不能为空",groups =Update.class)
97 | private Long id;
98 | //用户名
99 | @NotNull(message = "用户名不能为空")
100 | private String userName;
101 | //密码
102 | @NotNull(message = "密码不能为空")
103 | private String password;
104 | //性别
105 | @NotNull(message = "性别不能为空")
106 | private String sex;
107 |
108 |
109 | public @interface Update {
110 | }
111 | }
112 | ```
113 | 控制层代码,BindingResult bindingResult 必须写在方法的接收参数上,否则校验失败,校验逻辑统一走@FwValidate切面处理
114 | ```java
115 | /**
116 | * 添加用户
117 | * @Author xuyisu
118 | * @Date 2019/10/25
119 | * @Param [user]
120 | * @Return com.yisu.common.result.FwResult
121 | */
122 | @PostMapping
123 | @ApiOperation(value = "创建用户")
124 | @FwValidate
125 | public FwResult createUser(@Valid @RequestBody User user,BindingResult bindingResult) {
126 | if(bindingResult.hasErrors())
127 | {
128 | return FwResult.failed();
129 | }
130 | FwResult userInfo=userService.createUser(user);
131 | return userInfo;
132 | }
133 |
134 | /**
135 | * 更新用户
136 | * @Author xuyisu
137 | * @Date 2019/10/25
138 | * @Param [user]
139 | * @Return com.yisu.common.result.FwResult
140 | */
141 | @PutMapping("/updateUser")
142 | @ApiOperation(value = "更新用户")
143 | @FwValidate
144 | public FwResult updateUser(@Validated(User.Update.class) @RequestBody User user,BindingResult bindingResult) {
145 | if(bindingResult.hasErrors())
146 | {
147 | return FwResult.failed();
148 | }
149 | FwResult userInfo=userService.updateUser(user);
150 | return userInfo;
151 | }
152 | ```
153 | ### 3.swagger 配置
154 | ```java
155 | /**
156 | * api页面 /swagger-ui.html
157 | * @author xuyisu
158 | * @date 2019-10-15
159 | */
160 |
161 | @Configuration
162 | @EnableSwagger2
163 | public class SwaggerConfig {
164 |
165 |
166 | @Value("${swagger.enabled}")
167 | private Boolean enabled;
168 |
169 | @Bean
170 | public Docket createRestApi() {
171 | return new Docket(DocumentationType.SWAGGER_2)
172 | .enable(enabled)
173 | .apiInfo(apiInfo())
174 | .select()
175 | .paths(Predicates.not(PathSelectors.regex("/error.*")))
176 | .build();
177 | }
178 |
179 | private ApiInfo apiInfo() {
180 | return new ApiInfoBuilder()
181 | .title("接口文档")
182 | .version("1.0")
183 | .build();
184 | }
185 |
186 | }
187 | ```
188 | 浏览器输入`http://localhost:8766/swagger-ui.html# `
189 | 
190 |
191 | ### 4.单元测试
192 | ```java
193 | /**
194 | * @ClassName UserControllerTest
195 | * @Author xuyisu
196 | * @Description 模拟http测试
197 | * @Date 2019/10/25
198 | */
199 | @RunWith(SpringRunner.class)
200 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
201 | public class UserControllerTest {
202 |
203 | @Autowired
204 | private WebApplicationContext wac;
205 |
206 | private MockMvc mockMvc;
207 |
208 | @Before
209 | public void setup() {
210 | mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
211 | }
212 |
213 | @Test
214 | public void whenGetUserInfoSuccess() throws Exception {
215 | String result = mockMvc.perform(get("/user/1")
216 | .contentType(MediaType.APPLICATION_JSON_UTF8))
217 | .andExpect(status().isOk())
218 | .andExpect(jsonPath("$.code").value(FwCommonConstants.SUCCESS))
219 | .andReturn().getResponse().getContentAsString();
220 |
221 | System.out.println(result);
222 | }
223 | //.......
224 | //具体请看代码`com.yisu.mock.UserControllerTest`
225 |
226 | ```
227 |
228 | # 亲,点个star再走呗
229 |
230 |
231 |
232 |
--------------------------------------------------------------------------------
/images/swagger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuyisu/restful-api-demo/70223d265349b0c3586359d1f6227867dccff93b/images/swagger.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.yisu
8 | restful-api-demo
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 3.4
13 | Greenwich.SR2
14 | 2.9.2
15 | 4.6.7
16 | 2.1.10.RELEASE
17 | 2.7
18 | 2.6
19 | 3.2.2
20 | 1.9.4
21 |
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-parent
26 | 2.1.6.RELEASE
27 |
28 |
29 |
30 |
31 |
32 | org.springframework.cloud
33 | spring-cloud-dependencies
34 | ${spring-cloud.version}
35 | pom
36 | import
37 |
38 |
39 |
40 | org.apache.commons
41 | commons-lang3
42 | ${commons-lang3.version}
43 |
44 |
45 | org.projectlombok
46 | lombok
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-starter-web
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-starter-test
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-starter-aop
59 |
60 |
61 | org.springframework.data
62 | spring-data-commons
63 | ${data-commons.version}
64 |
65 |
66 |
67 | commons-io
68 | commons-io
69 | ${commons-io.version}
70 |
71 |
72 | commons-lang
73 | commons-lang
74 | ${commons-lang.version}
75 |
76 |
77 | commons-collections
78 | commons-collections
79 | ${commons-collections.version}
80 |
81 |
82 | commons-beanutils
83 | commons-beanutils
84 | ${commons-beanutils.version}
85 |
86 |
87 |
88 |
89 | io.springfox
90 | springfox-swagger2
91 | ${swagger.version}
92 |
93 |
94 | io.springfox
95 | springfox-swagger-ui
96 | ${swagger.version}
97 |
98 |
99 |
100 | cn.hutool
101 | hutool-all
102 | ${hutool.version}
103 |
104 |
105 |
106 |
107 |
108 |
109 | org.springframework.boot
110 | spring-boot-maven-plugin
111 |
112 |
113 |
114 | org.apache.maven.plugins
115 | maven-compiler-plugin
116 | 2.3.2
117 |
118 | 1.8
119 | 1.8
120 | UTF-8
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | public
129 | aliyun nexus
130 | http://maven.aliyun.com/nexus/content/groups/public/
131 |
132 | true
133 |
134 |
135 |
136 |
137 |
138 | public
139 | aliyun nexus
140 | http://maven.aliyun.com/nexus/content/groups/public/
141 |
142 | true
143 |
144 |
145 | false
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/src/main/java/com/yisu/ApiApplication.java:
--------------------------------------------------------------------------------
1 | package com.yisu;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * @author xuyisu
8 | * @date 2018/9/29
9 | */
10 | @SpringBootApplication
11 | public class ApiApplication {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(ApiApplication.class);
15 | }
16 |
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/com/yisu/common/constant/FwCommonConstants.java:
--------------------------------------------------------------------------------
1 | package com.yisu.common.constant;
2 |
3 | /**
4 | * @ClassName FwCommonConstants
5 | * @Author xuyisu
6 | * @Description 公共常量
7 | * @Date 2019/10/11
8 | */
9 | public class FwCommonConstants {
10 | //成功
11 | public static final int SUCCESS = 200;
12 |
13 | //失败
14 | public static final int FAIL = 500;
15 |
16 | /**
17 | * 默认开始页
18 | */
19 | public static final int PAGE_NO=1;
20 |
21 | /**
22 | * 默认页大小
23 | */
24 | public static final int PAGE_SIZE=20;
25 | /**
26 | * 默认用户账号
27 | */
28 | public static final String USER_NAME = "admin";
29 | /**
30 | * 树形节点的父节点
31 | * @Author xuyisu
32 | * @Date 2019/10/24
33 | * @Param
34 | * @Return
35 | */
36 | public static final String PARENT_CODE = "0";
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/yisu/common/exception/ControllerExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.yisu.common.exception;
2 |
3 | import com.yisu.common.result.FwResult;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.bind.MethodArgumentNotValidException;
6 | import org.springframework.web.bind.MissingServletRequestParameterException;
7 | import org.springframework.web.bind.annotation.ControllerAdvice;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.bind.annotation.ResponseBody;
10 | import org.springframework.web.bind.annotation.RestControllerAdvice;
11 |
12 | import javax.validation.ConstraintViolationException;
13 | import java.security.InvalidParameterException;
14 |
15 | /**
16 | * 验证异常处理
17 | * @Author xuyisu
18 | * @Date 2019/10/25
19 | * @Param
20 | * @Return
21 | */
22 | @RestControllerAdvice
23 | public class ControllerExceptionHandler {
24 |
25 | @ExceptionHandler({InvalidParameterException.class, IllegalArgumentException.class, MissingServletRequestParameterException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class})
26 | public FwResult paramException(Exception e) {
27 | if (e instanceof MethodArgumentNotValidException) {
28 | return FwResult.failed(((MethodArgumentNotValidException) e).getBindingResult().getAllErrors().get(0).getDefaultMessage());
29 | }
30 |
31 | if (e.getMessage() != null) {
32 | return FwResult.failed(e.getMessage());
33 | }
34 |
35 | return FwResult.failed();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/yisu/common/exception/ValidateException.java:
--------------------------------------------------------------------------------
1 | package com.yisu.common.exception;
2 |
3 | import com.yisu.common.result.FwResult;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 |
7 | import java.util.Map;
8 | import java.util.Set;
9 |
10 | /**
11 | * @ClassName ValidateException
12 | * @Author xuyisu
13 | * @Description 验证的异常捕捉
14 | * @Date 2019/10/25
15 | */
16 | @Data
17 | @AllArgsConstructor
18 | public class ValidateException extends RuntimeException {
19 |
20 | private static final long serialVersionUID = 7207451175263593487L;
21 |
22 | private Set