Spring的Controller怎样保证线程安全

问题分析

我们先来看下面的代码,判断一下两个接口请求的值分别多少。

import com.sun.proxy.model.system.OptResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author ybc
 * @date 2020/08/05 21:30
 */
@RestController
public class TestController {
    //定义测试成员变量
    private int num = 0;

    @RequestMapping(value = "/testOne",method = RequestMethod.GET)
    public OptResult<Integer> testOne() {
        return new OptResult<>(OptResult.OptStat.OK,++num);
    }

    @RequestMapping(value = "/testTwo",method = RequestMethod.GET)
    public OptResult<Integer> testTwo() {
        return new OptResult<>(OptResult.OptStat.OK,++num);
    }

}

如果这个Controller是线程安全的,两个接口请求的值应该是相同的。

问题验证

请求接口testOne返回结果为:
在这里插入图片描述
请求接口testTwo返回结果为:
在这里插入图片描述
两个接口返回的值是不同的,显然线程不安全。

下面我们来改造一下代码,让controller增加作用多例 @Scope(“prototype”),重新运行程序。

@RestController
@Scope("prototype")
public class TestController {
    //定义测试成员变量
    private int num = 0;

    @RequestMapping(value = "/testOne",method = RequestMethod.GET)
    public OptResult<Integer> testOne() {
        return new OptResult<>(OptResult.OptStat.OK,++num);
    }

    @RequestMapping(value = "/testTwo",method = RequestMethod.GET)
    public OptResult<Integer> testTwo() {
        return new OptResult<>(OptResult.OptStat.OK,++num);
    }

}

请求接口testOne返回结果为:
在这里插入图片描述
请求接口testTwo返回结果为:
在这里插入图片描述
通过上述两种对比的结果我们可以发现,单例是不安全的,会导致属性重复使用。

解决方案

  1. 尽量避免在controller中定义成员变量。
  2. 如果必须定义成员变量时候,需要通过注解@Scope(“prototype”),将其设置为多例模式。
  3. 在Controller中使用ThreadLocal变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值