当前位置: 首页 > 面试题库 >

解释此Spring MVC Controller行为

吴英武
2023-03-14
问题内容

我有这个课:

@Component
@Scope("session")
@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue
    @GenericGenerator(name = "incremental", strategy = "increment")
    private Long userID;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String email;

    @Column(nullable = false)
    private String password;
    // getters and setters
}

而这个控制器:

@Controller
@SessionAttributes("user")
@Scope("request")
public class UserCreationWizard {
    @Autowired
    private User user;

    @ModelAttribute("user")
    private User createUser() {
        return user;
    }

    @RequestMapping(value = "/new/users/page/", method = RequestMethod.GET)
    public String begin(HttpServletRequest request) {
        return "wizard"; 
    }

    @RequestMapping(value = "/new/users/page/{page}", method = RequestMethod.POST) 
    public String step(@ModelAttribute("user") User user,
                       @RequestParam("username") String username,
                       @RequestParam("email") String password,
                       @PathVariable() Integer page) {

        return "wizard" + page;
    }

    @RequestMapping(value = "/new/users/page/end", params = "submit", method = RequestMethod.POST) 
    public String end(@RequestParam("password") String password) {

        user.setPassword(password);
        user.setActive(true);
        user.setLastLoggedIn(Calendar.getInstance());

        Session s = HibernateUtils.getSessionFactory().openSession();
        Transaction t = s.beginTransaction();
        try {
            s.persist(user);
            s.flush();
            t.commit();

            s.close();
        } catch (HibernateException e) {
            t.rollback();
        }
        return "wizard";
    }
}

begin()只需在用户创建向导中加载第一个视图(jsp)。它有输入字段usernameemail。在视图中,您将触发POST表单提交step()。在第二个视图(wizard
+ page.jsp)中,您有一个password字段和一个触发了的输入end()

  1. 在调试模式下,我注意到在中step(),我已将User作为ModelAttribute传递给我,不需要为用户名和密码设置其字段。它们是从RequestParams属性中自动获取的。在end()然而,在我没有的ModelAttribute,我不得不手动设置密码。Spring如何管理这个?
  2. 另外,如果我createUser()在Controller中删除该方法,则应用程序将失败,无法找到“用户”的会话属性。该方法如何作为方法参数链接到MethodAttribute?
  3. 最后,如果我删除@SessionAttributes,应用程序不会失败,但是我感觉出了点问题。用户用户现在对所有httprequest是全局的吗?

我的一般问题是:春豆是否映射到其名称?例如。在这里,我以“ user”作为用户,在会话中具有“ user”,“
password”作为requestparam,“ password”作为User成员变量。


问题答案:

好,很多问题。让我们看看,所有引用都是针对当前Spring MVC版本的文档。

1)在你看到的行为user属性的部分解释说,“
在一个方法参数使用@ModelAttribute ”

方法参数上的@ModelAttribute指示应从模型中检索参数。如果模型中不存在该参数,则应首先实例化该参数,然后将其添加到模型中。一旦出现在模型中,则应从具有匹配名称的所有请求参数中填充参数的字段。这在Spring
MVC中称为数据绑定,这是一种非常有用的机制,使您不必分别解析每个表单字段。

Spring如何做到这一点?好吧,源代码是最终的答案,但要猜测起来并不难:Spring知道参数是的实例,User并且通过反射它可以读取类的方法,特别是其
setter
。在这种情况下,它找到setUsername()setEmail(),这些方法的参数是a,String因此它与请求中的参数兼容。

(顺便说一句:@RequestParam("email") String password可能是一个错误。至少是令人困惑的)

2)该方法createUser()之前带有注释@ModelAttribute("user")。这将在“
在方法上使用@ModelAttribute ”部分介绍

方法上的@ModelAttribute指示该方法的目的是添加一个或多个模型属性。

因此,此方法将与名称相关联的对象"user"放在模型上,然后可供其他方法用作参数,例如step()。注意,注释控制着模型中对象使用的标识符。如果将代码更改为

@ModelAttribute("strangeWeirdIdentifier")
private User createUser() { return user; }

应用程序将中断。但是,如果将step()签名更改为

public String step(@ModelAttribute("strangeWeirdIdentifier") User user,
                   @RequestParam("username") String username,
                   @RequestParam("email") String password,
                   @PathVariable() Integer page) {

3)1)和2)中描述的过程在请求期间将对象存储在模型中。使用类注释,@SessionAttributes("user")您可以延长对象的寿命,将其添加到当前对象Session或等效对象中。例如,您可以在其他Controllers中使用与step()方法相同的对象。

最后只是要清楚

  • 在问题2中看到的注释发生在问题1中出现的用法之前。
  • 您可能不需要问题3的注释
  • Spring不会将bean映射到Java代码中的名称,而是映射到注释中使用的名称。为了清楚起见,重复与示例中相同的名称并不罕见。

希望这比官方文档更清楚,通常太简短了,我给你。



 类似资料:
  • 在我的作业中,我对字符串Lexer有以下描述: “字符串文字由零个或多个用双引号(”“)括起的字符组成。使用转义序列(如下所列)表示字符串中的特殊字符。在字符串文本中出现新行或EOF字符是编译时错误。 所有支持的转义序列如下: \b退格 \f formfeed \r回车 \n换行符 \t水平选项卡 \“双引号 \反斜杠 以下是字符串文字的有效示例: "这是一个包含制表符\t的字符串" "他问我:\

  • 语法和语义分析的结果是抽象语法树AST,再往后编译原理还有代码生成及优化的很大一部分,但如果只是做一个执行器,到AST为止就可以解释执行了,当然就算不生成AST,解析执行也可以,只是基于之前说过的原因,极少采用解析执行的方式 目前的大多数解释执行的语言,都是在虚拟机解释字节码执行,这个后面再说,它只是把AST的解释串行化了而已,事实上ruby在1.9版本之前是解释AST执行的,到1.9整合了YAR

  • 这是代码。 输出是''

  • 在下面的代码中,{…{key}}似乎在向html标记添加唯一的键索引,我认为这是React所需要的。但是这种语法是如何工作的呢?我对spread操作符很熟悉,但不知道如何将所有内容组合在一起。此链接https://reactjs.org/docs/lists-and-keys.html 给出了有关键用法的示例,但没有一个使用此语法。

  • 问了这个问题后,我很困惑,于是决定为一个C编译器程序构建类似的测试。这是我的代码: 使用选项在GCC下编译 测试代码被更改,这样错误值只能在运行时知道(而不能在编译时知道),这样GCC优化器就不能删除循环的代码。 我们应该期待CPU的加速吗?(正如GCC编译程序预测的那样)

  • 本文向大家介绍解释行为驱动框架。,包括了解释行为驱动框架。的使用技巧和注意事项,需要的朋友参考一下 行为驱动框架从项目中的所有涉众那里获取信息,比如开发人员、测试人员、产品所有者、经理、客户和业务分析师。这个想法是为了让项目的每个成员都有相同的理解。 行为驱动框架致力于团队中每个人之间的协作和协调。技术编码知识是不必要的,因为功能需求或规范是用非技术性的,通用的语言描述的。 在自动和手动测试人员设

  • 看见http://codepen.io/anon/pen/NGqPNz CSS: JS: 滚动事件在主体元素上触发。滚动条位于body元素上,而不是html或window元素上。那么,为什么要修改文档呢。身体scrollTop或$('body')。scrollTop()返回0? 有什么方法可以检测滚动条的位置,或者我卡住了,如果我想使用高度: 100%;溢出:隐藏在html元素? 谢谢