Spring MVC就像控制器中的OptimisticLocking

时间:2017-05-19 19:02:27

标签: java spring spring-mvc

我有一个Spring控制器和两个方法,一个准备订单数据供用户编辑,另一个方法是从表格(POST)返回最新的订单信息更改。

现在我想让一些程序像OptiMistic Locking一样工作而不在数据库中添加版本列。因为客户端在会话到期之前花了一些时间来编辑订单,所以我必须使用post方法确保客户首次打开订单编辑页面时订单仍处于相同状态

所以我在加载订单编辑页面之前添加orderStatus属性来保存原始状态,并在保存订单编辑时与DB的最新状态进行比较,如下所示:

@RequestMapping("/order")
@Controller
public class OrderController{
    private String orderStatus;

    @RequestMapping(value = "/{orderId}/edit", method = RequestMethod.GET)
    public String prepareOrderEditForm(....){
         ....
        // remember the original status
        orderStatus = Order.getLatestStatus(orderId);
    }

    @RequestMapping(value = "/processEdit", method = RequestMethod.POST)
    public String prepareOrderEditForm(....){
         ....
        String currentOrderStatus = Order.getLatestStatus(orderId);
        // compare most recent status with the original status
        if(currentOrderStatus.equals(orderStatus) == false){
            ....//something is wrong, someone may be already edit the order
            return "failed";
        }else{
            orderService.merge(order);
            orderStatus = order.getNewStatus();
        }

        return "updated";
    }
}

我理解这个设计不像数据库的乐观锁定那样健壮,它可能会忽略执行DML的时间,这里的orderStatus也应该使用getter / setter作为java bean。所以请排除上述问题,但只将范围放在此控制器中

我的问题是,由于Spring MVC在JSP Servlet这样的单线程中运行,当多个用户登录到spring web应用程序并编辑相同的顺序时会出现任何问题,因此该控制器类中的orderStatus以某种方式由多个用户交织在一起(并发问题)?

1 个答案:

答案 0 :(得分:0)

JSP和Spring MVC都不是单线程的。

您应该始终尝试不在控制器方法中更改实例/静态变量。

修改

我应该提到会话线程安全只有在你将Spring MVC抽象控制器的synchronizeOnSession设置为true时才会起作用(默认为false)。

在您的情况下,您可以:

1)在定义控制器的spring应用程序上下文中将synchronizeOnSession设置为true。

2)从Spring的AbstractController扩展并覆盖handleRequestInternal方法。

3)在handleRequestInternal中调用request.getSession()。setAttribute(" orderStatus")