美文网首页
前后端分离传值方案-RestfulAPI

前后端分离传值方案-RestfulAPI

作者: Xia0JinZi | 来源:发表于2018-01-11 18:33 被阅读0次

SpringBoot结合Swagger展示Restful API

标签(空格分隔): springboot java springmvc jpa


镇楼

Restful API 搭建

RESTful架构,是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。后端通过提供一套标准的RESTful API,让网站,移动端和第三方系统都可以基于API进行数据交互和对接,极大的提高系统的开发效率,也使得前后端分离架构成为可能。

SpringBoot开发RestfulAPI

maven 3.3.9 ,Mysql 5.7.19,编译器采用idea,本示例实现学生信息的增删改查

  • 数据库表结构设计
CREATE TABLE `stu_information` (
  `stu_id` varchar(100) NOT NULL COMMENT '学生id',
  `stu_name` varchar(10) NOT NULL COMMENT '学生姓名',
  `stu_sex` int(11) NOT NULL COMMENT '学生性别,0表示男,1表示女',
  `stu_age` int(11) NOT NULL COMMENT '学生年龄',
  `stu_magor` varchar(100) NOT NULL COMMENT '专业',
  `stu_grade` int(11) NOT NULL COMMENT '年级',
  `stu_department` varchar(100) NOT NULL COMMENT '院系',
  `stu_class` varchar(100) NOT NULL COMMENT '班级',
  PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生信息表';
  • 项目创建(这个就不多讲解了),添加依赖
<!--数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!--jpa-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!--lombok 插件-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

  • 配置文件设置
server:
  port: 8088
  context-path: /student

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://127.0.0.1:3306/stu_api?characterEncoding=utf-8&useSSL=false
  jpa:
    show-sql: true
  • Api封装
<!--呈现内容-->
@Data
public class ResultVo<T> {

    /** 状态码 .*/
    private Integer code;

    /** 消息 .*/
    private String msg;

    /** 具体值 .*/
    private T data;

}

<!--返回结果工具-->
public class ResultVoUtil {

    /**
     * 成功返回有值
     * @param object
     * @return
     */
    public static ResultVo success(Object object){
        ResultVo resultVo = new ResultVo();
        resultVo.setCode(ResultEnum.SUCCESS.getCode());
        resultVo.setMsg(ResultEnum.SUCCESS.getMessage());
        resultVo.setData(object);
        return resultVo;
    }

    /**
     * 无值成功返回
     * @return
     */
    public static ResultVo success(){
       return success(null);
    }

    /**
     * 错误返回
     * @param resultEnum
     * @return
     */
    public static ResultVo error(ResultEnum resultEnum){
        ResultVo resultVo =  new ResultVo();
        resultVo.setCode(resultEnum.getCode());
        resultVo.setMsg(resultEnum.getMessage());
        return resultVo;
    }
}
  • 返回结果枚举
@Getter
public enum ResultEnum {
    SUCCESS(0,"成功"),
    LIST_SAVE_ERROR(10,"批量存储出错"),
    PARAM_ERROR_ADD(20,"添加学生信息错误")
    ;

    private Integer code;

    private String message;

    ResultEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}
  • 异常处理
public class StuInformationException extends RuntimeException{

    private Integer code;

    public StuInformationException(ResultEnum resultEnum) {
        super(resultEnum.getMessage());
        this.code = resultEnum.getCode();
    }
}
  • 主键生成工具
public class KeyUtil {

    /**
     * 唯一值学生主键生成
     * @return
     */
    public static synchronized String getUniqueKey(){
        Random random = new Random();
        Integer number = random.nextInt(90000)+10000;
        return "2014"+number;
    }
}
  • Dao层处理 Jpa简化操作

@Entity
@Data
public class User {

    @Id
    @GeneratedValue
    private Integer id;

    /** 用户名 .*/
    private String username;

    /** 密码 .*/
    private String password;

    /** 状态 .*/
    private String status;

    /** 描述 .*/
    private String descn;

}

public interface StuInformationRepository extends JpaRepository<StuInformation,String>{

}
  • 表单提交
@Data
public class StudentForm {

    /** 姓名 .*/
    private String stuName;

    /** 性别 0表示男生,1标识女生 .*/
    private Integer stuSex;

    /** 年龄 .*/
    private Integer stuAge;

    /** 专业 .*/
    private String stuMagor;

    /** 年级 .*/
    private Integer stuGrade;

    /** 院系 .*/
    private String stuDepartment;

    /** 班级 .*/
    private String stuClass;
}

<!--提交值集合转换-->
public class StudentFormList2StuInformationList {

    public static StuInformation convert(StudentForm studentForm){
        StuInformation stuInformation = new StuInformation();
        BeanUtils.copyProperties(studentForm,stuInformation);
        stuInformation.setStuId(KeyUtil.getUniqueKey());
        return stuInformation;
    }

    public static List<StuInformation> convert(List<StudentForm> studentForms){
        return studentForms.stream().map(e->convert(e)).collect(Collectors.toList());
    }
}
  • Service层处理
public interface StuInfomationService {

    /** 查询所有 .*/
    Page<StuInformation> findAll(Pageable pageable);

    /** 单个结果查询 .*/
    StuInformation findOne(String stuId);

    /** 集合插入 .*/
    List<StuInformation> save(List<StudentForm> studentForms);

    /** 单个存储 .*/
    StuInformation add(StudentForm form);

    /** 更新 .*/
    StuInformation update(StuInformation stuInformation);

    void delete(String stuid);
}


@Service
@Slf4j
public class StuInformationServiceImpl implements StuInfomationService {

    @Autowired
    private StuInformationRepository repository;


    @Override
    public Page<StuInformation> findAll(Pageable pageable) {
        return repository.findAll(pageable);
    }

    @Override
    public StuInformation findOne(String stuId) {
        return repository.findOne(stuId);
    }

    @Override
    @Transactional
    public List<StuInformation> save(List<StudentForm> studentForms) {
        List<StuInformation> result = repository.save(StudentFormList2StuInformationList.convert(studentForms));
        if(result.size()!=studentForms.size()){
            log.error("【批量数据插入出错】 批量数据插入错误 result = {}",result);
            throw new StuInformationException(ResultEnum.LIST_SAVE_ERROR);
        }
        return result;
    }

    @Override
    public StuInformation add(StudentForm form) {
        StuInformation stuInformation = new StuInformation();
        BeanUtils.copyProperties(form,stuInformation);
        stuInformation.setStuId(KeyUtil.getUniqueKey());
        return repository.save(stuInformation);
    }

    @Override
    public StuInformation update(StuInformation stuInformation) {
        StuInformation match = repository.findOne(stuInformation.getStuId());
        if(match==null){
            log.error("【更新操作】 数据库出错 stuInformation={}",stuInformation);
            throw new StuInformationException(ResultEnum.PARAM_ERROR_ADD);
        }
        StuInformation result = repository.save(stuInformation);
        return result;
    }

    @Override
    public void delete(String stuid) {
        StuInformation stuInformation = repository.findOne(stuid);
        if(stuInformation==null){
            log.error("【更新操作】 数据库出错 stuInformation={}",stuInformation);
            throw new StuInformationException(ResultEnum.PARAM_ERROR_ADD);
        }
        repository.delete(stuid);
    }
}

Swagger可视化API方案

Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件。本文简单介绍了在项目中集成swagger的方法和一些常见问题。如果想深入分析项目源码,了解更多内容,见参考资料。
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。Swagger 让部署管理和使用功能强大的API从未如此简单。

  • 依赖添加
<!--api文档规范-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.2.2</version>
</dependency>
  • Swagger配置
@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xiaojinzi.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2构建RESTful APIs")
                .description("后期写成md上传简书:https://www.jianshu.com/u/cebf2052c61b")
                .termsOfServiceUrl("https://www.jianshu.com/u/cebf2052c61b")
                .contact("金全")
                .version("1.0")
                .build();
    }
}
  • Controller 请求处理
