上次我们讲到前后端开发的时候要以RESTFul风格的API进行开发,这样减少了前后端交流的口舌,所以我们就来实战一下,写一个以RESTFul风格的开发的API
一、前提准备
- IEDA
- Mysql-8.0.18
- Navigator
二、数据库的建立
首先建立一个叫做RESTFulDemo的数据库,然后在数据库里面建立一个叫做demo_user的表,表的结构如下:
然后导入我事先准备好的数据,这样就有了数据了
然后建立一个叫做data的表(这个表的名字没有什么逻辑,只是为了此次写API所写的demo),并导入我事前准备的数据
三、代码编写
- 首先我们需要连接到数据库,所以加上相关的pom依赖
<!--jdbcTemplate支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--添加lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
- 然后再application.properties里添加数据库配置
# 添加的数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/restfuldemo?useUnicode=true&characterEncoding=utf-8serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=XXXXXX
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
其中XXXXXX指的是你的密码
- 然后写相关的实体类,与数据库表相对应
ChartData.java
package com.example.demo.Model;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class ChartData {
private String name;//电视台名称
private String price;//广告价格
}
demoUser.java
package com.example.demo.Model;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class demoUser {
private String id;//id号
private String name;//姓名
private Integer age;//年龄
private String qq;//qq
private String address;//地址
private String Email;//电子邮件
}
- 然后编写Dao层接口
IDemoUserDao.java
package com.example.demo.Dao;
import com.example.demo.Model.demoUser;
import java.util.*;
/** * demoUserDao的接口 */
public interface IDemoUserDao {
int add(demoUser user);//增加一个demoUser对象
int delete(demoUser user);//删除一个demoUser对象
int update(demoUser user);//修改
demoUser findOne(String id);//查找到一个
List<demoUser> findAll();//找到所有的demoUser对象
}
由于我此时想测试数据库是不是能够连接成功,于是在pom依赖里面添加了Junit测试starter
<!--添加junit测试依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
然后我们实现IDemoUserDao这个接口并实现其中的add功能
DemoUserDao.java
package com.example.demo.Dao.Impl;
import com.example.demo.Dao.IDemoUserDao;
import com.example.demo.Model.demoUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Repository
public class DemoUserDao implements IDemoUserDao {
@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
@Override
public int add(demoUser user){
String sql = "insert into demo_user(id,name,age,qq,address,email) "
+ "values(:id,:name,:age,:qq,:address,:email)";
Map<String,Object> param = new HashMap<>();
param.put("id",user.getId());
param.put("name",user.getName());
param.put("age",user.getAge());
param.put("qq",user.getQq());
param.put("address",user.getAddress());
param.put("email",user.getEmail());
return (int) jdbcTemplate.update(sql,param);
}
@Override
public int delete(demoUser user){
return 0;
}
@Override
public int update(demoUser user){
return 0;
}
@Override
public demoUser findOne(String id){
return null;
}
@Override
public List<demoUser> findAll(){
return null;
}
}
然后就要生成我们的测试类,至于idea里如何生成测试类,还请读者自行百度。在DemoUser.java文件里面按住ctrl+shift+t弹出创建测试类的窗口,然后勾选你需要测试的方法。
测试类编写如下:
package com.example.demo.Dao.Impl;
import com.example.demo.DemoApplication;
import com.example.demo.Model.demoUser;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.jupiter.api.Assertions.*;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
class DemoUserDaoTest {
@Autowired
private DemoUserDao userDao;
@Test
void add() {
demoUser user = new demoUser();
user.setId("7988256100");
user.setName("张三娘");
user.setAge(18);
user.setQq("8008208820");
user.setAddress("北京市朝阳区世纪东方城125栋5单元3103室");
user.setEmail("8008208820@qq.com");
System.out.println(userDao==null);
userDao.add(user);
System.out.println("插入成功,返回");
}
}
之后运行测试类,发现数据库有了这条数据,并返回
然后数据库也有了这条数据
这说明我们的数据库连接是正常的,接下来我们就要实现其他的代码了
4.当我们的DAO层写好之后我们开始写我们的Service层
部分代码如下:
package com.example.demo.Service;
import com.example.demo.Dao.Impl.DemoUserDao;
import com.example.demo.Model.demoUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private DemoUserDao userDao;
public int add(demoUser user){
return userDao.add(user);
}
public int delete(demoUser user){
return userDao.delete(user);
}
public int update(demoUser user){
return userDao.update(user);
}
public demoUser findOne(String id){
return userDao.findOne(id);
}
public List<demoUser> findAll(){
return userDao.findAll();
}
}
- 然后我们要开始写我们的RESTFul接口的,在写RESTFul接口之前,我们得写一个AjaxResponse的Model
AjaxResponse.java
package com.example.demo.Model;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class AjaxResponse {
private boolean isOk;
private int code;
private String message;
private Object data;
/** * 当调用成功不返回数据 * @return */
public static AjaxResponse success(){
AjaxResponse resultBean = new AjaxResponse();
resultBean.setOk(true);
resultBean.setCode(200);
resultBean.setMessage("success");
return resultBean;
}
/** * 当调用成功返回数据 * @param data * @return */
public static AjaxResponse success(Object data){
AjaxResponse resultBean = new AjaxResponse();
resultBean.setOk(true);
resultBean.setCode(200);
resultBean.setMessage("success");
resultBean.setData(data);
return resultBean;
}
/** * 当调用失败时 * @return */
public static AjaxResponse fail(){
AjaxResponse resultBean = new AjaxResponse();
resultBean.setOk(false);
resultBean.setCode(400);
resultBean.setMessage("failed");
return resultBean;
}
}
为什么要写这样的一个实体呢,其实写这个实体是为了前端调用我们的接口的时候,当成功调用和失败调用能够以此返回相应的数据
- 然后编写相应的contorller类
UserRestController.java
package com.example.demo.Controller;
import com.example.demo.Model.AjaxResponse;
import com.example.demo.Model.demoUser;
import com.example.demo.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static org.springframework.web.bind.annotation.RequestMethod.*;
@RestController
@RequestMapping("/api")
public class UserRestController {
@Autowired
private UserService userService;
@RequestMapping(value="/users",method = POST,produces = "application/json")
public AjaxResponse addUser(@RequestBody demoUser user){
if(userService.add(user)==1){
return AjaxResponse.success();
}else{
return AjaxResponse.fail();
}
}
@RequestMapping(value="/users/{id}",method = DELETE,produces="application/json")
public AjaxResponse deleteUser(@PathVariable String id){
demoUser user = new demoUser();
user.setId(id);
if(userService.delete(user)==1){
return AjaxResponse.success();
}else{
return AjaxResponse.fail();
}
}
@RequestMapping(value="/users/{id}/{name}",method = PUT,produces="application/json")
public AjaxResponse updateUser(@PathVariable String id,@PathVariable String name,@RequestBody demoUser user){
user.setId(id);
user.setName(name);
if(userService.update(user)==1){
return AjaxResponse.success();
}else{
return AjaxResponse.fail();
}
}
@RequestMapping(value="/users/{id}",method = GET,produces="application/json")
public AjaxResponse getOneUser(@PathVariable String id){
demoUser user;
user = userService.findOne(id);
if(user!=null){
return AjaxResponse.success(user);
}else{
return AjaxResponse.fail();
}
}
@RequestMapping(value="/users",method = GET,produces="application/json")
public AjaxResponse getAllUser(){
List<demoUser> userList;
userList = userService.findAll();
if(userList!=null){
return AjaxResponse.success(userList);
}else{
return AjaxResponse.fail();
}
}
}
- 写完了controller之后,我们启动项目并用postman这个工具来做接口测试,至于postman工具如何安装并使用请读者自行百度。
当我们在postman发送一个GET请求的时候,请求的路径为http://localhost:8080/api/users,这个请求的路径其实就是获取所有用户的信息。
当我们将请求的路径后面加上用户的id的时候就能够获取到id为这个的用户的信息了
三、使用Swagger2构建API发布文档
其实写到前面那里,我们的RESTFul风格的接口就已经写好了。现在我们想一下,我们后端写的接口是要提供给前端使用的,所以前端需要后端接口的API文档,众所周知,程序员讨厌写文档,所以就出现了Swagger2这样的一个API文档自动生成的工具,而且能够实时更新
- 首先添加相关的pom依赖
<!--Swagger2的依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
- 然后新建一个叫做config的包,在包里新建swagger2.java文件
Swagger2.java
package com.example.demo.Config;
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.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.example.demo"))
.paths(PathSelectors.regex("/api/.*"))
.build();
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("SpringBoot利用swagger构建api文档")
.description("简单优雅的RESTFul风格")
.termsOfServiceUrl("http://www.example.com")
.version("1.0")
.build();
}
}
然后运行项目,访问http://localhost:8080/swagger-ui.html就会显示下面的样子
以上就是这次要讲的全部内容,源代码已经上传至Gitee(码云),有需要的小伙伴可以自行下载