导读
本文基于以下文章开发:
SpringBoot学习之旅(二)—整合MyBatis(MyBatis Generator);
可优先读取该文章,快速搭建一个基于整合了mybatis的SpringBoot项目
源码地址
前言
- 何为MVC
可参考mvc设计模式 - 本文简介
使用MVC设计模式,实现对用户注册及登录操作,从而演示整个业务的流程
目录结构完善
- src/main/java/com.lupf.springboottest
- controller
控制器层- viewobject
该目录为用于定义响应给前端的数据对象;由于业务对象中的数据可能存在部分敏感或者不需要返回给前端的对象,那么在该对象中将其剔除掉
- viewobject
- dataobject
数据模型对象,直接映射数据库的表的对象,这里的数据不会展示给用户;说通俗一点例子,这里就是我们裤衩子了,直接贴近我们的隐私部位(数据库数据),所以是不能给人看的;需要通过饰品(model)装饰之后,穿上衣服(View),才能展示个别人 - service
服务层- impl
用于具体的service接口的实现 - model
业务模型对象
与上面的dataobject对象不同的是,这里的对象是涉及到部分业务相关的业务对象,其中可能存在业务逻辑从而导致业务对象的结构与DO成的结构不一致的情况;如,用户和密码在DO成是2个对象,但是在业务层需要将其合并,因为用户信息和密码均属于用户相关信息
- impl
- controller
编码
Service层实现
-
service接口
package com.lupf.springboottest.service; import com.lupf.springboottest.service.model.UserModel; /** * 用户的service接口 */ public interface UserService { /** * 根据用户id获取用户对象 * * @param id */ UserModel getUserBuId(Integer id) throws BusiException; /** * 获取手机验证码 * * @param phoneNum 用户手机号码 */ void getUserPhoneCode(String phoneNum) throws BusiException; /** * 注册 * * @param userModel * @return */ UserModel register(UserModel userModel) throws BusiException; /** * 登录 * * @param phoneNum 电话 * @param pwd 密码 * @return */ UserModel login(String phoneNum, String pwd) throws BusiException; }
- service实现需要做的事情
package com.lupf.springboottest.service.impl; import com.lupf.springboottest.dao.UserDOMapper; import com.lupf.springboottest.dao.UserPasswordDOMapper; import com.lupf.springboottest.dataobject.UserDO; import com.lupf.springboottest.dataobject.UserPasswordDO; import com.lupf.springboottest.service.UserService; import com.lupf.springboottest.service.model.UserModel; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class UserServiceImpl implements UserService { @Autowired private UserDOMapper userDOMapper; @Autowired private UserPasswordDOMapper userPasswordDOMapper; @Override @Transactional public UserModel getUserBuId(Integer id) throws BusiException { //根据用户id获取用户信息 //根据用户的id获取到用户的密码信息 //将数据模型对象转换为领域模型对象 //返回用户信息 return null; } @Override public void getUserPhoneCode(String phoneNum) throws BusiException { //校验手机号码的有效性 //生成验证码 //发送验证码 //保存验证码 } @Override public UserModel register(UserModel userModel) throws BusiException { //校验前端上传的用户信息 //校验验证码 //校验密码的合法性 //保存用户 //保存密码 //返回注册的用户信息 //生成登录的唯一标识 //返回用户信息 return null; } @Override public UserModel login(String phoneNum, String pwd) throws BusiException { //获取用户信息 //校验用户密码 //校验成功 //生成登录的唯一标识 //返回用户信息 return null; }
-
Pom文件添加Lang包配置
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency>
-
Dao层添加根据电话号码获取用户信息(用于登录)
UserDOMapper添加以下方法/** * 根据用户电话号码查询用户信息 * * @param phoneNum * @return */ UserDO selectByPhoneNum(String phoneNum);
UserDOMapper.xml下添加以下配置
<select id="selectByPhoneNum" parameterType="java.lang.String" resultMap="BaseResultMap"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Thu Feb 28 16:27:46 CST 2019. --> select <include refid="Base_Column_List"/> from user_info where telphone = #{phoneNum,jdbcType=VARCHAR} </select>
-
service具体实现
package com.lupf.springboottest.service.impl; import com.alibaba.druid.util.StringUtils; import com.lupf.springboottest.dao.UserDOMapper; import com.lupf.springboottest.dao.UserPasswordDOMapper; import com.lupf.springboottest.dataobject.UserDO; import com.lupf.springboottest.dataobject.UserPasswordDO; import com.lupf.springboottest.error.BusiErrCodeEm; import com.lupf.springboottest.error.BusiException; import com.lupf.springboottest.service.UserService; import com.lupf.springboottest.service.model.UserModel; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletRequest; import java.util.Random; @Service public class UserServiceImpl implements UserService { @Autowired private UserDOMapper userDOMapper; @Autowired private UserPasswordDOMapper userPasswordDOMapper; @Autowired private HttpServletRequest httpServletRequest; @Override public UserModel getUserBuId(Integer id) throws BusiException { //根据用户id获取用户信息 UserDO userDO = userDOMapper.selectByPrimaryKey(id); //根据用户的id获取到用户的密码信息 UserPasswordDO userPasswordDO = null; if (null != userDO) { userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId()); } //将数据模型对象转换为领域模型对象 UserModel userModel = userDOAndPasswordDO2UserModel(userDO, userPasswordDO); //返回用户信息 return userModel; } @Override public void getUserPhoneCode(String phoneNum) throws BusiException { //校验手机号码的有效性 //这里就不演示具体的校验规则了,网上很多 //生成验证码 Random random = new Random(); //生个6位的随机数 int code = random.nextInt(899999) + 100000; //发送验证码 //这里发送验证码;可以使用三方的接口将验证码发送给用户 //演示使用,这里就只做个打印 System.out.println("验证码为:" + code); //保存验证码 //为了方便测试,这里将验证码放在session里面 //实际的开发过程中,可以将这个数据保存到redis中并且给这个数据设置一个有效期 httpServletRequest.getSession().setAttribute(phoneNum, code); } @Override @Transactional public UserModel register(UserModel userModel) throws BusiException { //校验前端上传的用户信息 if (null == userModel) { throw new BusiException(BusiErrCodeEm.REQ_PARAM_10001); } //校验密码的合法性 //这里按各自的规则进行校验即可 //这里不做演示 UserDO userDO = userModel2UserDO(userModel); try { //保存用户 //在mapper对应的方法下添加以下参数 //这里很重要,否则添加之后userDO对象里面的id没有数据 //keyProperty="id" useGeneratedKeys="true" userDOMapper.insertSelective(userDO); //保存密码 //组装用户密码相关的对象 UserPasswordDO userPasswordDO = new UserPasswordDO(); //用户的索引ID userPasswordDO.setUserId(userDO.getId()); //加密后的密码 userPasswordDO.setEncrptPassword(userModel.getEncrptPassword()); //添加用户密码数据 userPasswordDOMapper.insertSelective(userPasswordDO); } catch (DuplicateKeyException e) { //用户号码是唯一键,如果存在,说明用户已经注册过了 e.printStackTrace(); throw new BusiException(BusiErrCodeEm.USER_20003); } //根据ID,重新获取一遍注册的用户信息并返回 UserModel inserUserModel = this.getUserBuId(userDO.getId()); //返回用户信息 return inserUserModel; } @Override public UserModel login(String phoneNum, String encrptPassword) throws BusiException { //获取用户信息 //根据用户的电话号码获取用户ID UserDO userDO = userDOMapper.selectByPhoneNum(phoneNum); //定义用户密码信息数据对象 UserPasswordDO userPasswordDO = null; //判断该用户是否已经 if (null != userDO) { userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId()); } else { throw new BusiException(BusiErrCodeEm.USER_20004); } //校验用户密码 if (null == userPasswordDO || !StringUtils.equals(encrptPassword, userPasswordDO.getEncrptPassword())) { //这里提示用户名或者密码不正确是为了防止用户去不停尝试帐号密码 throw new BusiException(BusiErrCodeEm.USER_20001, "用户名或者密码不正确"); } //校验成功 //将数据对象转换为领域模型对象 UserModel userModel = this.userDOAndPasswordDO2UserModel(userDO, userPasswordDO); //返回用户信息 return userModel; } /** * 将用户的DO对象和密码DO对象转换为用户业务对象 * * @param userDO * @param userPasswordDO * @return */ protected UserModel userDOAndPasswordDO2UserModel(UserDO userDO, UserPasswordDO userPasswordDO) { if (null == userDO) return null; UserModel userModel = new UserModel(); BeanUtils.copyProperties(userDO, userModel); if (null != userPasswordDO) { userModel.setEncrptPassword(userPasswordDO.getEncrptPassword()); } return userModel; } /** * 将领域模型对象转换为数据对象 * * @param userModel * @return */ public UserDO userModel2UserDO(UserModel userModel) { UserDO userDO = new UserDO(); BeanUtils.copyProperties(userModel, userDO); return userDO; } }
-
Controller代码实现
package com.lupf.springboottest.controller; import com.lupf.springboottest.controller.viewobject.UserVO; import com.lupf.springboottest.dao.UserDOMapper; import com.lupf.springboottest.error.BusiErrCodeEm; import com.lupf.springboottest.error.BusiException; import com.lupf.springboottest.response.BaseRespObj; import com.lupf.springboottest.service.UserService; import com.lupf.springboottest.service.model.UserModel; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import sun.misc.BASE64Encoder; import javax.servlet.http.HttpServletRequest; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @RestController @RequestMapping("/user") public class UserController extends BaseController { @Autowired UserDOMapper userDOMapper; @Autowired private UserService userService; @Autowired private HttpServletRequest httpServletRequest; /** * 获取用户验证码 * * @param phoneNum 用户号码 * @return * @throws BusiException */ @RequestMapping(value = "/getPhoneCode", method = RequestMethod.POST) public BaseRespObj getUserByID(@RequestParam(name = "phoneNum") String phoneNum) throws BusiException { userService.getUserPhoneCode(phoneNum); return BaseRespObj.create(null); } /** * 注册 * * @param name 用户昵称 * @param phoneNum 用户号码 * @param code 用户验证码 * @param age 年龄 * @param sex 性别 * @param email 邮箱 * @param pwd 密码 * @return * @throws Exception */ @RequestMapping(value = "/register", method = RequestMethod.POST) public BaseRespObj register( @RequestParam(name = "name") String name, @RequestParam(name = "phoneNum") String phoneNum, @RequestParam(name = "phoneCode") Integer code, @RequestParam(name = "age") Integer age, @RequestParam(name = "sex") String sex, @RequestParam(name = "email") String email, @RequestParam(name = "pwd") String pwd) throws Exception { //将前端数据转换为领域模型对象 UserModel userModel = new UserModel(); userModel.setAge(age); userModel.setSex(Byte.valueOf(sex)); userModel.setEmail(email); userModel.setName(name); userModel.setTelphone(phoneNum); //在session中取出前面发送的验证码 Integer sessCode = (Integer) httpServletRequest.getSession().getAttribute(phoneNum); if (null == sessCode || sessCode.intValue() != code.intValue()) { throw new BusiException(BusiErrCodeEm.REQ_PARAM_10001, "短信验证码信息有误!"); } userModel.setEncrptPassword(this.encodeByMD5(pwd)); userModel.setRegisterMode("bytelphone"); UserModel insertUserModel = userService.register(userModel); UserVO userVO = userModel2UserVO(insertUserModel); return BaseRespObj.create(userVO); } /** * 登录 * * @param phoneNum 用户电话号码 * @param pwd 用户密码 * @return * @throws Exception */ @RequestMapping(value = "/login", method = RequestMethod.POST) public BaseRespObj login( @RequestParam(name = "phoneNum") String phoneNum, @RequestParam(name = "pwd") String pwd) throws Exception { if (StringUtils.isEmpty(phoneNum) || StringUtils.isEmpty(pwd)) { throw new BusiException(BusiErrCodeEm.REQ_PARAM_10001); } UserModel userModel = userService.login(phoneNum, this.encodeByMD5(pwd)); UserVO userVO = userModel2UserVO(userModel); return BaseRespObj.create(userVO); } /** * 将用户业务对象转为前端的视图对象 * * @param userModel 业务模型对象 * @return 前端视图对象 */ protected UserVO userModel2UserVO(UserModel userModel) { UserVO userVO = new UserVO(); BeanUtils.copyProperties(userModel, userVO); return userVO; } /** * MD5加密 * * @param va 待加密的数据 * @return 加密后的数据 * @throws NoSuchAlgorithmException */ protected String encodeByMD5(String va) throws NoSuchAlgorithmException { MessageDigest md5 = MessageDigest.getInstance("MD5"); BASE64Encoder base64Encoder = new BASE64Encoder(); String newVa = base64Encoder.encode(md5.digest(va.getBytes())); return newVa; } }
测试
-
获取验证码
127.0.0.1:8082/user/getPhoneCode?phoneNum=13888888888
-
用户注册
- 成功
- 失败
- 成功
-
用户登录
- 成功
- 失败
- 成功
到此一个基础的基于SpringMvc的项目即搭建完成