创建数据库和准备用户表

  1. CREATE TABLE `user` (
  2. `id` int(8) NOT NULL AUTO_INCREMENT,
  3. `name` varchar(20) NOT NULL,
  4. `password` varchar(255) NOT NULL,
  5. PRIMARY KEY (`id`),
  6. UNIQUE KEY `user_name_uindex` (`name`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  8. insert into user values("111","gate","bill");

添加 fastjson 依赖 和 spring boot dev tool 依赖

打开 pom.xml, 在 dependencies 节点下面添加

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.22</version>
  5. </dependency>
  6. <!--mybatis-plus依赖-->
  7. <dependency>
  8. <groupId>com.baomidou</groupId>
  9. <artifactId>mybatis-plus-boot-starter</artifactId>
  10. <version>3.2.0</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-devtools</artifactId>
  15. </dependency>

编写UserDo.java

目前 User 只有 idnamepassword 三个属性

  1. @Alias(value="UserDo")
  2. public class UserDo {
  3. private Integer id;
  4. private String name;
  5. private String password;
  6. // 下面是 getter 和 setter 方法。。。
  7. }

注意 id 用 Integer 而不用 int, 因为 int 自动初始化为0,mybatis mapper 文件 就不能使用 了,而 Integer 可以为 null

编写 UserApi.java

  1. @RestController
  2. @RequestMapping("/api/user")
  3. public class MysqlController {
  4. private UserServices userService;
  5. @Autowired
  6. public MysqlController(UserServices userService) {
  7. this.userService = userService;
  8. }
  9. @GetMapping("/")
  10. public Object add() {
  11. UserDo user = new UserDo();
  12. user.setName("11");
  13. user.setPassword("111");
  14. user.setId(1);
  15. if (userService.findByName(user.getName()) != null) {
  16. JSONObject jsonObject = new JSONObject();
  17. jsonObject.put("message","用户名已被使用");
  18. return jsonObject;
  19. }
  20. return userService.add(user);
  21. }
  22. }

api这一层主要是调用service层的方法, 返回JSON数据。我用 @RestController 代替了 @Controller,表示该类里面的方法都是返回 JSON 数据, 而不用再给每个方法添加@ResponseBody注解。add 方法 @PostMapping("") 对应的路由为

  1. POST /api/user

编写 UserServices.java

  1. @Service
  2. public class UserServices {
  3. private UserMappers userMapper;
  4. @Autowired
  5. public UserServices(UserMappers userMapper) {
  6. this.userMapper = userMapper;
  7. }
  8. public UserDo add(UserDo user) {
  9. userMapper.add(user);
  10. return findById(user.getId());
  11. }
  12. public UserDo findById(int id) {
  13. UserDo user = new UserDo();
  14. user.setId(id);
  15. return userMapper.findOne(user);
  16. }
  17. public UserDo findByName(String name) {
  18. UserDo param = new UserDo();
  19. param.setName(name);
  20. return userMapper.findOne(param);
  21. }
  22. }

service这一层处理主要的业务逻辑,比如说添加用户, api层传过来了一个 user对象, 具体怎么添加在这里处理。目前逻辑比较简单,直接调用mapper层的方法,保存到数据库即可。

编写 UserMappers.java

  1. @Repository
  2. public interface UserMappers {
  3. int add(UserDo user);
  4. UserDo findOne(UserDo user);
  5. }

一个添加接口和一个查询接口

编写 UserMappers.xml

  • 注意替换com.hpm.blog.mapper.UserMappers
  • 注意resultType要填写全路径 ```xml <?xml version=”1.0” encoding=”UTF-8” ?> <!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd“ >

    insert into user(name, password) values (#{name},#{password})

  1. `insert` 标签中的 `useGeneratedKeys` 作用是获取由数据库生成的`id`,注意`mapper xml`文件要和`mapper java`文件同名, 并且包名一致,不同的是xml文件要放在 resource目录之下。xml文件所在的包是一个多级目录结构,要建完一个目录再建另外一个,不能一下子新建一个名为`xxx.yyy.zzz`的目录。到这里, 我们的代码基本写完了。
  2. <a name="7m0abt"></a>
  3. ### 编写`Mybatis`配置文件
  4. 1. resource目录下面新建一个名为`mybatis.xml` 的文件
  5. ```xml
  6. <?xml version="1.0" encoding="UTF-8"?>
  7. <!DOCTYPE configuration
  8. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  9. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  10. <configuration>
  11. <settings>
  12. <!-- 开启驼峰命名转换 Table(create_time) -> Entity(createTime) -->
  13. <setting name="mapUnderscoreToCamelCase" value="true"/>
  14. </settings>
  15. </configuration>
  1. 打开application.yml文件, 添加以下内容
  • 注意替换com.hpm.blog.model
    1. mybatis:
    2. config-location: classpath:mybatis.xml
    3. mapper-locations: classpath:mapper/*.xml

type-aliases-package, 根据你的包结构修改为UserDo.java文件所在的包

  1. 使spring boot扫描 mapper文件。打开SpringBootBlogApplication.java, 添加mybatis扫描注解,参数为mapper文件所在的包名
  • 注意替换com.hpm.blog.mapper
    1. @MapperScan("com.hpm.blog.mapper")

SpringBootBlogApplication.java内容最终如下

  1. @SpringBootApplication
  2. @MapperScan("com.hpm.blog.mapper")
  3. public class SpringBootBlogApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(SpringBootBlogApplication.class, args);
  6. }
  7. }

测试访问接口

代码编写完毕,接下来运行项目,添加一个用户试试。下面使用curl发起一个POST请求。(如果你用的是Windows系统,没有curl这个命令,那么我推荐你安装一个git客户端,用软件带的git bash代替 cmd,将拥有Linux系统下面的包括curl在内的很多有用的命令)。

  1. curl -X POST -H "Content-Type: application/json" -d '{"name": "xiaohong","password": "123456"}' "http://localhost:8080/api/user/"

windows系统下 curl 不能用单引号,要用双引号转义

  1. curl -X POST -H "Content-Type: application/json" -d "{\"name\": \"xiaohong\",\"password\": \"123456\"}" "http://localhost:8080/api/user/"

得到如下输出,添加用户成功。

  1. {"id":10,"name":"xiaohong","password":"123456"}

使用 hash 来保存用户密码

目前为止,数据库中的用户密码还是原文存储的,很不安全,改用 hash 值来存储用户密码。哈希算法很多种,以下使用 SHA-256
打开 UserServices.java 文件

  1. 修改 add 方法
  1. public User add(User user) {
  2. String passwordHash = passwordToHash(user.getPassword());
  3. user.setPassword(passwordHash);
  4. userMapper.add(user);
  5. return findById(user.getId());
  6. }
  1. 添加 passwordToHash 方法
  1. private String passwordToHash(String password) {
  2. try {
  3. MessageDigest digest = MessageDigest.getInstance("SHA-256");
  4. digest.update(password.getBytes());
  5. byte[] src = digest.digest();
  6. StringBuilder stringBuilder = new StringBuilder();
  7. // 字节数组转16进制字符串
  8. // https://my.oschina.net/u/347386/blog/182717
  9. for (byte aSrc : src) {
  10. String s = Integer.toHexString(aSrc & 0xFF);
  11. if (s.length() < 2) {
  12. stringBuilder.append('0');
  13. }
  14. stringBuilder.append(s);
  15. }
  16. return stringBuilder.toString();
  17. } catch (NoSuchAlgorithmException ignore) {
  18. }
  19. return null;
  20. }

重启服务器,再测试一下

  1. curl -X POST -H "Content-Type: application/json" -d "{\"name\": \"xiaoming\",\"password\": \"123456\"}" "http://localhost:8080/api/user/"

输出:

  1. {"id":11,"name":"xiaoming","password":"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92"}

好了,密码已经由原文存储变为hash存储了。

查看项目完整代码

项目地址: https://github.com/hyrijk/spring-boot-blog
克隆项目到本地

  1. git clone https://github.com/hyrijk/spring-boot-blog.git

checkout 到当前版本

  1. git checkout 324933e88dbf22368b8cc250c57f895fd836e0d8

常见问题

  • 可能碰到:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): xiaomingappV1.mapper.UserMapper.findOne问题。
    • 看是不是有冲突,路径是否一致.
  • Unknown system variable ‘query_cache_size’
    • mybatis connection的驱动版本太低不行,更新即可.
  • Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
    • 添加 driver-class-name: com.mysql.cj.jdbc.Driver
      1. spring:
      2. datasource:
      3. driver-class-name: com.mysql.cj.jdbc.Driver

如果报错一堆不知道如何解决

参考资料