微服务: 简单的用户名注册和登录
内容概要
在本篇中我们要完成一个目标:提供注册、登录的接口给前端或者客户端来使用。
涉及到的内容主要有下面几个:
1、SpringBoot 中常用的注解如何使用?
2、 如何对接口进行单元测试?
其他相关的微服务文章,可以点击 微服务项目系列文章 了解。
常用注解
控制器 Controller
是 Spring 中最基本的组件,主要是处理跟用户交互的,一般每个业务逻辑都会有一个 Controller
,提供 HTTP 请求接口,用户请求接口进行数据访问。
跟 Controller 相关的几个注解主要有 @Controller
,@RestController
,@RequestMapping
,@PathVariable
,@RequestParam
,@GetMapping
等。
@Controller
:标注 Controller
类,处理 HTTP 请求。
@RestController
:标注 Controller
类,Spring 4 新加注解,相当于 @Controller
+ @ResponseBody
,主要是为了使 HTTP 请求返回数据格式为 json
格式,正常情况下都是使用这个注解。
@RequestMapping
:配置 URL 映射,即请求的地址。
@PathVariable
,@RequestParam
,@QueryParam
,@PathParam
注解,可以参考 微服务: 学习几个容易混淆的URL注解 这篇文章。
@GetMapping
,@PostMapping
,@PutMapping
称之为组合注解,它们等价于 @RequestMapping
单独指定映射再指定请求方法。举个例子,如下:
1
| @RequestMapping(value = "/signup/name", method = RequestMethod.POST)
|
等价于下面的注解:
1
| @PostMapping(value = "/signup/name")
|
编写实体
不管是登录还是注册,都是每个用户进行的操作,我们先定义用户实体类 MSUser
,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import lombok.Data; import java.io.Serializable;
@Data public class MSUser implements Serializable { private String userID;
private String accountName;
private String accountPwd;
private String nickName;
private Integer age;
private Integer gender;
private String motto; }
|
大家可以看到,在实体类 MSUser
中,我们用到了注解 @Data
,该注解来源于 lombok
,需要自己在IDEA中安装该插件,安装方法请大家自行搜索解决。
注解 @Data
相当于给我们自动实现了 Get
、Setter
、toString
、 equals
和 hashCode
方法以及构造方法,不需要我们自己再去写这些代码。
HTTP 的请求响应结果,也可以被封装为实体类,如下 MSResponse
就是用来承载HTTP返回的响应。
1 2 3 4 5 6 7 8
| import lombok.Data;
@Data public class MSResponse<T> { private int code; private String msg; private T results; }
|
编写接口
一般来说,用户注册需要将用户的信息存下来,存到数据库中方便后续使用这份数据,这个行为称之为 数据持久化
,现在我们不做这个操作,只是纯粹的提供接口让用户可以注册、登录我们的系统,后续再来考虑和实现数据持久化。
这个阶段注册功能只提供 用户名+密码
的方式,该请求是个 POST
请求,主要核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @RestController @RequestMapping(value = "signup") public class MSSignupController {
@CrossOrigin(origins = {"*"}) @PostMapping(value = "/name") public MSResponse signup(@RequestParam(value = "username") String userName, @RequestParam(value = "userpwd") String userPwd) { MSResponse response = new MSResponse(); MSUser user = null; if (null == userName || null == userPwd || userName.length() <= 0 || userPwd.length() <= 0) { MSResponseEnum signupError = MSResponseEnum.SignupInvalidInfo; response.setMsg(signupError.getMsg()); response.setCode(signupError.getCode()); } else { response.setCode(MSResponseEnum.SUCCESS.getCode()); response.setMsg(MSResponseEnum.SUCCESS.getMsg()); user = MSUserUtil.createUser(userName, userPwd); }
response.setResults(user);
return response; } }
|
同理,登录功能也只提供 用户名+密码
的方式,该请求是个 GET
请求,主要核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| @RestController @RequestMapping(value = "signin") public class MSSigninController {
@CrossOrigin(origins = {"*", "http://localhost:8082"}) @RequestMapping(value = "/name", method = RequestMethod.GET) public MSResponse sigin(@RequestParam(value = "username") String userName, @RequestParam(value = "userpwd") String userPwd) { MSResponse response = new MSResponse(); MSUser user = null; if (null == userName || null == userPwd || userName.length() <= 0 || userPwd.length() <= 0) { MSResponseEnum responseEnum = MSResponseEnum.Login4SiginInvalidInfo; response.setCode(responseEnum.getCode()); response.setMsg(responseEnum.getMsg()); } else { user = MSUserUtil.createUser(userName, userPwd); MSResponseEnum rspEnum = MSResponseEnum.SUCCESS; response.setCode(rspEnum.getCode()); response.setMsg(rspEnum.getMsg()); }
response.setResults(user);
return response; } }
|
单元测试
在 IDEA 中新建 SpringBoot 工程后,默认就会创建一个测试目录。
即 test
目录下会有 SpringbootApplicationTests
类文件,其中 pom 文件中已经添加好了 spring-boot-starter-test
启动器。
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
|
springboot-test
包中已经包括了 junit
和 mockito
类库,不需要我们额外再去添加这些库。
借助于 MockMvc
我们可以对接口进行简单的单元测试了。主要的测试核心代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| @RunWith(SpringRunner.class) @AutoConfigureMockMvc @SpringBootTest public class SpringbootApplicationTests {
@Autowired private MockMvc mvc;
@Test public void signinTest() throws Exception { String url = "/signin/name?username=itman&userpwd=123";
MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get(url) .accept(MediaType.APPLICATION_JSON)) .andReturn();
MockHttpServletResponse response = mvcResult.getResponse(); int status = response.getStatus(); String contentAsString = response.getContentAsString();
System.err.println(status); System.err.println(contentAsString); }
@Test public void signupTest() throws Exception { String url = "/signup/name"; MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(url) .accept(MediaType.APPLICATION_JSON) .param("username", "itman") .param("userpwd", "123567")) .andReturn(); MockHttpServletResponse response = mvcResult.getResponse(); int status = response.getStatus(); String contentAsString = response.getContentAsString(); System.err.println(status); System.err.println(contentAsString); } }
|
在上面编写的测试代码中,解释一下几个用到的注解和类。
1、@RunWith(SpringRunner.class) ,SpringRunner
是 SpringJUnit4ClassRunner
的简写,用于提供测试时的 Spring 应用上下文信息。
2、MockMvc ,MockMvc
是测试 Spring MVC 应用程序的主要入口,为我们的测试提供了一个模拟的应用上下文的环境。
3、@Autowired,可以对类成员变量、方法及构造函数进行标注,完成自动装配。不需要手动创建该对象,这个跟 Spring 的 IOC 机制有关。
代码写好之后,就可以进行单元测试了,直接在 signinTest
或者 signupTest
右键运行即可,不需要启动整个工程。如下图所示:

运行之后,可以在输出的控制台中看到信息:

前端请求
在 跨域和OPTIONS这对欢喜冤家 和 减少跨域中的OPTIONS请求 这两篇文章中,已经跟大家分享过如何在前端页面中进行接口访问了,其中也重点讲解了如何在 SpringBoot 中解决跨域问题,这里不再赘述,感兴趣的朋友可以去看看这两篇文章。
文中的完整示例代码都在 Github 上面,需要的可以自行clone,感谢您的阅读。
临渊羡鱼不如按退而结网~
