studentDOS = studentDOMapper.getAll();
+ StringBuilder studentBuilder = new StringBuilder();
+ for (StudentDO student : studentDOS) {
+ studentBuilder.append("学号:").append(student.getStudentNo()).append("\n\n");
+ studentBuilder.append("姓名:").append(student.getName()).append("\n\n");
+ studentBuilder.append("----------------\n\n");
+ }
+ return CommonReturnType.create(studentBuilder.toString());
+ }
+ }
+
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/UserController.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/UserController.java
new file mode 100644
index 0000000..6942c05
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/UserController.java
@@ -0,0 +1,350 @@
+package edu.heuet.shaohua.controller;
+
+import com.alibaba.druid.util.StringUtils;
+import edu.heuet.shaohua.controller.viewobject.RegisterVO;
+import edu.heuet.shaohua.controller.viewobject.UserVO;
+import edu.heuet.shaohua.error.BusinessException;
+import edu.heuet.shaohua.error.EmBusinessError;
+import edu.heuet.shaohua.response.CommonReturnType;
+import edu.heuet.shaohua.response.OtpCode;
+import edu.heuet.shaohua.service.UserService;
+import edu.heuet.shaohua.service.model.UserModel;
+import edu.heuet.shaohua.util.CommonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+import sun.misc.BASE64Encoder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.validation.Valid;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Random;
+
+/*
+@Controller的作用在类级上,用来标记该类,让Spring可以扫描到
+这一部分知识属于基础知识,可以参考《Spring实战(任意一版)》
+*/
+@Controller("user")
+@RequestMapping("/user")
+/**
+ * 继承BaseController,
+ * 父类的方法子类不重新,就会引用父类的方法,
+ * 若子类重写父类的方法,则引用子类的方法
+ * 这里不需要进行重写handlerException
+ *
+ * @CrossOrigin解决跨域请求问题
+ * No 'Access-Control-Allow-Origin' header is present on the requested resource
+ * 加上这个注解后,就会让response对象返回'Access-Control-Allow-Origin' header 为 通配符*
+ * 但是单纯的加注解,只是让跨域互通了,还不能实现互信
+ * 需要再加两个参数,才能实现前后端互信
+ *
+ * @author littlecurl
+ */
+@CrossOrigin(allowCredentials = "true", allowedHeaders = "*")
+public class UserController extends BaseController {
+ private static Logger Log = LoggerFactory.getLogger(UserController.class);
+ /**
+ * 带@Autowired的都是Bean,默认用单例模式创建
+ */
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private HttpServletRequest httpServletRequest;
+
+ /**
+ *
+ */
+ private HttpSession session;
+
+ /**
+ * **************** 对前两个注解的解释:****************
+ * 1、这里的@RequestMapping作用在方法级,
+ * 告诉我们不只有类级可以使用此注解,
+ * 同时也提现了SpringMVC可以映射URL到具体方法的优秀设计
+ * 2、这里需要指定@ResponseBody,
+ * 具体理解可以参考[博客园](https://www.cnblogs.com/qiankun-site/p/5774325.html#4263851)
+ * 这样返回的数据才会以JSON的格式写入到HttpServletResponse对象的body区
+ * 浏览器才能呈现body区的JSON数据
+ * 如果忘记指定@ResponseBody,则response对象为空,会报404错误
+ * (具体response对象是个啥?这是JavaEE基础Servlet里面的知识点,可以回头补习一下)
+ * 另外,JSON格式的数据,推荐是否Firefox浏览器查看,会自动格式化
+ *
+ * **************** 对返回值类型CommonReturnType的解释:****************
+ * 虽然我们在Service层,将dataobject整合成了UserModel
+ * 但那是给Controller层诸如密码验证之类的,需要两张表的数据的业务准备的
+ * 单纯的getUser()业务没必要返回UserModel,将用户敏感信息诸如加密密码,登录方式等等也透传给前端
+ * 因此返回值应该再独立出一个viewobject层
+ * 但是,仅仅返回viewobject对象的JSON序列化,这样设计没有通用性
+ * 比如说,不知道返回值的状态到底是成功还是失败
+ * 因此,应该再构造一个response层,对viewobject进行封装,返回CommonReturnType
+ *
+ * **************** 对@RequestParam注解的解释:****************
+ *
+ * @param id 用户id
+ * @return 通用返回对象
+ * @RequestParam用来获取URL中?后面的arg=value对应的参数值 当然SpringMVC不只提供了这一种获取参数的方式,只不过这一注解最常用,其他注解还有好多
+ * 具体可以参考[博客园](https://www.cnblogs.com/selinamee/p/5266266.html)
+ */
+ @RequestMapping("/get")
+ @ResponseBody
+ public CommonReturnType getUser(@RequestParam(name = "id") Integer id) throws BusinessException {
+ /* 调用Service服务,获取id对应的用户信息UserModel
+ 将model转为viewobject
+ 再将viewobject进行封装成CommonReturnType
+ 返回CommonReturnType
+ */
+ UserModel userModel = userService.getUserById(id);
+ /*
+ 若用户不存在,则抛出异常,抛到了Tomcat的容器层,
+ 如果把异常抛到Tomcat容器层后就不管了,那就只是会在控制台Tomcat日志中打印异常信息,
+ 无法返回到前端。
+ 好在SpringBoot有给出解决办法,就是再定义一个handlerException方法,
+ 写在了BaseController中。
+ */
+ if (userModel == null) {
+ /*
+ 如果把下面的代码注释掉,并且再引用一下userModel对象
+ 比如:
+ userModel.setEncryptPassword("123");
+ 因为userModel是null,引用空指针进行set,Java虚拟机会抛出java.lang.NullPointException
+ 这时候就会触发BaseController里面SpringBoot的注解@ExceptionHandler(Exception.class)
+ 然后判断到if (ex instanceof BusinessException)条件不成立
+ 继而返回UNKNOWN_ERROR的CommonReturnType
+ 从这里可以看出来UserController继承BaseController实现代码复用机制
+ */
+ throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
+ }
+ UserVO userVO = convertFromModel(userModel);
+ /*
+ 如果没有异常跑出,就表示返回的是正确的结果
+ 同时,因为有加@ResponseBody注解,该对象会被解析为JSON格式,呈现到前端
+ */
+ return CommonReturnType.create(userVO);
+ }
+
+ /**
+ * 将UserModel转为UserVO
+ *
+ * @param userModel Model
+ * @return UserVO
+ */
+ private UserVO convertFromModel(UserModel userModel) {
+ if (userModel == null) {
+ return null;
+ }
+ UserVO userVO = new UserVO();
+ /* 调用BeanUtils提供的复制属性方法,userVO不存在的属性会被自动丢弃 */
+ BeanUtils.copyProperties(userModel, userVO);
+ return userVO;
+ }
+
+ /**
+ * 获取otp验证码
+ * 三步走
+ * 1、生成验证码
+ * 2、存到 Session 中
+ * 3、返回验证码
+ *
+ * 注意这里POST请求要求传递请求头 content-type:application/x-www-form-urlencoded
+ *
+ * @param telephone
+ * @return
+ * @throws BusinessException
+ */
+ @RequestMapping(value = "/getOtp", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
+ @ResponseBody
+ public CommonReturnType getOtp(@RequestParam(name = "telephone") String telephone) throws BusinessException {
+ /* 0、用户获取验证码时,检测是否已存在注册用户 */
+ boolean hasRegistered = userService.getUserByTelephone(telephone);
+ if (hasRegistered) {
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "手机号已重复注册");
+ }
+ // 1、按照一定规则生成OTP验证码(6位)
+ Random random = new Random();
+ int randomInt = random.nextInt(99999);
+ randomInt += 100000;
+ String otpCode = String.valueOf(randomInt);
+
+ // 2、将OTP验证码与用户手机号进行绑定
+ session = httpServletRequest.getSession();
+ session.setAttribute(telephone, otpCode);
+
+ // 3、将OTP验证码通过短信通道发给用户,省略
+ Log.info("telephone: " + telephone + "&otpCode: " + otpCode);
+
+ // 4、将信息抽象为类
+ OtpCode otpCodeObj = new OtpCode(telephone, otpCode);
+ // 5、返回正确信息,方便前端获取
+ return CommonReturnType.create(otpCodeObj, "successGetOtpCode");
+ }
+
+ /**
+ * 用户注册接口
+ * 接收参数统一使用字符串,接收后再进行类型转换
+ *
+ * @param telephone 手机号
+ * @param otpCode 验证码
+ * @param name 姓名
+ * @param ageStr 年龄
+ * @param genderStr 性别
+ * @param password 密码
+ * @return 通用返回对象
+ */
+ @RequestMapping(value = "/register", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
+ @ResponseBody
+ public CommonReturnType register(
+ @RequestParam(name = "telephone") String telephone,
+ @RequestParam(name = "otpCode") String otpCode,
+ @RequestParam(name = "name") String name,
+ @RequestParam(name = "age") String ageStr,
+ @RequestParam(name = "gender") String genderStr,
+ @RequestParam(name = "password") String password
+ ) throws UnsupportedEncodingException, NoSuchAlgorithmException, BusinessException {
+ boolean hasRegistered = userService.getUserByTelephone(telephone);
+ if (hasRegistered) {
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "手机号已重复注册");
+ }
+
+ // 从Session中获取对应手机号的验证码
+ // otpCode是用户填写的,inSessionOtpCode是系统生成的
+ if (session == null) {
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "无效的验证码,请重新获取");
+ }
+
+ String inSessionOtpCode = (String) session.getAttribute(telephone);
+
+
+ Log.info("telephone: " + telephone + " inSessionOtpCode: " + inSessionOtpCode + " otpCode: " + otpCode);
+ if (!StringUtils.equals(otpCode, inSessionOtpCode)) {
+ Log.info("短信验证码错误");
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "短信验证码错误");
+ }
+
+ // 类型转换,适配数据库
+ int age = Integer.parseInt(ageStr);
+ Byte gender = Byte.parseByte(genderStr);
+ // 验证码通过后,进行注册流程
+ UserModel userModel = new UserModel();
+ userModel.setName(name);
+ userModel.setGender(gender);
+ userModel.setAge(age);
+ userModel.setTelephone(telephone);
+ userModel.setRegisterMode("byphone");
+ userModel.setEncryptPassword(this.EncodeByMd5(password));
+
+ userService.register(userModel);
+ // 注册成功,只返回success即可
+ return CommonReturnType.create(userModel);
+ }
+
+ /**
+ * 用户注册接口
+ * 接收参数统一使用字符串,接收后再进行类型转换
+ *
+ * @return 通用返回对象
+ */
+ @RequestMapping(value = "/registerjson", method = {RequestMethod.POST})
+ @ResponseBody
+ public CommonReturnType registerJson(
+ @Valid
+ @RequestBody RegisterVO registerVO,
+ BindingResult bindingResult
+ ) throws UnsupportedEncodingException, NoSuchAlgorithmException, BusinessException {
+ if (bindingResult.hasErrors()) {
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, CommonUtil.processErrorString(bindingResult));
+ }
+ // 从Session中获取对应手机号的验证码
+ // otpCode是用户填写的,inSessionOtpCode是系统生成的
+ String inSessionOtpCode = (String) session.getAttribute(registerVO.getTelephone());
+ Log.info("telephone: " + registerVO.getTelephone() + " inSessionOtpCode: "
+ + inSessionOtpCode + " otpCode: " + registerVO.getOtpCode());
+ if (!StringUtils.equals(registerVO.getOtpCode(), inSessionOtpCode)) {
+ Log.info("短信验证码错误");
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "短信验证码错误");
+ }
+ // 类型转换,适配数据库
+ int age = Integer.parseInt(registerVO.getAge());
+ Byte gender = Byte.parseByte(registerVO.getGender());
+ // 验证码通过后,进行注册流程
+ UserModel userModel = new UserModel();
+ userModel.setName(registerVO.getName());
+ userModel.setGender(gender);
+ userModel.setAge(age);
+ userModel.setTelephone(registerVO.getTelephone());
+ userModel.setRegisterMode("byphone");
+ userModel.setEncryptPassword(this.EncodeByMd5(registerVO.getTelephone()));
+
+ userService.register(userModel);
+ // 注册成功,只返回success即可
+ return CommonReturnType.create(null);
+ }
+
+ /**
+ * 用户登录接口
+ *
+ * @param telephone 手机号
+ * @param password 原生密码
+ * @return 通用返回对象
+ */
+ @RequestMapping(value = "/login", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
+ @ResponseBody
+ public CommonReturnType login(
+ @RequestParam(value = "telephone", required = true) String telephone,
+ @RequestParam(value = "password", required = true) String password,
+ @RequestParam(value = "type", required = true) String type
+ ) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
+ // 入参校验
+ if (org.apache.commons.lang3.StringUtils.isEmpty(telephone)
+ || org.apache.commons.lang3.StringUtils.isEmpty(password)
+ || org.apache.commons.lang3.StringUtils.isEmpty(type)
+ ) {
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
+ }
+
+ boolean hasRegistered = userService.getUserByTelephone(telephone);
+ if (!hasRegistered) {
+ throw new BusinessException(EmBusinessError.USER_NOT_EXIST);
+ }
+
+ UserModel userModel = null;
+ // 登录
+ if (StringUtils.equals(type, "login")) {
+ userModel = userService.validateLogin(telephone, this.EncodeByMd5(password));
+ }
+ // 自动登录
+ else if (StringUtils.equals(type, "autoLogin")) {
+ userModel = userService.validateLogin(telephone, password);
+ } else {
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
+ }
+
+ // 将登陆凭证加入到用户登录成功的Session中
+ // 切换web页面的时候,可以不用重复登录
+ session = httpServletRequest.getSession();
+ session.setAttribute("IS_LOGIN", true);
+ session.setAttribute("LOGIN_USER", userModel);
+
+ // 登录成功,只返回success即可
+ return CommonReturnType.create(userModel);
+ }
+
+ /**
+ * MD5加密+BASE64编码
+ *
+ * @return 加密后字符串
+ */
+ public String EncodeByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ BASE64Encoder base64en = new BASE64Encoder();
+ String newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
+ return newstr;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/viewobject/RegisterVO.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/viewobject/RegisterVO.java
new file mode 100644
index 0000000..e953872
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/viewobject/RegisterVO.java
@@ -0,0 +1,69 @@
+package edu.heuet.shaohua.controller.viewobject;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+public class RegisterVO {
+ @NotNull(message = "手机号不能为空")
+ private String telephone;
+ private String otpCode;
+ @NotBlank(message = "用户名不能为空")
+ private String name;
+ @NotNull(message = "必须填写年龄")
+ @Min(value = 0, message = "年龄必须大于0")
+ @Max(value = 150, message = "年龄必须小于150")
+ private String age;
+ @NotNull(message = "必须填写性别")
+ private String gender;
+ private String password;
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+
+ public String getOtpCode() {
+ return otpCode;
+ }
+
+ public void setOtpCode(String otpCode) {
+ this.otpCode = otpCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAge() {
+ return age;
+ }
+
+ public void setAge(String age) {
+ this.age = age;
+ }
+
+ public String getGender() {
+ return gender;
+ }
+
+ public void setGender(String gender) {
+ this.gender = gender;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/viewobject/UserVO.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/viewobject/UserVO.java
new file mode 100644
index 0000000..49c06fa
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/controller/viewobject/UserVO.java
@@ -0,0 +1,49 @@
+package edu.heuet.shaohua.controller.viewobject;
+/* 用于呈现给前端的模型 */
+public class UserVO {
+ private Integer id;
+ private String name;
+ private Byte gender;
+ private Integer age;
+ private String telephone;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Byte getGender() {
+ return gender;
+ }
+
+ public void setGender(Byte gender) {
+ this.gender = gender;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/NewsDOMapper.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/NewsDOMapper.java
new file mode 100644
index 0000000..5fc448b
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/NewsDOMapper.java
@@ -0,0 +1,59 @@
+package edu.heuet.shaohua.dao;
+
+import edu.heuet.shaohua.dataobject.NewsDO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface NewsDOMapper {
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table news_info
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ int deleteByPrimaryKey(Long id);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table news_info
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ int insert(NewsDO record);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table news_info
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ int insertSelective(NewsDO record);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table news_info
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ NewsDO selectByPrimaryKey(Long id);
+
+ List selectByTitle(@Param("title") String title);
+
+ List selectAll();
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table news_info
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ int updateByPrimaryKeySelective(NewsDO record);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table news_info
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ int updateByPrimaryKey(NewsDO record);
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/StudentDOMapper.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/StudentDOMapper.java
new file mode 100644
index 0000000..6a7d030
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/StudentDOMapper.java
@@ -0,0 +1,58 @@
+package edu.heuet.shaohua.dao;
+
+import edu.heuet.shaohua.dataobject.StudentDO;
+
+import java.util.List;
+
+public interface StudentDOMapper {
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table student_inf_mysql
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ int deleteByPrimaryKey(String studentNo);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table student_inf_mysql
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ int insert(StudentDO record);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table student_inf_mysql
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ int insertSelective(StudentDO record);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table student_inf_mysql
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ StudentDO selectByPrimaryKey(String studentNo);
+
+ StudentDO selectByName(String name);
+
+ List getAll();
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table student_inf_mysql
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ int updateByPrimaryKeySelective(StudentDO record);
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method corresponds to the database table student_inf_mysql
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ int updateByPrimaryKey(StudentDO record);
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/UserDOMapper.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/UserDOMapper.java
new file mode 100644
index 0000000..08a8715
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/UserDOMapper.java
@@ -0,0 +1,13 @@
+package edu.heuet.shaohua.dao;
+
+import edu.heuet.shaohua.dataobject.UserDO;
+
+public interface UserDOMapper {
+ int deleteByPrimaryKey(Integer id);
+ int insert(UserDO record);
+ int insertSelective(UserDO record);
+ UserDO selectByPrimaryKey(Integer id);
+ UserDO selectByTelephone(String telphone);
+ int updateByPrimaryKeySelective(UserDO record);
+ int updateByPrimaryKey(UserDO record);
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/UserPasswordDOMapper.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/UserPasswordDOMapper.java
new file mode 100644
index 0000000..c254aec
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dao/UserPasswordDOMapper.java
@@ -0,0 +1,16 @@
+package edu.heuet.shaohua.dao;
+
+import edu.heuet.shaohua.dataobject.UserPasswordDO;
+
+/**
+ * 这里的方法都是调用的Mapper.xml的SQL语句
+ */
+public interface UserPasswordDOMapper {
+ int deleteByPrimaryKey(Integer id);
+ int insert(UserPasswordDO record);
+ int insertSelective(UserPasswordDO record);
+ UserPasswordDO selectByPrimaryKey(Integer id);
+ UserPasswordDO selectByUserId(Integer UserId);
+ int updateByPrimaryKeySelective(UserPasswordDO record);
+ int updateByPrimaryKey(UserPasswordDO record);
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/NewsDO.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/NewsDO.java
new file mode 100644
index 0000000..4a313ba
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/NewsDO.java
@@ -0,0 +1,180 @@
+package edu.heuet.shaohua.dataobject;
+
+import java.util.Date;
+
+public class NewsDO {
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column news_info.id
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ private Long id;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column news_info.title
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ private String title;
+
+ private String content;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column news_info.picture
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ private String picture;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column news_info.create_time
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ private Date createTime;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column news_info.update_time
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ private Date updateTime;
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column news_info.id
+ *
+ * @return the value of news_info.id
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column news_info.id
+ *
+ * @param id the value for news_info.id
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column news_info.title
+ *
+ * @return the value of news_info.title
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column news_info.title
+ *
+ * @param title the value for news_info.title
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public void setTitle(String title) {
+ this.title = title == null ? null : title.trim();
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column news_info.picture
+ *
+ * @return the value of news_info.picture
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public String getPicture() {
+ return picture;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column news_info.picture
+ *
+ * @param picture the value for news_info.picture
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public void setPicture(String picture) {
+ this.picture = picture == null ? null : picture.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column news_info.create_time
+ *
+ * @return the value of news_info.create_time
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column news_info.create_time
+ *
+ * @param createTime the value for news_info.create_time
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column news_info.update_time
+ *
+ * @return the value of news_info.update_time
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column news_info.update_time
+ *
+ * @param updateTime the value for news_info.update_time
+ *
+ * @mbg.generated Wed Jun 17 23:26:31 GMT+08:00 2020
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/StudentDO.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/StudentDO.java
new file mode 100644
index 0000000..521d2cd
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/StudentDO.java
@@ -0,0 +1,137 @@
+package edu.heuet.shaohua.dataobject;
+
+import java.util.Date;
+
+public class StudentDO {
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column student_inf_mysql.student_no
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ private String studentNo;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column student_inf_mysql.name
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ private String name;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column student_inf_mysql.create_time
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ private Date createTime;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column student_inf_mysql.update_time
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ private Date updateTime;
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column student_inf_mysql.student_no
+ *
+ * @return the value of student_inf_mysql.student_no
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public String getStudentNo() {
+ return studentNo;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column student_inf_mysql.student_no
+ *
+ * @param studentNo the value for student_inf_mysql.student_no
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public void setStudentNo(String studentNo) {
+ this.studentNo = studentNo == null ? null : studentNo.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column student_inf_mysql.name
+ *
+ * @return the value of student_inf_mysql.name
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column student_inf_mysql.name
+ *
+ * @param name the value for student_inf_mysql.name
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public void setName(String name) {
+ this.name = name == null ? null : name.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column student_inf_mysql.create_time
+ *
+ * @return the value of student_inf_mysql.create_time
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column student_inf_mysql.create_time
+ *
+ * @param createTime the value for student_inf_mysql.create_time
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column student_inf_mysql.update_time
+ *
+ * @return the value of student_inf_mysql.update_time
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column student_inf_mysql.update_time
+ *
+ * @param updateTime the value for student_inf_mysql.update_time
+ *
+ * @mbg.generated Tue Jan 19 15:17:18 GMT+08:00 2021
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/UserDO.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/UserDO.java
new file mode 100644
index 0000000..cb54638
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/UserDO.java
@@ -0,0 +1,234 @@
+package edu.heuet.shaohua.dataobject;
+
+public class UserDO {
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private Integer id;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.name
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private String name;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.gender
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private Byte gender;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.age
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private Integer age;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.telephone
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private String telephone;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.register_mode
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private String registerMode;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_info.third_part_id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private String thirdPartId;
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.id
+ *
+ * @return the value of user_info.id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.id
+ *
+ * @param id the value for user_info.id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.name
+ *
+ * @return the value of user_info.name
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.name
+ *
+ * @param name the value for user_info.name
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setName(String name) {
+ this.name = name == null ? null : name.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.gender
+ *
+ * @return the value of user_info.gender
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public Byte getGender() {
+ return gender;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.gender
+ *
+ * @param gender the value for user_info.gender
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setGender(Byte gender) {
+ this.gender = gender;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.age
+ *
+ * @return the value of user_info.age
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public Integer getAge() {
+ return age;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.age
+ *
+ * @param age the value for user_info.age
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.telephone
+ *
+ * @return the value of user_info.telephone
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public String getTelephone() {
+ return telephone;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.telephone
+ *
+ * @param telephone the value for user_info.telephone
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setTelephone(String telephone) {
+ this.telephone = telephone == null ? null : telephone.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.register_mode
+ *
+ * @return the value of user_info.register_mode
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public String getRegisterMode() {
+ return registerMode;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.register_mode
+ *
+ * @param registerMode the value for user_info.register_mode
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setRegisterMode(String registerMode) {
+ this.registerMode = registerMode == null ? null : registerMode.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_info.third_part_id
+ *
+ * @return the value of user_info.third_part_id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public String getThirdPartId() {
+ return thirdPartId;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_info.third_part_id
+ *
+ * @param thirdPartId the value for user_info.third_part_id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setThirdPartId(String thirdPartId) {
+ this.thirdPartId = thirdPartId == null ? null : thirdPartId.trim();
+ }
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/UserPasswordDO.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/UserPasswordDO.java
new file mode 100644
index 0000000..0460698
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/dataobject/UserPasswordDO.java
@@ -0,0 +1,102 @@
+package edu.heuet.shaohua.dataobject;
+
+public class UserPasswordDO {
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_password.id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private Integer id;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_password.encrypt_password
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private String encryptPassword;
+
+ /**
+ *
+ * This field was generated by MyBatis Generator.
+ * This field corresponds to the database column user_password.user_id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ private Integer userId;
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_password.id
+ *
+ * @return the value of user_password.id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_password.id
+ *
+ * @param id the value for user_password.id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_password.encrypt_password
+ *
+ * @return the value of user_password.encrypt_password
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public String getEncryptPassword() {
+ return encryptPassword;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_password.encrypt_password
+ *
+ * @param encryptPassword the value for user_password.encrypt_password
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setEncryptPassword(String encryptPassword) {
+ this.encryptPassword = encryptPassword == null ? null : encryptPassword.trim();
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method returns the value of the database column user_password.user_id
+ *
+ * @return the value of user_password.user_id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public Integer getUserId() {
+ return userId;
+ }
+
+ /**
+ * This method was generated by MyBatis Generator.
+ * This method sets the value of the database column user_password.user_id
+ *
+ * @param userId the value for user_password.user_id
+ *
+ * @mbg.generated Sat Jun 01 10:31:20 GMT+08:00 2019
+ */
+ public void setUserId(Integer userId) {
+ this.userId = userId;
+ }
+}
\ No newline at end of file
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/BusinessException.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/BusinessException.java
new file mode 100644
index 0000000..687fdbb
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/BusinessException.java
@@ -0,0 +1,43 @@
+package edu.heuet.shaohua.error;
+
+/*
+CommonError通过异常机制来使用
+而这个实现方式属于一个设计模式:包装器业务异常类实现
+ */
+public class BusinessException extends Exception implements CommonError {
+ private CommonError commonError;
+
+ /*
+ 直接接收EmBusinessError的传参用于构造业务异常
+ 这里参数类型是EmBusinessError的接口类型
+ 是一种良好设计的体现
+ */
+ public BusinessException(CommonError commonError){
+ /* 这里调用了Exception类的构造方法 */
+ super();
+ this.commonError = commonError;
+ }
+
+ // 接收自定义errMsg的方式构造业务异常
+ public BusinessException(CommonError commonError, String errorMsg){
+ super();
+ this.commonError = commonError;
+ this.commonError.setMsg(errorMsg);
+ }
+
+ @Override
+ public int getCode() {
+ return this.commonError.getCode();
+ }
+
+ @Override
+ public String getMsg() {
+ return this.commonError.getMsg();
+ }
+
+ @Override
+ public CommonError setMsg(String errorMsg) {
+ this.commonError.setMsg(errorMsg);
+ return this;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/CommonError.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/CommonError.java
new file mode 100644
index 0000000..83bb156
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/CommonError.java
@@ -0,0 +1,7 @@
+package edu.heuet.shaohua.error;
+
+public interface CommonError {
+ public int getCode();
+ public String getMsg();
+ public CommonError setMsg(String errorMsg);
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/EmBusinessError.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/EmBusinessError.java
new file mode 100644
index 0000000..a816ec7
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/error/EmBusinessError.java
@@ -0,0 +1,44 @@
+package edu.heuet.shaohua.error;
+/*
+ Enum类也有属性、构造方法和普通方法
+ 和常规类的区别之处在于
+ Enum可以在类内写成下面这种形式
+ Enum名称1(构造参数1, 构造参数2),
+ Enum名称2(构造参数1, 构造参数2),
+ Enum名称3(构造参数1, 构造参数2)
+ ;
+ */
+public enum EmBusinessError implements CommonError{
+ /* 通用的错误类型 1开头 */
+ PARAMETER_VALIDATION_ERROR(10001,"参数不合法"),
+ UNKNOWN_ERROR(10002,"未知错误"),
+
+ /* 用户相关的异常 2开头 */
+ USER_NOT_EXIST(20001,"用户不存在"),
+ USER_LOGIN_FAIL(20002,"用户手机号或密码不正确")
+ ;
+
+ private int code;
+ private String msg;
+
+ EmBusinessError(int errorCode, String msg) {
+ this.code = errorCode;
+ this.msg = msg;
+ }
+
+ @Override
+ public int getCode() {
+ return code;
+ }
+
+ @Override
+ public String getMsg() {
+ return msg;
+ }
+
+ @Override
+ public CommonError setMsg(String errorMsg) {
+ this.msg = errorMsg;
+ return this;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/response/CommonReturnType.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/response/CommonReturnType.java
new file mode 100644
index 0000000..f6203fb
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/response/CommonReturnType.java
@@ -0,0 +1,75 @@
+package edu.heuet.shaohua.response;
+
+/**
+ * 此类是对Controller中方法返回值的通用封装
+ *
+ * @author littlecurl
+ */
+public class CommonReturnType {
+ // msg:
+ // success表示成功,返回 data 存储 viewobject
+ // fail表示失败,返回data存储通用的错误码格式
+ private int code;
+ private String msg;
+ // data: 正确信息viewobject或异常信息通用错误码或空
+ private Object data;
+
+ /*
+ 正常的流程返回值都是正确的,
+ 因此只需要传进viewobject对象即可,默认status为success
+
+ 对于异常流程,返回值为null
+ 在Controller层进行拦截并处理
+ */
+ public static CommonReturnType create(Object data) {
+ return CommonReturnType.create(0, "success", data);
+ }
+
+ public static CommonReturnType create(int code, String msg) {
+ CommonReturnType type = new CommonReturnType();
+ type.setCode(code);
+ type.setData(null);
+ type.setMsg(msg);
+ return type;
+ }
+
+ public static CommonReturnType create(Object data, String msg) {
+ CommonReturnType type = new CommonReturnType();
+ type.setCode(0);
+ type.setData(data);
+ type.setMsg(msg);
+ return type;
+ }
+
+ public static CommonReturnType create(int code, String msg, Object data) {
+ CommonReturnType type = new CommonReturnType();
+ type.setCode(code);
+ type.setData(data);
+ type.setMsg(msg);
+ return type;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ 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;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/response/OtpCode.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/response/OtpCode.java
new file mode 100644
index 0000000..0a995a1
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/response/OtpCode.java
@@ -0,0 +1,27 @@
+package edu.heuet.shaohua.response;
+
+public class OtpCode {
+ private String telphone;
+ private String otpCode;
+
+ public OtpCode(String telphone, String otpCode) {
+ this.telphone = telphone;
+ this.otpCode = otpCode;
+ }
+
+ public String getTelphone() {
+ return telphone;
+ }
+
+ public void setTelphone(String telphone) {
+ this.telphone = telphone;
+ }
+
+ public String getOtpCode() {
+ return otpCode;
+ }
+
+ public void setOtpCode(String otpCode) {
+ this.otpCode = otpCode;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/NewsService.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/NewsService.java
new file mode 100644
index 0000000..ec6b8ca
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/NewsService.java
@@ -0,0 +1,13 @@
+package edu.heuet.shaohua.service;
+
+import edu.heuet.shaohua.dataobject.NewsDO;
+
+import java.util.List;
+
+public interface NewsService {
+ NewsDO selectDetailById(long id);
+
+ List selectDetailByTitle(String title);
+
+ List selectAll();
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/UserService.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/UserService.java
new file mode 100644
index 0000000..1e9dce8
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/UserService.java
@@ -0,0 +1,21 @@
+package edu.heuet.shaohua.service;
+
+import edu.heuet.shaohua.error.BusinessException;
+import edu.heuet.shaohua.service.model.UserModel;
+
+/* 设计具体实现方法之前,先抽象为接口,是一种良好设计的表现 */
+public interface UserService {
+ /*
+ 返回值应该提供应有的所有属性
+ 而整合业务需求就是model层的工作
+ 因此返回值类型应该是model类型
+ */
+ public UserModel getUserById(Integer id);
+
+ /* 用户获取手机验证码时需要用到 */
+ public Boolean getUserByTelephone(String telephone);
+
+ void register(UserModel userModel) throws BusinessException;
+
+ UserModel validateLogin(String telphone, String encryptPassword) throws BusinessException;
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/impl/NewsServiceImpl.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/impl/NewsServiceImpl.java
new file mode 100644
index 0000000..99ce17c
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/impl/NewsServiceImpl.java
@@ -0,0 +1,30 @@
+package edu.heuet.shaohua.service.impl;
+
+import edu.heuet.shaohua.dao.NewsDOMapper;
+import edu.heuet.shaohua.dataobject.NewsDO;
+import edu.heuet.shaohua.service.NewsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class NewsServiceImpl implements NewsService {
+ @Autowired
+ NewsDOMapper newsDOMapper;
+
+ @Override
+ public NewsDO selectDetailById(long id) {
+ return newsDOMapper.selectByPrimaryKey(id);
+ }
+
+ @Override
+ public List selectDetailByTitle(String title) {
+ return newsDOMapper.selectByTitle(title);
+ }
+
+ @Override
+ public List selectAll() {
+ return newsDOMapper.selectAll();
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/impl/UserServiceImpl.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..4d60409
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/impl/UserServiceImpl.java
@@ -0,0 +1,218 @@
+package edu.heuet.shaohua.service.impl;
+
+import edu.heuet.shaohua.dao.UserDOMapper;
+import edu.heuet.shaohua.dao.UserPasswordDOMapper;
+import edu.heuet.shaohua.dataobject.UserDO;
+import edu.heuet.shaohua.dataobject.UserPasswordDO;
+import edu.heuet.shaohua.error.BusinessException;
+import edu.heuet.shaohua.error.EmBusinessError;
+import edu.heuet.shaohua.service.UserService;
+import edu.heuet.shaohua.service.model.UserModel;
+import edu.heuet.shaohua.validator.ValidationResult;
+import edu.heuet.shaohua.validator.ValidatorImpl;
+import org.apache.commons.lang3.StringUtils;
+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 org.springframework.transaction.interceptor.TransactionAspectSupport;
+
+/* @Service标注加在具体的Service实现类上 */
+@Service
+public class UserServiceImpl implements UserService {
+ /**
+ * Controller层接收View层传来的参数,
+ * 将参数转给Service层
+ * Service层再调用DAO层访问数据
+ * Service层再将DAO层返回给Controller层
+ * Controller层将Service层返回传递给View层
+ */
+ @Autowired
+ private UserDOMapper userDOMapper;
+
+ /**
+ * 每一个需要自动注入的对象都需要加@Autowired注解
+ */
+ @Autowired
+ private UserPasswordDOMapper userPasswordDOMapper;
+
+ @Autowired
+ private ValidatorImpl validator;
+
+ public UserServiceImpl() {
+ }
+
+
+ @Override
+ public UserModel getUserById(Integer id) {
+ /*
+ **************** 对返回值类型model的解释:****************
+ 在Service层持有DoMapper的对象,调用查询数据方法
+ 用UserDO接口对象接收
+ 因为dataobject层的UserDO属性与数据库字段一一对应
+ 有时候因为业务需要,一些字段并不在同一张表里
+ 导致对应的UserDO属性不全
+ 故不应该使用UserDO作为返回值传递给Controller
+ 而应该再建立一级model层,来整合业务需要的所有属性
+ */
+ UserDO userDO = userDOMapper.selectByPrimaryKey(id);
+ /* userDO的判空处理 */
+ if (userDO == null){ return null; }
+ /* 通过UserDO的id查询到关联表user_password中的关联数据 */
+ UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId());
+
+ /* 调用方法,整合UserDO和UserPasswordDO为userModel并返回给Controller */
+ return convertFromDataObject(userDO, userPasswordDO);
+ }
+
+ /**
+ * 用户获取验证码时,检测是否已存在注册用户
+ * @param telephone 用户手机号
+ * @return 是否存在当前手机号的用户
+ */
+ @Override
+ public Boolean getUserByTelephone(String telephone) {
+ UserDO userDO = userDOMapper.selectByTelephone(telephone);
+ if (userDO == null){
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /* 整合业务需要的所有属性为UserModel,这里为两张表的所有属性 */
+ private UserModel convertFromDataObject(UserDO userDO, UserPasswordDO userPasswordDO){
+ /* UserDO的判空处理 */
+ if (userDO == null){ return null; }
+ UserModel userModel = new UserModel();
+ /* 先把 userDO 中的数据复制给 userModel */
+ BeanUtils.copyProperties(userDO, userModel);
+ /* userPasswordDO的判空处理 */
+ if (userPasswordDO != null) {
+ /*
+ 已经复制过一遍了,如果再次进行复制,有可能出现id字段相同而值不同
+ 因此不能再次复制,只能通过setter方法进行设置
+ */
+ userModel.setEncryptPassword(userPasswordDO.getEncryptPassword());
+ }
+ // 将整合好的userModel返回
+ return userModel;
+ }
+
+ /**
+ * 用户注册服务的实现
+ * 加上@Transactional注解是为了避免出现用户信息插入不全,程序意外结束
+ *
+ * @param userModel 用户信息
+ */
+ @Override
+ @Transactional
+ public void register(UserModel userModel) throws BusinessException{
+ // 先进行整体判空处理,这样代码才健壮一些
+ if (userModel == null){
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
+ }
+
+ // 优化后的model校验
+ ValidationResult result = validator.validate(userModel);
+ if (result.isHasError()){
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, result.getErrMsg());
+ }
+
+ // model ---> dataobject:UserDO
+ // 之所以使用insertSelective方法,这样可以避免使用null字段,而使用设计数据库时的默认值
+ UserDO userDO = convertFromModel(userModel);
+ try {
+ userDOMapper.insertSelective(userDO);
+ }catch (DuplicateKeyException ex){
+ // 手动回滚事务
+ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"手机号已重复注册");
+ }
+ /*
+ 一旦insertSelective成功,user表的id就会自增(这需要去UserDOMapper.xml文件中设置id为主键自增)
+ 这时候就可以通过userDo进行get了
+ 将get到的id赋值给userModel,并传递给convertPasswoedFromModel方法
+ */
+ userModel.setId(userDO.getId());
+
+ // model ---> dataobject:UserPasswordDO
+ UserPasswordDO userPasswordDO = convertPasswordFromModel(userModel);
+ userPasswordDOMapper.insertSelective(userPasswordDO);
+ }
+
+ /**
+ * 实现model ---> dataobject:UserDO
+ *
+ * @param userModel Model
+ * @return UserDO
+ */
+ private UserDO convertFromModel(UserModel userModel){
+ // 每一层都进行判空,这样代码才处处健壮
+ if(userModel == null){
+ return null;
+ }
+ UserDO userDO = new UserDO();
+ // source是userModel,target是userDO,
+ // 这样在copy过程中,userModel中多余的属性会被自动丢弃
+ BeanUtils.copyProperties(userModel, userDO);
+
+ return userDO;
+ }
+
+ /**
+ * 实现model ---> dataobject:UserDO
+ *
+ * @param userModel Model
+ * @return UserDO
+ */
+ private UserPasswordDO convertPasswordFromModel(UserModel userModel){
+ if (userModel == null){
+ return null;
+ }
+ UserPasswordDO userPasswordDO = new UserPasswordDO();
+ /*
+ 对于userPasswordDO,我们不能像userDO那样进行copy
+ 因为我们在整合DO为model时,id是从userDO那里copy过来的,
+ 强行copy会导致user_password表中id不一致
+ 还有一点是,应该现有userDO中的属性,才会有userPasswordDO中的属性
+ 所以这里的userPasswordDO的id属性不需要设置,自动递增即可
+ */
+ userPasswordDO.setEncryptPassword(userModel.getEncryptPassword());
+ /*
+ user_password表总共三个字段,id不用我们管,可不要漏掉user_id字段
+ 否则无法根据外键进行查询密码了
+ 之所以userModel可以getId,在register方法中有提到
+ */
+ userPasswordDO.setUserId(userModel.getId());
+ return userPasswordDO;
+ }
+
+ /**
+ * 用户登录服务的实现
+ *
+ * @param telphone 手机号
+ * @param encryptPassword 加密密码
+ * @return 用户Model
+ */
+ @Override
+ public UserModel validateLogin(String telphone, String encryptPassword) throws BusinessException {
+ // 通过用户的手机获取用户信息
+ /* 这里的selectByTelphone是我们在UserDOMapper.xml中手动实现的 */
+ UserDO userDO = userDOMapper.selectByTelephone(telphone);
+ if (userDO == null){
+ throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL);
+ }
+ UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId());
+ UserModel userModel = convertFromDataObject(userDO, userPasswordDO);
+
+ // 比对用户信息内加密的面是否和传输进来的密码相匹配
+ if (!StringUtils.equals(encryptPassword,userModel.getEncryptPassword())){
+ throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"用户名或密码错误");
+ }
+ return userModel;
+ }
+
+
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/model/UserModel.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/model/UserModel.java
new file mode 100644
index 0000000..860851f
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/service/model/UserModel.java
@@ -0,0 +1,93 @@
+package edu.heuet.shaohua.service.model;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 因为业务需要,有些字段并不能在同一张表里
+ * model层就是整合业务需要的所有字段
+ */
+public class UserModel {
+ private Integer id;
+ @NotBlank(message = "用户名不能为空")
+ private String name;
+ @NotNull(message = "必须填写性别")
+ private Byte gender;
+ @NotNull(message = "必须填写年龄")
+ @Min(value = 0, message = "年龄必须大于0")
+ @Max(value = 150, message = "年龄必须小于150")
+ private Integer age;
+ @NotNull(message = "手机号不能为空")
+ private String telephone;
+ private String registerMode;
+ private String thirdPartId;
+ /* 整合加密后的密码字段 */
+ @NotNull(message = "密码不能为空")
+ private String encryptPassword;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Byte getGender() {
+ return gender;
+ }
+
+ public void setGender(Byte gender) {
+ this.gender = gender;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+
+ public String getRegisterMode() {
+ return registerMode;
+ }
+
+ public void setRegisterMode(String registerMode) {
+ this.registerMode = registerMode;
+ }
+
+ public String getThirdPartId() {
+ return thirdPartId;
+ }
+
+ public void setThirdPartId(String thirdPartId) {
+ this.thirdPartId = thirdPartId;
+ }
+
+ public String getEncryptPassword() {
+ return encryptPassword;
+ }
+
+ public void setEncryptPassword(String encryptPassword) {
+ this.encryptPassword = encryptPassword;
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/util/CommonUtil.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/util/CommonUtil.java
new file mode 100644
index 0000000..9e34200
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/util/CommonUtil.java
@@ -0,0 +1,17 @@
+package edu.heuet.shaohua.util;
+
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.FieldError;
+
+public class CommonUtil {
+ public static String processErrorString(BindingResult bindingResult) {
+ if (!bindingResult.hasErrors()) {
+ return "";
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ for (FieldError fieldError : bindingResult.getFieldErrors()) {
+ stringBuilder.append(fieldError.getDefaultMessage()).append(",");
+ }
+ return stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/validator/ValidationResult.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/validator/ValidationResult.java
new file mode 100644
index 0000000..7783e5b
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/validator/ValidationResult.java
@@ -0,0 +1,32 @@
+package edu.heuet.shaohua.validator;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ValidationResult {
+ private boolean hasError = false;
+
+ private Map errorMsgMap = new HashMap<>();
+
+ public boolean isHasError() {
+ return hasError;
+ }
+
+ public void setHasError(boolean hasError) {
+ this.hasError = hasError;
+ }
+
+ public Map getErrorMsgMap() {
+ return errorMsgMap;
+ }
+
+ public void setErrorMsgMap(Map errorMsgMap) {
+ this.errorMsgMap = errorMsgMap;
+ }
+
+ public String getErrMsg() {
+ return StringUtils.join(errorMsgMap.values().toArray(), ",");
+ }
+}
diff --git a/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/validator/ValidatorImpl.java b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/validator/ValidatorImpl.java
new file mode 100644
index 0000000..9c75a60
--- /dev/null
+++ b/AndroidDatabaseDemo/LoginBackEnd/src/main/java/edu/heuet/shaohua/validator/ValidatorImpl.java
@@ -0,0 +1,33 @@
+package edu.heuet.shaohua.validator;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.stereotype.Component;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import java.util.Set;
+@Component
+public class ValidatorImpl implements InitializingBean {
+
+ private Validator validator;
+
+ public ValidationResult validate(Object bean){
+ final ValidationResult result = new ValidationResult();
+ Set< ConstraintViolation