学习笔记-Spring Boot 开发 RESTful Web API(二)

题记:

上一篇我们讲解了Spring Boot开发RESTful API的基础知识,本篇将继续这方面的学习,通过一个样例来展示使用Spring Boot开发RESTful Web API,另外,本篇还使用MyBatis来访问数据库数据。

 

一、使用MyBatis

1、什么是 MyBatis ?

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

2、引入MyBatis依赖

MyBatis的最新版是3.4.6,Spring Boot 通过mybatis-spring-boot-starter整合了MyBatis,我们这里使用mybatis-spring-boot-starter的1.3.2版本。

需要在POM.xml中添加依赖:

        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        

完成后,即可通过 mybatis-spring-boot-starter 使用MyBatis了。

附录:本文使用样例的pom.xml配置(其他配置项全部使用工程创建时的默认配置,仅需要在依赖中添加如下配置项即可):

        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        
 
        
        
            mysql
            mysql-connector-java
        

3、数据库配置

在/web-api/src/main/resources/application.properties中,添加如下配置:

## 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

 

二、统一返回值

新建package utils,在该package中构建返回值类,来统一返回格式

package com.example.demo.utils;

/**
 * 默认响应
 * 
 * @author light
 *
 */
public class ResponseMsg {
    /**
     * 返回结果
     */
    private boolean result;

    /**
     * 错误码
     */
    private int code = 0;

    /**
     * 错误描述
     */
    private String description = "";

    /**
     * 数据
     */
    private T data = null;

    public ResponseMsg(boolean result, int code, String description) {
        this.result = result;
        this.code = code;
        this.description = description;
        this.data = null;
    }

    public ResponseMsg(boolean result, int code, String description, T data) {
        this.result = result;
        this.code = code;
        this.description = description;
        this.data = data;
    }

    public boolean isResult() {
        return result;
    }

    public void setResult(boolean result) {
        this.result = result;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

 

三、在domain中添加实体

添加User实体,具体类如下:

package com.example.demo.domain;

/**
 * 用户实体类
 * 
 * @author light
 *
 */
public class User {
    /**
     * 用户id
     * */
    private int id;
    
    /** 
     * 姓名 
     * */
    private String name; 
    
    /** 
     * 年龄 
     * */
    private int age;

    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("[userid=");
        sb.append(id);
        sb.append(",username=");
        sb.append(name);
        sb.append(",userage=");
        sb.append(age);
        sb.append("]");
        return sb.toString();
    }
}

 

四、在repository中添加数据访问类

这里的数据库访问实体,其实就是我们通常开发使用的dao层,具体类如下:

package com.example.demo.repository;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.example.demo.domain.User;

/**
 * 用户访问数据
 * 
 * @author light
 *
 */
@Mapper
public interface UserRepository {

    /**
     * 获取全部用户信息
     * 
     * @return
     */
    @Select("select * from t_user1")
    @Results({ 
        @Result(property = "id", column = "id"), 
        @Result(property = "name", column = "name"),
        @Result(property = "age", column = "age") })
    List queryAll();

    /**
     * 用户数据新增
     */
    @Insert("insert into t_user1(id,name,age) values (#{id},#{name},#{age})")
    void addUser(User user);

    /**
     * 用户数据修改
     */
    @Update("update t_user1 set name=#{name},age=#{age} where id=#{id}")
    void updateUser(User user);

    /**
     * 用户数据删除
     */
    @Delete("delete from t_user1 where id=#{id}")
    void deleteUser(int id);

    /**
     * 根据用户ID查询用户信息
     *
     */
    @Select("SELECT id,name,age FROM t_user1 where id=#{userId}")
    @Results({ 
        @Result(property = "id", column = "id"), 
        @Result(property = "name", column = "name"),
        @Result(property = "age", column = "age") })
    User findById(@Param("userId") int userId);

}

 

@Param("id"):全局限定别名,定义查询参数在sql语句中的位置不再是顺序下标0,1,2,3......的形式,而是对应名称,该名称在此处定义。

@Results是以@Result为元素的数组,@Result表示单条属性——字段的映射关系,id = true表示该id字段是主键,查询时mybatis会给予必要的优化。数组中所有的@Result组成了单个记录的映射关系,而@Results则是单个记录的集合。另外,还有一个非常重要的注解@ResultMap,其与@Results类似

@Select("查询语句")、@Insert("增加语句")、@Update("更新语句")和@Delete("删除语句")表示对数据进行查询、添加、更新和删除的操作。

 

五、添加service实现

1、添加UserService

package com.example.demo.service;

import com.example.demo.domain.User;
import com.example.demo.utils.ResponseMsg;

/**
 * UserService 接口
 * 
 * @author light
 *
 */
public interface UserService {

    /**
     * 获取所有用户列表
     * 
     * @return
     */
    ResponseMsg getUsers();

    /**
     * 新增用户
     * 
     * @param user
     * @return
     */
    ResponseMsg addUser(User user);

    /**
     * 修改用户
     * 
     * @param user
     * @return
     */
    ResponseMsg updateUser(User user);

