原型bean在@Controller中不按预期工作

5 浏览
0 Comments

原型bean在@Controller中不按预期工作

我有一个包含两个方法的控制器。第一个方法生成一个随机的验证码值,第二个方法用于比较用户输入的验证码和生成的验证码。问题是当多个用户尝试验证验证码值时,最后一个生成的值会正确地预览给其他用户生成的值。

以下是尝试解决这个问题的不同方式:

1. 使控制器具备webApplicationContext感知能力,详情请参考这里

2. 使用@Lookup,示例在这里

3. 最后尝试使用作用域代理,详情请参考这里

错误是由于@Controller bean的单例模式,并且我需要在我的bean中使用原型范围(Prototype scope)。但是我尝试的所有方法都没有起作用。我尝试进行调试,在控制器的这一行代码中:

String captchaText = captchaProducer.createText();
dataCaptcha.setCaptcha(captchaText);

captchaText有一个值,但是在使用setCaptcha并检查dataCaptcha对象之后,captcha字段为空。

我正在使用Spring Boot 2.0.3版本。

0
0 Comments

问题出现的原因是:Singleton Bean在其整个生命周期中持有对同一个prototype bean的引用。如果将DataCaptcha定义为prototype作用域,那么它将在不同的threadContexts之间共享,多个用户将能够使用相同的验证码。但是,如果将DataCaptcha定义在类级别,那么只会创建一个控制器类的对象(singleton bean),其关联的DataCaptcha也将是相同的。

解决方法是:根据你已经指出的webApplicationContext-aware,你需要在方法内部获取一个新的局部实例的DataCaptcha。你可以尝试为DataCaptcha添加一个唯一的ID,并使用该ID检索验证码以进行验证。或者你可以将其放在服务器端的userSession对象中,并在验证成功后清除。

以下是代码示例:

@Controller
public class MyController {
    @Autowired
    private WebApplicationContext webApplicationContext;
    @RequestMapping("/get-captcha")
    public ModelAndView getCaptcha() {
        DataCaptcha dataCaptcha = webApplicationContext.getBean(DataCaptcha.class);
        // 生成验证码逻辑
        return new ModelAndView("captcha");
    }
    @RequestMapping("/validate-captcha")
    public ModelAndView validateCaptcha(@RequestParam("captchaId") String captchaId, @RequestParam("captchaValue") String captchaValue) {
        DataCaptcha dataCaptcha = webApplicationContext.getBean(captchaId, DataCaptcha.class);
        // 验证验证码逻辑
        return new ModelAndView("result");
    }
}

在上面的代码示例中,我们通过在方法内部使用`webApplicationContext.getBean(DataCaptcha.class)`来获取一个新的DataCaptcha实例。在生成验证码时,我们可以将其唯一的ID返回给客户端。在验证验证码时,我们可以使用该ID通过`webApplicationContext.getBean(captchaId, DataCaptcha.class)`方法获取到相应的DataCaptcha实例来进行验证。

希望以上解决方法对你有帮助!

0
0 Comments

Prototype bean inside @Controller not working as expected

在使用Spring MVC时,有一个问题可能会遇到:在@Controller中定义的原型(prototype)bean无法按预期工作。下面将介绍该问题的原因以及解决方法。

问题的原因是在@Controller中定义的DataCaptcha变量应该不是一个类变量,而是应该定义为handleRequest方法中的一个局部变量。这样做是因为原型(prototype)bean的作用域是每次请求都会创建一个新的实例,而类变量只会在应用程序启动时创建一次实例。

解决该问题的方法是使用Spring上下文来获取一个原型(prototype)bean的实例。可以在handleRequest方法中添加以下代码:

DataCaptcha dataCaptcha = ctx.getBean(DataCaptcha.class);

上述代码将使用Spring上下文(ctx)来获取一个DataCaptcha的原型实例。这样,每次调用handleRequest方法时,都会创建一个新的DataCaptcha实例,以确保每个请求都使用独立的实例。

通过将DataCaptcha变量定义为局部变量,并在每次请求时获取一个新的原型实例,可以解决原型bean在@Controller中无法按预期工作的问题。这样做可以确保每个请求都使用独立的实例,避免了原型bean被多个请求共享导致的问题。

0