java 庖丁解牛api_Java Restful API Best Practices

API 是后端工作的主要工作之一, 开发难度低, 但是比较繁杂。 经过几个月的学习,总结一下自己对接口开发的一些套路。

cbfd0f6fdc5a

接口

首先,需要熟悉业务,熟悉数据库表结构,列出接口与表的对应关系。

确定接口需求与数据表

如某单位接口界面与表需求:

cbfd0f6fdc5a

线路统计

界面需要展示的数据 <==> 数据表

按照这种关系, 制作一个对应的Excel表,将初始需求确定下来,以便后面快速进行开发。

后台项目结构

user

---> controller ---> service ---> dao

---> cache ---> 返回

---> mapper ---> DB ---> 返回

---> 管道 ---> 数据处理 ---> 返回

按照这种结构可以更好地扩展,

dao层负责数据获取与接受,方式不定,可能从DB, Cache, MQ之类的结构获取或者提交数据。

pojo 分为

dto 数据传输对象, 当model数据需要处理时返回使用

vo 最后返回给前端的对象封装

model 从DB直接出来的数据,未经过逻辑加工

项目构建

结构定下来后, 直接使用

cbfd0f6fdc5a

spring initializr -- https://start.spring.io/

加入swagger-ui,交代清楚接口事宜。

package com.loyotech.bigscreenbackend;

import com.google.common.base.Function;

import com.google.common.base.Optional;

import com.google.common.base.Predicate;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import springfox.documentation.RequestHandler;

import springfox.documentation.builders.ApiInfoBuilder;

import springfox.documentation.builders.PathSelectors;

import springfox.documentation.service.ApiInfo;

import springfox.documentation.service.Contact;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**

* @Auther:chalide

* @Date:2018/8/30 11:45

* @Description:

*/

@Configuration

@EnableSwagger2

public class SwaggerConfig {

@Bean

public Docket api(){

return new Docket(DocumentationType.SWAGGER_2)

.groupName("loyotech")

.apiInfo(apiInfo())

.select()

.apis(SwaggerConfig.basePackage("com.loyotech.bigscreenbackend"))

.paths(PathSelectors.regex("/*.*"))

.build();

}

/**

* Predicate that matches RequestHandler with given base package name for the class of the handler method.

* This predicate includes all request handlers matching the provided basePackage

*

* @param basePackage - base package of the classes

* @return this

*/

public static Predicate basePackage(final String basePackage) {

return input -> declaringClass(input).transform(handlerPackage(basePackage)).or(true);

}

/**

* 处理包路径配置规则,支持多路径扫描匹配以逗号隔开

*

* @param basePackage 扫描包路径

* @return Function

*/

private static Function, Boolean> handlerPackage(final String basePackage) {

return input -> {

for (String strPackage : basePackage.split(",")) {

boolean isMatch = input.getPackage().getName().startsWith(strPackage);

if (isMatch) {

return true;

}

}

return false;

};

}

/**

* @param input RequestHandler

* @return Optional

*/

private static Optional extends Class>> declaringClass(RequestHandler input) {

return Optional.fromNullable(input.declaringClass());

}

private ApiInfo apiInfo() {

return new ApiInfoBuilder()

//标题

.title("Demo-Api")

//联系人

.contact(new Contact("", "", ""))

//版本号

.version("1.0")

//描述

.description("Demo-api")

.build();

}

}

cbfd0f6fdc5a

引入swagger-ui,减少交互成本

环境

上下文环境在这里指的就是Spring容器上下文,也就是在环境中定义一些对象,存储进去。

添加spring 上下文环境, spring-dao, spring-service, spring-web, web.xml

或者是使用Java Config类去定义上下文环境(推荐)。

其他环境,mybatis-config.xml, logback.xml

cbfd0f6fdc5a

使用多环境配置上下文,减少因为环境变动的文件更改

当部署的时候只需要在命令行中调用对应的环境

java -jar xxx.jar --spring.profiles.active=test

这样就可以启动那个对应环境的配置

相似的,下面是会根据对应的关系启用对应的properties/yaml文件

cbfd0f6fdc5a

启用对应的properties

开发流程

user

---> controller ---> service ---> dao

---> cache ---> 返回

---> mapper ---> DB ---> 返回

---> 管道 ---> 数据处理 ---> 返回

规则1.所有的类都必须有接口和实现,以便后期扩展。

规则2.所有的单条接口流程命名一致,如有其他业务则另外扩展业务类

规则3.写上业务注释,使用IDEA全局搜索辅助查找需求

规则4.所有传参统一使用Map,所有返参统一使用Object

规则5.一切都往规则靠拢,不要魔法数,命名表达意思...