    /**
     * 删除用户
     * 
     * @param id
     * @return
     */
    ResponseMsg deleteUser(int id);

    /**
     * 根据用户ID查询用户信息
     * 
     * @param userId
     */
    ResponseMsg findUserById(int userId);
}

2、添加UserService的实现

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.domain.User;
import com.example.demo.repository.UserRepository;
import com.example.demo.utils.EmptyData;
import com.example.demo.utils.ResponseMsg;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepo;

    @Override
    public ResponseMsg getUsers() {
        ResponseMsg> res = new ResponseMsg>(true, 0, "");
        try {
            List users = userRepo.queryAll();
            if (null != users && users.size() > 0) {
                res.setData(users);
            } else {
                res.setCode(2);
                res.setDescription("no user is existed!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            res.setResult(false);
            res.setCode(10000);
            res.setDescription("Exception ");
        }

        return res;
    }

    @Override
    public ResponseMsg addUser(User user) {
        ResponseMsg res = new ResponseMsg(true, 0, "", new EmptyData());
        try {
            userRepo.addUser(user);
        } catch (Exception e) {
            e.printStackTrace();
            res.setResult(false);
            res.setCode(10000);
            res.setDescription("Exception ");
        }

        return res;
    }

    @Override
    public ResponseMsg updateUser(User user) {
        ResponseMsg res = new ResponseMsg(true, 0, "", new EmptyData());
        try {
            userRepo.updateUser(user);
        } catch (Exception e) {
            e.printStackTrace();
            res.setResult(false);
            res.setCode(10000);
            res.setDescription("Exception ");
        }

        return res;
    }

    @Override
    public ResponseMsg deleteUser(int id) {
        ResponseMsg res = new ResponseMsg(true, 0, "", new EmptyData());
        try {
            userRepo.deleteUser(id);
        } catch (Exception e) {
            e.printStackTrace();
            res.setResult(false);
            res.setCode(10000);
            res.setDescription("Exception ");
        }

        return res;
    }

    @Override
    public ResponseMsg findUserById(int userId) {
        try {
            User user = userRepo.findById(userId);
            if (null != user) {
                System.out.println("find user with " + userId + ", return user: " + user.toString());
                return new ResponseMsg(true, 0, "", user);
            } else {
                return new ResponseMsg(false, 1, "User does not exists!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseMsg(false, 1000, "Exception !!");
        }
    }
}


六、添加controller层实现

本例实现接口将通过统一路径的方式访问,形如:{ip}:{port}/api/user/{path}。

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
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 com.example.demo.domain.User;
import com.example.demo.service.UserService;
import com.example.demo.utils.ResponseMsg;

/**
 * API接口核心控制层
 * 
 * @author light
 *
 */
@RestController
@RequestMapping(value = "/api/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 获取全部用户信息
     * 
     * @return
     */
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public ResponseMsg queryAll() {
        System.out.println("开始查询全部用户");
        return userService.getUsers();
    }

    /**
     * 特别说明:在POST请求的BODY中传送参数,务必加上@RequestBody注解
     * 
     * @param user
     * @return
     */
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public ResponseMsg addUser(@RequestBody User user) {
        System.out.println("开始新增... user:" + user.toString());
        return userService.addUser(user);
    }

    /**
     * 特别说明:在PUT请求的BODY中传送参数,务必加上@RequestBody注解
     * 
     * @param user
     * @return
     */
    @RequestMapping(value = "/updateUser", method = RequestMethod.PUT)
    public ResponseMsg updateUser(@RequestBody User user) {
        System.out.println("开始更新...user:" + user.toString());
        return userService.updateUser(user);
    }

    @RequestMapping(value = "/deleteUser", method = RequestMethod.DELETE)
    public ResponseMsg delete(@RequestParam(value = "userId", required = true) int userId) {
        System.out.println("开始删除..., userid=" + userId);
        return userService.deleteUser(userId);
    }

    @RequestMapping(value = "/userId", method = RequestMethod.GET)
    public ResponseMsg findByUserId(@RequestParam(value = "userId", required = true) int userId) {
        System.out.println("开始查询..., userid=" + userId);
        return userService.findUserById(userId);
    }

}


七、运行验证

运行验证较为简单,可以使用Postman工具进行验证,较为简单,这里就不列出来了。

 

总结:
使用Spring Boot 开发 Web API 接口,是当前微服务开发模式下最为流程的开发方式,目前公司各个新的业务模块,特别是针对APP的模块已经全面切换到Spring Boot 进行 Web API 开发了。当然了,仅仅提供接口不足以支撑商业应用,基于Spring Boot 的开发还有很多的配套设施要做,后续将逐步展开。


参考:
http://www.mybatis.org/mybatis-3/zh/index.html

https://blog.csdn.net/gebitan505/article/details/54929287

https://blog.csdn.net/travellersy/article/details/78620247

 

你可能感兴趣的:(程序设计,软件工程-服务端,软件设计,Spring,Boot,MyBatis,WebApi)