在项目中遇到两次请求并发,造成第一次请求通讯中断的问题,所以对这个问题进行了一些验证,本文为自己记录,不喜勿喷。
springboot 默认单例,多例增加@Scope("prototype")
1、单例与多例controller的验证
1)单例模式下
package com.chs.nginxdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class BankController {
private int index;
private static int staicIndex;
@RequestMapping("/query")
@ResponseBody
public String queryBank() {
System.out.println("普通属性:" + index++ + "..." + "静态属性:" + staicIndex++);
return "ok";
}
}
打印输出如下:
普通属性:0...静态属性:0
普通属性:1...静态属性:1
普通属性:2...静态属性:2
普通属性:3...静态属性:3
普通属性:4...静态属性:4
我们可以看出非静态成员变量是共用的,一直在递增;静态成员也在递增。
2)多例模式
package com.chs.nginxdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Scope("prototype")
public class BankController {
private int index;
private static int staicIndex;
@RequestMapping("/query")
@ResponseBody
public String queryBank() {
System.out.println("普通属性:" + index++ + "..." + "静态属性:" + staicIndex++);
return "ok";
}
}
普通属性:0...静态属性:0
普通属性:0...静态属性:1
普通属性:0...静态属性:2
普通属性:0...静态属性:3
普通属性:0...静态属性:4
我们看到非静态成员变量每次是创建,都是0;静态成员变量每次递增;
由此看出一般不要在单例模式下使用非静态成员变量。
2、如果controller继承的基类是多例,那么controller也是多例吗?
package com.chs.nginxdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
@Controller
@Scope("prototype")
public class BaseController {
}
package com.chs.nginxdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class BankController extends BaseController{
private int index;
private static int staicIndex;
@RequestMapping("/query")
@ResponseBody
public String queryBank() {
System.out.println("普通属性:" + index++ + "..." + "静态属性:" + staicIndex++);
return "ok";
}
}
打印输出如下:
普通属性:0...静态属性:0
普通属性:1...静态属性:1
普通属性:2...静态属性:2
普通属性:3...静态属性:3
普通属性:4...静态属性:4
由此看出此基类多例,子类单例,仍然是单例,不会继承;
3、如果controller是多例, service 是单例会创建多个service吗?
package com.chs.nginxdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
@Controller
@Scope("prototype")
public class BaseController {
}
package com.chs.nginxdemo.controller;
import com.chs.nginxdemo.service.SocketClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Scope("prototype")
public class BankController extends BaseController {
private int index;
private static int staicIndex;
@Autowired
private SocketClient socketClient;
@RequestMapping("/query")
@ResponseBody
public String queryBank() {
String data = socketClient.doTrade();
System.out.println("普通属性:" + index++ + "..." + "静态属性:" + staicIndex++ + "..." + "data:" + data);
return "ok";
}
}
package com.chs.nginxdemo.service;
import org.springframework.stereotype.Service;
@Service
public class SocketClient {
private int index;
public String doTrade() {
return Integer.toString(index++);
}
}
打印输出:
普通属性:0...静态属性:0...data:0
普通属性:0...静态属性:1...data:1
普通属性:0...静态属性:2...data:2
普通属性:0...静态属性:3...data:3
由此看出,单例service依然是单例
把service设成多例,代码如下
package com.chs.nginxdemo.service;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
@Service
@Scope("prototype")
public class SocketClient {
private int index;
public String doTrade() {
return Integer.toString(index++);
}
}
打印输出如下:
普通属性:0...静态属性:0...data:0
普通属性:0...静态属性:1...data:0
普通属性:0...静态属性:2...data:0
普通属性:0...静态属性:3...data:0
普通属性:0...静态属性:4...data:0
可以看出 data都是0,变成多例了。
综上所述,想比较简单的解决并发问题,需要controller和 service都设置成多例。