# helloworld **Repository Path**: HQSONG/helloworld ## Basic Information - **Project Name**: helloworld - **Description**: No description available - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-04-16 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## helloworld ### 扫码登录-客户端定时器轮训实现 #### controller接口 > 详细可参考源代码。cn.codersnet.helloworld.scanlogin.web.ScanLoginController ```java @RestController @RequestMapping("/scanlogin") public class ScanLoginController { private Log logger = LogFactory.getLog(this.getClass()); private static final String TOKEN_LOGINID_SUFFIX = "_loginID"; @Autowired private Cache cache; /** * 生成二维码,暂时返回token * @return */ @GetMapping("/generate") public String generateCrCode() { //生成token String token = UUID.randomUUID().toString(); //将token置于缓存中,可以设置默认有效期,可以直接使用redis缓存设置过期时间。这里简单通过map实现 cache.put(token, new ScanStatus(ScanStatus.CODE_GENERATE, "二维码已生成, 待扫描"), 60); //60s后过期 return token; } /** * 移动端扫码 * @return */ @GetMapping("/appScan") public ScanStatus appScan(String token) { ScanStatus status = new ScanStatus(ScanStatus.CODE_SCANED, "二维码已扫描, 待确认"); if(cache.existed(token)) { cache.put(token, status); } else { status.setStatusCode(ScanStatus.CODE_EXPIRED); status.setMessage("二维码已过期或不存在"); } return status; } /** * 移动端确认登录,如果存在token未过期,设置token和loginID关联关系 * @param token * @param loginID * @return */ @GetMapping("/appConfirm") public ScanStatus appConfirm(String token, String loginID) { ScanStatus status = new ScanStatus(ScanStatus.CODE_APP_CONFIRM, "移动端已确认"); if(cache.existed(token)) { cache.put(token, status); cache.put(token + TOKEN_LOGINID_SUFFIX, loginID); } else { status.setStatusCode(ScanStatus.CODE_EXPIRED); status.setMessage("二维码已过期或不存在"); } return status; } /** * 检查扫码状态 * @param token * @return */ @PostMapping("/check") public ScanStatus check(String token) { if(cache.existed(token)) { ScanStatus scanStatus = (ScanStatus)cache.get(token); if(ScanStatus.CODE_APP_CONFIRM == scanStatus.getStatusCode()) { //TODO 执行登录 String loginID = (String)cache.get(token + TOKEN_LOGINID_SUFFIX); logger.info(loginID + ", app扫描登录成功"); return new ScanStatus(ScanStatus.CODE_LOGIN_SUCCESS, "登录成功"); } else { return scanStatus; } } //二维码过期 cache.remove(token + TOKEN_LOGINID_SUFFIX); return new ScanStatus(ScanStatus.CODE_EXPIRED, "二维码已过期或不存在"); } } ``` #### 单元测试 > 详细可参考源代码。cn.codersnet.helloworld.ScanLoginTests ```java @RunWith(SpringRunner.class) @SpringBootTest(classes = HelloworldApplication.class) @AutoConfigureMockMvc public class ScanLoginTests { @Autowired private MockMvc mvc; private JacksonTester json; @Before public void setup() { ObjectMapper objectMapper = new ObjectMapper(); JacksonTester.initFields(this, objectMapper); } /** * 扫码登录测试测试方法 * @throws Exception */ @Test public void scanLoginSuccessTest() throws Exception { // 1. 获取token(二维码) String token = mvc.perform(get("/scanlogin/generate")).andReturn().getResponse().getContentAsString(); Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_GENERATE, "生成二维码失败"); // 2. 移动端扫码 mvc.perform(get("/scanlogin/appScan").param("token", token)); Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_SCANED, "扫码失败"); // 3. 移动端确认登录 mvc.perform(get("/scanlogin/appConfirm").param("token", token).param("loginID", "test01")); // 4. PC端登录成功 Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_LOGIN_SUCCESS, "登录失败"); } /** * 扫码登录超时测试方法,示例代码中超时时间为60s * @throws Exception */ @Test public void scanLoginTimeoutTest() throws Exception { // 1. 获取token(二维码) String token = mvc.perform(get("/scanlogin/generate")).andReturn().getResponse().getContentAsString(); Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_GENERATE, "生成二维码失败"); //2. 等待超时 Thread.sleep(60*1000); //3. PC端check验证 Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_EXPIRED, "超时校验失败"); //4. 移动端扫码验证 mvc.perform(get("/scanlogin/appScan").param("token", token)); Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_EXPIRED, "超时校验失败"); } private ScanStatus check(String token) throws Exception { String checkStr = mvc.perform(post("/scanlogin/check").param("token", token)).andReturn().getResponse() .getContentAsString(); return this.json.parseObject(checkStr); } } ```