以上是为了开发时可以更好利用搜索,统一命名可能不太妥当,所以如有其他业务则直接扩展业务类,重新定义业务方法名。

最外层开始 -->

@SpringBootApplication

@ComponentScan

@EnableAutoConfiguration

@EnableSwagger2

@EnableCaching

public class BigScreenBackendApplication(){}

Controller

@RestController

@Api("Ice-Module-Api")

@Log

public class IceModuleController implements IceModuleRemoteApi {

@Autowired

IceModuleService iceModuleService;

@Override

public Object selectIceMonitorDeviceCountEveryProvince(HttpServletRequest request, HttpServletResponse response) {

// 获取传输参数, 删除无效参数, 加上分页逻辑.....

Map parameterMap = MapUtil.getParameterMap(request);

log.info("方法-selectIceMonitorDeviceCountEveryProvince 参数-" + parameterMap.toString());

return iceModuleService.selectIceMonitorDeviceCountEveryProvince(parameterMap);

}

}

Service

@Service

@Transactional

@Log

public class IceModuleServiceImpl implements IceModuleService {

// 有可能会用到redisTemplate, 如果没有使用redis,

// 则这个对象为null, 使用时在最外层做一下空指针判定

@Autowired(required = false)

RedisTemplate redisTemplate;

@Autowired

IceModuleDao iceModuleDao;

// #TODO 截至编码位置, 利用TODO来标示任务项,可快速定位开发位置

@Override

public Object selectIceMonitorDeviceCountEveryProvince(Map paramterMap) {

List recCompanies = Arrays.asList("南网超高压", "广东电网", "广西电网", "云南电网", "贵州电网");

List iceMonitorDeviceCounts = iceModuleDao.selectIceMonitorDeviceCountEveryProvince(paramterMap);

List result = new LinkedList<>();

// 初始化数据

recCompanies.stream().distinct().forEach(

recCompany -> {

result.add(new IceMonitorDeviceCount(){{

setRecCompany(recCompany);

}});

}

);

result.stream().forEach(iceMonitorDeviceCount -> {

for (IceMonitorDeviceCount data : iceMonitorDeviceCounts) {

if (iceMonitorDeviceCount.getRecCompany().equalsIgnoreCase(data.getRecCompany())) {

iceMonitorDeviceCount.setCount(data.getCount());

}

}

});

return prepareGoodResult(result);

}

}

Dao

@Repository

public class IceModuleDaoImpl implements IceModuleDao {

@Autowired

IceModuleMapper iceModuleMapper;

@Override

@Cacheable(value = "demo", key = "'IMDC:' + #parameterMap.get(id)")

public List selectIceMonitorDeviceCountEveryProvince(Map parameterMap) {

List result = iceModuleMapper.selectIceMonitorDeviceCountEveryProvince(parameterMap);

return result;

}

}

Mapper

@Mapper

@Repository

public interface IceModuleMapper {

List selectIceMonitorDeviceCountEveryProvince(Map parameterMap);

}

IceModuleMapper.xml

SELECT COUNT(DISTINCT BSID) AS COUNT, COMPANY

FROM ICE_MONITOR_DATA

GROUP BY REC_COMPANY

以上,构建了最主要的API主要的轮廓,还可以往上添加很多其他的内容,如:

Servlet, Listener, Filter, Bean, ApplicationContext, CronTask, InitRunner, Exception, Cache....

这些这里暂且不做说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Introduction There are numerous resources on best practices for creating RESTful web services (see the Resources section at the end of this document). Many of the available resources are conflicting, depending on when they were written. Plus, reading and comprehending several books on the subject in order to implement services “tomorrow” is not doable. In order to facilitate the quick uptake and understanding of RESTful concepts, without requiring the reading of at least three to five books on the subject, this guide is meant to speed up the process—condensing REST best practices and conventions into just the high points with not a lot of discussion. REST is more a collection of principles than it is a set of standards. Other than its over-arching six constraints nothing is dictated. There are "best practices" and de-facto standards but those are constantly evolving—with religious battles waging continuously. Designed to be brief, this document provides recommendations and some cookbook-style discussion on many of the common questions around REST and provides some short background information to offer support for effective creation of real-world, production-ready, consistent RESTful services. This document aggregates information available in other sources, adapting it with experience gained through hard knocks. There is still considerable debate as to whether REST is better than SOAP (and vice versa), and perhaps there are still reasons to create SOAP services. While touching on SOAP, this document won't spend a lot of time discussing the relative merits. Instead, because technology and the industry marches on, we will proceed with the assumption that leveraging REST is the current best practice for Web service creation. The first section offers an overview of what REST is, its constraints, and what makes it unique. The second section supplies some quick tips as little reminders of REST service concepts. Later sections go more in depth to provide the Web

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值