Developing restful APIs using Spring MVC (cont.)

Source: Internet
Author: User
Tags message queue

Using multithreading to improve rest service performance

Improve server throughput by processing rest services asynchronously

Using runnable to handle the rest service asynchronously

Asynccontroller.java

@RestController@GetMapping("/async")public class AsyncController {    private Logger logger = LoggerFactory.getLogger(getClass());    @RequestMapping("/order")    public Callable<String> order() throws Exception {        logger.info("主线程开始");        Callable<String> result = new Callable<String>() {            @Override            public String call() throws Exception {                logger.info("副线程开始");                Thread.sleep(2000); // 模拟处理下单消耗的时间                logger.info("副线程结束");                return "success";            }        };        logger.info("主线程结束");        return result;    }}
Using Deferredresult to handle the rest service asynchronously

App 1/thread 1: Receive the next order request, put it in message queue

Apply 1/Thread 2: Listener, listen for Message Queuing for order Processing results, return HTTP response

Application 2: Processing the next order logic

Asynccontroller.java

@GetMapping("/order2")public DeferredResult<String> order2() throws Exception {    logger.info("主线程开始");    // 主线程,相当于图中应用1/线程1,接收HTTP请求    // 收到下单请求,生成一个随机订单号,放到消息队列里    String orderNumber = RandomStringUtils.randomNumeric(8);    mockQueue.setPlaceOrder(orderNumber);    // 用于接收处理结果    DeferredResult<String> result = new DeferredResult<>();    deferredResultHolder.getMap().put(orderNumber, result);    logger.info("主线程结束");    return result;}

Mockqueue.java, Analog queue

@Componentpublic 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, for passing Deferredresult objects between thread 1 and Threads 2

@Componentpublic class DeferredResultHolder {    // 订单号,订单处理结果    private Map<String, DeferredResult<String>> map = new HashMap<>();    public Map<String, DeferredResult<String>> getMap() {        return map;    }    public void setMap(Map<String, DeferredResult<String>> map) {        this.map = map;    }}

Queuelistener.java, Listener

@Componentpublic class Queuelistener implements applicationlistener<contextrefreshedevent> {@Autowired privat    e mockqueue mockqueue;    @Autowired private Deferredresultholder Deferredresultholder;    Private Logger Logger = Loggerfactory.getlogger (GetClass ());        @Override public void Onapplicationevent (Contextrefreshedevent contextrefreshedevent) {//equivalent to figure application 1/thread 2, Analog listener New Thread ((), {while (true) {if (Stringutils.isnotblank (Mockqueue.getcompleteorder (                    )) {String ordernumber = Mockqueue.getcompleteorder ();                    Logger.info ("Return Order Processing Result:" + ordernumber);                    Deferredresultholder.getmap (). Get (OrderNumber). Setresult ("Place order Success");                Mockqueue.setcompleteorder (NULL);                    } else {try {thread.sleep (100);                    } catch (Interruptedexception e) {}}}). Start (); }}

Launch the app and access Http://localhost:8080/async/order2

Asynchronous processing Configuration

Intercepting requests for asynchronous processing with interceptors in the configuration of the thread pool

// 用拦截器拦截异步处理的请求,有如下两个方法注册拦截器,分别对应异步处理的两种方式// 区别是有超时时间// configurer.registerCallableInterceptors()// configurer.registerDeferredResultInterceptors()// Runnable使用的简单的异步线程池来处理,线程不可重用
Using swagger to automatically generate documents to introduce swagger

Introducing Dependencies, Immoc-security-demo/pom.xml

<!-- 引入swagger --><dependency>    <groupId>io.springfox</groupId>    <artifactId>springfox-swagger2</artifactId>    <version>2.7.0</version></dependency><dependency>    <groupId>io.springfox</groupId>    <artifactId>springfox-swagger-ui</artifactId>    <version>2.7.0</version></dependency>

Add annotations, Demoapplication.java

@EnableSwagger2 //  启用Swagger2

Restart the app to access the link http://localhost:8080/swagger-ui.html

Detailed description

Description of the method

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

Description of the parameter

// 参数被封装到对象里@ApiModelProperty("用户名")// 参数直接写在方法里@ApiParam("用户ID")
Using Wiremock to forge rest services

Wiremock comes in handy when working in parallel with front-end development, in the development phase, when the front-end includes app and page development needs test data. This is different from how you can write a web app to provide test data. Because Wiremock does not have to be restarted, it is convenient to define URLs and return data.

Download and launch

Download: http://wiremock.org/docs/running-standalone/

Specify the port to start:

java -jar wiremock-standalone-2.18.0.jar --port 9999# --port 9999 指定端口,默认端口8080, --port 0 随机端口

Impersonation requests and responses

Introducing Dependencies

<!--  引入WireMock--><dependency>    <groupId>com.github.tomakehurst</groupId>    <artifactId>wiremock</artifactId></dependency><dependency>    <groupId>org.apache.httpcomponents</groupId>    <artifactId>httpclient</artifactId></dependency>

Write code, 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)));    }}

Developing restful APIs using Spring MVC (cont.)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.