java spring mvc restful,使用Spring MVC开发RESTful API(续)

使用多线程提高REST服务性能

异步处理REST服务,提高服务器吞吐量

使用Runnable异步处理Rest服务

2018-09-03_035106.png

AsyncController.java

@RestController

@GetMapping("/async")

public class AsyncController {

private Logger logger = LoggerFactory.getLogger(getClass());

@RequestMapping("/order")

public Callable order() throws Exception {

logger.info("主线程开始");

Callable result = new Callable() {

@Override

public String call() throws Exception {

logger.info("副线程开始");

Thread.sleep(2000); // 模拟处理下单消耗的时间

logger.info("副线程结束");

return "success";

}

};

logger.info("主线程结束");

return result;

}

}

使用DeferredResult异步处理Rest服务

2018-09-03_231305.png

应用1/线程1:接收下单请求,放到消息队列

应用1/线程2:监听器,监听消息队列是否有下单处理结果,返回HTTP响应

应用2:处理下单逻辑

AsyncController.java

@GetMapping("/order2")

public DeferredResult order2() throws Exception {

logger.info("主线程开始");

// 主线程,相当于图中应用1/线程1,接收HTTP请求

// 收到下单请求,生成一个随机订单号,放到消息队列里

String orderNumber = RandomStringUtils.randomNumeric(8);

mockQueue.setPlaceOrder(orderNumber);

// 用于接收处理结果

DeferredResult result = new DeferredResult<>();

deferredResultHolder.getMap().put(orderNumber, result);

logger.info("主线程结束");

return result;

}

MockQueue.java,模拟队列

@Component

public class MockQueue {

private String placeOrder; // 下单消息

private String completeOrder; // 订单完成订单完成

private Logger logger = LoggerFactory.getLogger(getClass());

public String getPlaceOrder() {

return placeOrder;

}

public void setPlaceOrder(String placeOrder) {

// 此线程是模拟应用2,处理下单逻辑

new Thread(() -> {

logger.info("接到下单请求:" + placeOrder);

try {

Thread.sleep(1000); // 模拟处理下单过程

} catch (InterruptedException e) {

e.printStackTrace();

}

this.completeOrder = placeOrder;

logger.info("下单请求处理完毕:" + placeOrder);

}).start();

}

public String getCompleteOrder() {

return completeOrder;

}

public void setCompleteOrder(String completeOrder) {

this.completeOrder = completeOrder;

}

}

DeferredResultHolder.java ,用于在线程1与线程2之间传递传递DeferredResult对象

@Component

public class DeferredResultHolder {

// 订单号,订单处理结果

private Map> map = new HashMap<>();

public Map> getMap() {

return map;

}

public void setMap(Map> map) {

this.map = map;

}

}

QueueListener.java,监听器

@Component

public class QueueListener implements ApplicationListener {

@Autowired

private MockQueue mockQueue;

@Autowired

private DeferredResultHolder deferredResultHolder;

private Logger logger = LoggerFactory.getLogger(getClass());

@Override

public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {

// 相当于图中应用1/线程2,模拟监听器

new Thread(() -> {

while (true) {

if (StringUtils.isNotBlank(mockQueue.getCompleteOrder())) {

String orderNumber = mockQueue.getCompleteOrder();

logger.info("返回订单处理结果:" + orderNumber);

deferredResultHolder.getMap().get(orderNumber)

.setResult("place order success");

mockQueue.setCompleteOrder(null);

} else {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

}

}).start();

}

}

2018-09-04_191940.png

异步处理配置

用拦截器拦截异步处理的请求以有线程池的配置

// 用拦截器拦截异步处理的请求,有如下两个方法注册拦截器,分别对应异步处理的两种方式

// 区别是有超时时间

// configurer.registerCallableInterceptors()

// configurer.registerDeferredResultInterceptors()

// Runnable使用的简单的异步线程池来处理,线程不可重用

使用Swagger自动生成文档

引入Swagger

引入相关依赖,immoc-security-demo/pom.xml

io.springfox

springfox-swagger2

2.7.0

io.springfox

springfox-swagger-ui

2.7.0

加注解,DemoApplication.java

@EnableSwagger2 // 启用Swagger2

2018-09-04_194358.png

详细描述

方法的描述

@ApiOperation(value = "用户查询服务")

参数的描述

// 参数被封装到对象里

@ApiModelProperty("用户名")

// 参数直接写在方法里

@ApiParam("用户ID")

使用WireMock伪造REST服务

与前端开发并行工作,开发阶段,前端包括app和页面开发时都需要测试数据,这时WireMock就派上用场了。这与你再写个web应用提供测试数据有什么不同呢。因为WireMock不用重启,定义url和返回数据都很方便。

下载并启动

指定端口启动:

java -jar wiremock-standalone-2.18.0.jar --port 9999

# --port 9999 指定端口,默认端口8080, --port 0 随机端口

2018-09-04_200520.png

模拟请求和响应

引入依赖

com.github.tomakehurst

wiremock

org.apache.httpcomponents

httpclient

编写代码,MockServer.java

public class MockServer {

public static void main(String[] args) throws IOException {

configureFor("192.168.5.210", 9999);

// configureFor(9999);

removeAllMappings();

mock("/order/1", "01.txt");

mock("/order/2", "02.txt");

}

private static void mock(String url, String fileName) throws IOException {

ClassPathResource resource =

new ClassPathResource("mock/response/" + fileName);

String content =

StringUtils.join(FileUtils.readLines(resource.getFile(), "UTF-8"), "\n");

stubFor(get(urlPathEqualTo(url))

.willReturn(aResponse().withBody(content).withStatus(200)));

}

}

2018-09-04_223812.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值