二、
新建小程序注册模块,配置好注册页面。
regist.wxml
<view> <view class="login-icon"> <image class="login-img" src="../resource/images/dsp1.jpg"></image> </view> <view class="login-from"> <form bindsubmit='doRegist'> <!--账号--> <view class="inputView"> <image class="nameImage" src="../resource/images/username.png"></image> <label class="loginLabel">账号</label> <input name="username" class="inputText" placeholder="请输入账号"/> </view> <view class="line"></view> <!--密码--> <view class="inputView"> <image class="keyImage" src="../resource/images/password.png"></image> <label class="loginLabel">密码</label> <input name="password" class="inputText" password="true" placeholder="请输入密码"/> </view> <!--按钮--> <view> <button class="loginBtn" type="primary" form-type='submit'>注册</button> </view> <view> <button class="goLoginBtn" type="warn" bindtap="goLoginPage">返回登录</button> </view> </form> </view> </view>
regist.wxss
page {
background-color: whitesmoke;
}
.login-img {
width: 750rpx;
}
/*表单内容*/
.inputView {
background-color: white;
line-height: 45px;
}
/*输入框*/
.nameImage, .keyImage {
margin-left: 22px;
width: 20px;
height: 20px;
}
.loginLabel {
margin: 15px 15px 15px 10px;
color: gray;
font-size: 15px;
}
.inputText {
float: right;
text-align: right;
margin-right: 22px;
margin-top: 11px;
font-size: 15px;
}
.line {
width: 100%;
height: 1px;
background-color: gainsboro;
margin-top: 1px;
}
/*按钮*/
.loginBtn {
width: 80%;
margin-top: 35px;
}
.goLoginBtn {
width: 80%;
margin-top: 15px;
}
三、开发注册用户的接口
新建两个工具类
package com.imooc.utils; /** * @Description: 自定义响应数据结构 * 这个类是提供给门户,ios,安卓,微信商城用的 * 门户接受此类数据后需要使用本类的方法转换成对于的数据类型格式(类,或者list) * 其他自行处理 * 200:表示成功 * 500:表示错误,错误信息在msg字段中 * 501:bean验证错误,不管多少个错误都以map形式返回 * 502:拦截器拦截到用户token出错 * 555:异常抛出信息 */ public class IMoocJSONResult { // 响应业务状态 private Integer status; // 响应消息 private String msg; // 响应中的数据 private Object data; private String ok; // 不使用 public static IMoocJSONResult build(Integer status, String msg, Object data) { return new IMoocJSONResult(status, msg, data); } public static IMoocJSONResult ok(Object data) { return new IMoocJSONResult(data); } public static IMoocJSONResult ok() { return new IMoocJSONResult(null); } public static IMoocJSONResult errorMsg(String msg) { return new IMoocJSONResult(500, msg, null); } public static IMoocJSONResult errorMap(Object data) { return new IMoocJSONResult(501, "error", data); } public static IMoocJSONResult errorTokenMsg(String msg) { return new IMoocJSONResult(502, msg, null); } public static IMoocJSONResult errorException(String msg) { return new IMoocJSONResult(555, msg, null); } public IMoocJSONResult() { } public IMoocJSONResult(Integer status, String msg, Object data) { this.status = status; this.msg = msg; this.data = data; } public IMoocJSONResult(Object data) { this.status = 200; this.msg = "OK"; this.data = data; } public Boolean isOK() { return this.status == 200; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getOk() { return ok; } public void setOk(String ok) { this.ok = ok; } }
package com.imooc.utils; import java.security.MessageDigest; import org.apache.commons.codec.binary.Base64; public class MD5Utils { /** * @Description: 对字符串进行md5加密 */ public static String getMD5Str(String strValue) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); String newstr = Base64.encodeBase64String(md5.digest(strValue.getBytes())); return newstr; } public static void main(String[] args) { try { String md5 = getMD5Str("imooc"); System.out.println(md5); } catch (Exception e) { e.printStackTrace(); } } }
四、开发注册用户的接口
在com.imooc.controller包中新建RegistLoginController类,然后新建相应的Service类,主要是检查用户是否存在以及新增用户。
UserService.class
package com.imooc.service; import com.imooc.pojo.Users; public interface UserService { /** * 判断用户名是否存在 * @param username * @return */ public boolean queryUsernameIsExist(String username); /** * 保存用户(用户注册) * @param user */ public void saveUser(Users user); }
UserServiceImpl.class
package com.imooc.service; import org.n3r.idworker.Sid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.imooc.mapper.UsersMapper; import com.imooc.pojo.Users; public class UserServiceImpl implements UserService { @Autowired private UsersMapper userMapper; //导入工具包,使用户生成的id是唯一的id @Autowired private Sid sid; @Transactional(propagation = Propagation.SUPPORTS) @Override public boolean queryUsernameIsExist(String username) { // TODO Auto-generated method stub Users user = new Users(); user.setUsername(username); Users result = userMapper.selectOne(user); return result == null ? false : true; } @Transactional(propagation = Propagation.REQUIRED) @Override public void saveUser(Users user) { // TODO Auto-generated method stub String userId = sid.nextShort(); user.setId(userId); userMapper.insert(user); } }
然后在RegistLoginController类中注入Service用于调用方法。
package com.imooc.controller; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.imooc.pojo.Users; import com.imooc.service.UserService; import com.imooc.utils.IMoocJSONResult; import com.imooc.utils.MD5Utils; @RestController public class RegistLoginController { @Autowired private UserService userService; @PostMapping("/regist") public IMoocJSONResult regist(@RequestBody Users user) throws Exception { //1、判断用户名和密码必须不为空 if(StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) { return IMoocJSONResult.errorMsg("用户名和密码不能为空"); } //2、判断用户名是否存在 boolean usernameIsExist = userService.queryUsernameIsExist(user.getUsername()); //3、保存用户,注册信息 if(!usernameIsExist) { user.setNickname(user.getUsername()); user.setPassword(MD5Utils.getMD5Str(user.getPassword())); user.setFansCounts(0); user.setReceiveLikeCounts(0); user.setFollowCounts(0); userService.saveUser(user); }else { return IMoocJSONResult.errorMsg("用户名已经存在,请换一个试试"); } return IMoocJSONResult.ok(); } }
此时,关于注册的类开发完了,接下来使用swagger2构建restful接口测试,关于swagger2的好处有以下几点:
接下来,在项目里导入swagger2,在common模块中的pom文件上注入以下配置
在api模块的com.imooc包中新建Swagger2类
package com.imooc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class Swagger2 { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() .apis(RequestHandlerSelectors.basePackage("com.imooc.controller")) .paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { // TODO Auto-generated method stub return new ApiInfoBuilder() // 设置页面标题 .title("使用swagger2构建短视频后端api接口文档") // 设置联系人 .contact(new Contact("imooc-zhaoBe", "http://www.imooc.com", "imooc@163.com")) // 描述 .description("欢迎访问短视频接口文档,这里是描述信息") // 定义版本号 .version("1.0").build(); } }
接着 ,在各个类中分别配置导入swagger2
首先是RegistLoginController类的类名前和对应的方法名前
接着是作为返回值的Users类,特别是作为参数的username以及password
以下是正确配置完swagger2之后的界面。
五、小程序注册与后端联调
首先在app.js上配置全局变量(如果测试时是在手机上的话,需要填http内网穿透)
接着写regist.js,用来完成联调
const app = getApp() Page({ data: { }, doRegist: function(e){ var formObject = e.detail.value; var username = formObject.username; var password = formObject.password; //简单验证 if(username.length == 0 || password.length == 0){ wx.showToast({ title: '用户名或密码不能为空', icon: 'none', duration: 3000 }) }else{ var serverUrl = app.serverUrl; wx.showLoading({ title: '请等待...', }); wx.request({ url: serverUrl + '/regist', method: "POST", data: { username: username, password: password }, header: { 'content-type': 'application/json' // 默认值 }, success: function(res) { console.log(res.data); wx.hideLoading(); var status = res.data.status; if(status == 200){ wx.showToast({ title: '用户注册成功~!!!', icon: 'none', duration: 3000 }), app.userInfo = res.data.data; }else if(status == 500){ wx.showToast({ title: res.data.msg, icon: 'none', duration: 3000 }) } } }) } }, goLoginPage: function () { wx.navigateTo({ url: '../userLogin/login', }) } })
测试时,需要在app.json上加上"debug": true的配置,在上线时再删除
六、用户登录
1、界面
login.wxml
<view> <view class="login-icon"> <image class="login-img" src="../resource/images/dsp1.jpg"></image> </view> <view class="login-from"> <form bindsubmit='doLogin'> <!--账号--> <view class="inputView"> <image class="nameImage" src="../resource/images/username.png"></image> <label class="loginLabel">账号</label> <input name="username" value='imooc' class="inputText" placeholder="请输入账号" /> </view> <view class="line"></view> <!--密码--> <view class="inputView"> <image class="keyImage" src="../resource/images/password.png"></image> <label class="loginLabel">密码</label> <input name="password" value='imooc' class="inputText" password="true" placeholder="请输入密码" /> </view> <!--按钮--> <view> <button class="loginBtn" type="primary" form-type='submit'>登录</button> </view> <view> <button class="goRegistBtn" type="warn" bindtap="goRegistPage">没有账号?点击注册</button> </view> </form> </view> </view>
login.wxss
page { background-color: whitesmoke; } .login-img { width: 750rpx; } /*表单内容*/ .inputView { background-color: white; line-height: 45px; } /*输入框*/ .nameImage, .keyImage { margin-left: 22px; width: 20px; height: 20px; } .loginLabel { margin: 15px 15px 15px 10px; color: gray; font-size: 15px; } .inputText { float: right; text-align: right; margin-right: 22px; margin-top: 11px; font-size: 15px; } .line { width: 100%; height: 1px; background-color: gainsboro; margin-top: 1px; } /*按钮*/ .loginBtn { width: 80%; margin-top: 35px; } .goRegistBtn { width: 80%; margin-top: 15px; }
2、编写后端springboot接口
RegistLoginController.class
package com.imooc.controller; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.imooc.pojo.Users; import com.imooc.service.UserService; import com.imooc.utils.IMoocJSONResult; import com.imooc.utils.MD5Utils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @RestController @Api(value = "用户注册登录的接口",tags = {"注册登录的controller"}) public class RegistLoginController { @Autowired private UserService userService; @ApiOperation(value = "用户注册", notes = "用户注册的接口") @PostMapping("/regist") public IMoocJSONResult regist(@RequestBody Users user) throws Exception { //1、判断用户名和密码必须不为空 if(StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) { return IMoocJSONResult.errorMsg("用户名和密码不能为空"); } //2、判断用户名是否存在 boolean usernameIsExist = userService.queryUsernameIsExist(user.getUsername()); //3、保存用户,注册信息 if(!usernameIsExist) { user.setNickname(user.getUsername()); user.setPassword(MD5Utils.getMD5Str(user.getPassword())); user.setFansCounts(0); user.setReceiveLikeCounts(0); user.setFollowCounts(0); userService.saveUser(user); }else { return IMoocJSONResult.errorMsg("用户名已经存在,请换一个试试"); } user.setPassword(""); return IMoocJSONResult.ok(user); } @ApiOperation(value="用户登录", notes="用户登录的接口") @PostMapping("/login") public IMoocJSONResult login(@RequestBody Users user) throws Exception { String username = user.getUsername(); String password = user.getPassword(); // Thread.sleep(3000); // 1. 判断用户名和密码必须不为空 if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) { return IMoocJSONResult.ok("用户名或密码不能为空..."); } // 2. 判断用户是否存在 Users userResult = userService.queryUserForLogin(username, MD5Utils.getMD5Str(user.getPassword())); // 3. 返回 if (userResult != null) { userResult.setPassword(""); // UsersVO userVO = setUserRedisSessionToken(userResult); return IMoocJSONResult.ok(userResult); } else { return IMoocJSONResult.errorMsg("用户名或密码不正确, 请重试..."); } } }
UserServiceImpl.class
package com.imooc.service; import org.n3r.idworker.Sid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.imooc.mapper.UsersMapper; import com.imooc.pojo.Users; import tk.mybatis.mapper.entity.Example; import tk.mybatis.mapper.entity.Example.Criteria; @Service public class UserServiceImpl implements UserService { @Autowired private UsersMapper userMapper; //导入工具包,使用户生成的id是唯一的id @Autowired private Sid sid; @Transactional(propagation = Propagation.SUPPORTS) @Override public boolean queryUsernameIsExist(String username) { // TODO Auto-generated method stub Users user = new Users(); user.setUsername(username); Users result = userMapper.selectOne(user); return result == null ? false : true; } @Transactional(propagation = Propagation.REQUIRED) @Override public void saveUser(Users user) { // TODO Auto-generated method stub String userId = sid.nextShort(); user.setId(userId); userMapper.insert(user); } @Transactional(propagation = Propagation.SUPPORTS) @Override public Users queryUserForLogin(String username, String password) { Example userExample = new Example(Users.class); Criteria criteria = userExample.createCriteria(); criteria.andEqualTo("username", username); criteria.andEqualTo("password", password); Users result = userMapper.selectOneByExample(userExample); return result; } }
3、小程序登录与后端联调
login.js
const app = getApp() Page({ data: { }, // onLoad: function (params) { // var me = this; // var redirectUrl = params.redirectUrl; // // debugger; // if (redirectUrl != null && redirectUrl != undefined && redirectUrl != '') { // redirectUrl = redirectUrl.replace(/#/g, "?"); // redirectUrl = redirectUrl.replace(/@/g, "="); // me.redirectUrl = redirectUrl; // } // }, // 登录 doLogin: function (e) { // var me = this; var formObject = e.detail.value; var username = formObject.username; var password = formObject.password; // 简单验证 if (username.length == 0 || password.length == 0) { wx.showToast({ title: '用户名或密码不能为空', icon: 'none', duration: 3000 }) } else { var serverUrl = app.serverUrl; wx.showLoading({ title: '请等待...', }); // 调用后端 wx.request({ url: serverUrl + '/login', method: "POST", data: { username: username, password: password }, header: { 'content-type': 'application/json' // 默认值 }, success: function (res) { console.log(res.data); wx.hideLoading(); if (res.data.status == 200) { // 登录成功跳转 wx.showToast({ title: '登录成功', icon: 'success', duration: 2000 }); app.userInfo = res.data.data; // // fixme 修改原有的全局对象为本地缓存 // app.setGlobalUserInfo(res.data.data); // 页面跳转 // var redirectUrl = me.redirectUrl; // if (redirectUrl != null && redirectUrl != undefined && redirectUrl != '') { // wx.redirectTo({ // url: redirectUrl, // }) // } else { // wx.redirectTo({ // url: '../mine/mine', // }) // } } else if (res.data.status == 500) { // 失败弹出框 wx.showToast({ title: res.data.msg, icon: 'none', duration: 3000 }) } } }) } }, goRegistPage:function() { wx.navigateTo({ url: '../userRegist/regist', }) } })
注:在两个页面的js文件上都配置了跳转到彼此的js函数。