@RestController
@RequestMapping("/student")
@Slf4j
public class StuInfoController {

    @Autowired
    private StuInfomationService stuInfomationService;

    /**
     * 单个对象添加
     * @param form
     * @param bindingResult
     * @return
     */
    @ApiOperation(value = "添加学生",notes = "根据对象添加")
    @ApiImplicitParam(name = "form",value = "学生实体StudentForm",required = true,dataType = "StudentForm")
    @PostMapping("/add")
    public ResultVo addStudent(@RequestBody StudentForm form, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            log.error("【添加学生】 参数传递错误 form ={}",form);
            throw new StuInformationException(ResultEnum.PARAM_ERROR_ADD);
        }
        StuInformation result = stuInfomationService.add(form);
        return ResultVoUtil.success(result);
    }


    /**
     * 批量添加
     * @param list
     * @param bindingResult
     * @return
     */
    @ApiOperation(value = "批量添加",notes = "集合对象添加")
    @PostMapping("/batchadd")
    public ResultVo batchAdd(@RequestBody List<StudentForm> list,BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            log.error("【添加学生】 参数传递错误 list ={}",list);
            throw new StuInformationException(ResultEnum.PARAM_ERROR_ADD);
        }
        List<StuInformation> stuInformations = stuInfomationService.save(list);
        return ResultVoUtil.success(stuInformations);
    }

    /**
     * 根据单个查询
     * @param stuid
     * @return
     */
    @ApiOperation(value = "单个查询",notes = "id查询")
    @ApiImplicitParam(name = "stuid",value = "通过id查询",required = true,dataType = "String",paramType = "Path")
    @GetMapping("/findone/{stuid}")
    public ResultVo findOne(@PathVariable String stuid){
        Map<String,String> map = new HashMap<>();
        StuInformation stuInformation = stuInfomationService.findOne(stuid);
        if(stuInformation==null){
            map.put("object","没有该同学");
            return ResultVoUtil.success(map);
        }
        return ResultVoUtil.success(stuInformation);
    }

    /**
     * 分页查询
     * @param page
     * @param size
     * @return
     */
    @ApiOperation(value = "分页查询",notes = "分页参数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "当前页",required = false,dataType = "Integer",defaultValue = "1",paramType = "Query"),
            @ApiImplicitParam(name = "size",value = "页面显示数",required = false,dataType = "Integer",defaultValue = "10",paramType = "Query")
    })
    @GetMapping("/findAll")
    public ResultVo findAll(@RequestParam(value = "page",defaultValue = "1")Integer page,@RequestParam(value = "size",defaultValue = "10")Integer size){
        PageRequest request = new PageRequest(page-1,size);
        Page<StuInformation> stuInformations = stuInfomationService.findAll(request);
        return ResultVoUtil.success(stuInformations.getContent());
    }

    /**
     * 更新操作
     * @param stuInformation
     * @return
     */
    @ApiOperation(value = "更新操作",notes = "单个更新")
    @ApiImplicitParam(name = "stuInformation",value = "学生实体stuInformation",required = true,dataType = "StuInformation")
    @PutMapping("/update")
    public ResultVo updateStu(@RequestBody StuInformation stuInformation){
        StuInformation result = stuInfomationService.update(stuInformation);
        return ResultVoUtil.success(result);
    }

    /**
     * 删除操作
     * @param stuid
     * @return
     */
    @ApiOperation(value = "删除操作" ,notes = "根据id删除")
    @ApiImplicitParam(name = "stuid",value = "主键删除",required = true,dataType = "String",paramType = "Path")
    @DeleteMapping("/delete/{stuid}")
    public ResultVo deleteStu(@PathVariable String stuid){
        stuInfomationService.delete(stuid);
        return ResultVoUtil.success();
    }

}
  • 截图
成功运行界面 具体api调试
  • 借鉴博客(程序员DD(翟永超)小哥哥构建强大的RESTful API文档
  • 下一篇讲解 SpringSecurity+JWT 保护你的API(近期推出)
  • 源码上传Git 渴望你的star
  • 本篇博客撰写人: XiaoJinZi 转载请注明出处
  • 学生能力有限 附上邮箱: 986209501@qq.com 不足以及误处请大佬指责

相关文章

网友评论

      本文标题:前后端分离传值方案-RestfulAPI

      本文链接:https://www.haomeiwen.com/subject/hiytoxtx.html