在基于 SPRING-BOOT JSP 的 web 应用程序中嵌入 VAADIN UI 的 HTTP 405

Posted

技术标签:

【中文标题】在基于 SPRING-BOOT JSP 的 web 应用程序中嵌入 VAADIN UI 的 HTTP 405【英文标题】:HTTP 405 with embedded VAADIN UI in a SPRING-BOOT JSP based webapp 【发布时间】:2017-01-12 07:41:08 【问题描述】:

我已经在基于 Spring Boot 的应用程序的一些 JSP 页面中集成了嵌入 UI 的 Vaadin 7,如 Vaadin Book 中所述。

尽管名为“v-my-vaadin-ui”的 UI 在我调用嵌入它的路径时正确显示(通过 Spring MVC 控制器),但在与 UI 交互时出现 HTTP 405 错误。

错误出现在 URL 上:

http://localhost:8080/v-my-vaadin-ui/UIDL/?v-uiId=4

似乎是因为在 Spring Boot 中,所有控制器默认只允许使用 GET 方法(必须明确允许 POST,如 here 的解释)

已经尝试在我的 Spring 安全配置中禁用 CSRF 并配置 Vaadin 相关路径:

http.authorizeRequests()
.antMatchers("/vaadinServlet/**", 
"/UIDL/**", 
"/v-my-vaadin-ui/UIDL/**", 
"/v-my-vaadin-ui/PUSH/**", 
"/HEARTBEAT/**", "/VAADIN/**").permitAll();
http.csrf().disable();

因为 VAADIN 集成不需要 Spring 管理的 CSRF,但这并不能解决问题。

VAADIN 应用程序非常基础:

@SpringUI(path = "v-my-vaadin-ui")
public class MyVaadinUI extends UI 

    private static final long serialVersionUID = -8129815147461786549L;

    @Override
    protected void init(VaadinRequest vaadinRequest) 

        final TextField name = new TextField("Name");
        final Button greetButton = new Button("Greet");

        greetButton.addClickListener(new ClickListener() 

            @Override
            public void buttonClick(ClickEvent event) 
                Notification.show("Hi " + name.getValue(), 
                                  Notification.Type.HUMANIZED_MESSAGE);
            
        );

        VerticalLayout vl = new VerticalLayout(name, greetButton);
        vl.setSpacing(true);
        setContent(vl);
    


但是点击 Vaadin 按钮,响应码是 405,详细的异常是:

.wsmaResponseStatusExceptionResolver :从处理程序 [ResourceHttpRequestHandler [locations=[ServletContext 资源 [/]、类路径资源 [META-INF/resources/]、类路径资源 [resources/]、类路径资源 [static/] 解决异常, 类路径资源 [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@4a8756c3]]]: org.springframework.web.HttpRequestMethodNotSupportedException: 不支持请求方法'POST'

不幸的是,我没有找到 任何方法来为 UI 配置 POST 方法,因为对于简单的控制器,即通过

@RequestMapping(method = RequestMethod.GET, RequestMethod.POST)

因为这个注解不能用于 Vaadin UI。

此外,如果我使用 URL 直接调用 UI(即不通过 Spring 控制器):

http://localhost:8080/v-my-vaadin-ui

用户界面显示和工作完美。

知道是什么导致了这个问题吗?如何允许 POST 方法?

【问题讨论】:

您能否详细说明您用于嵌入 UI 的 URL 结构?或指向您正在关注的教程的链接?如果您的直接 UI 有效,那么嵌入失败的一种解释是与相关链接混淆。对 UI 本身的调用基本上什么都不做,只是返回嵌入 UI 的“全屏”的 html 【参考方案1】:

你试过这个插件吗? https://vaadin.com/directory#!addon/jsp-integration

【讨论】:

嗨 Alejandro,感谢您的回复,老实说,我不知道您的插件(我刚刚创建了一个自定义标签,它使用 VAADIN 文档中描述的 JS 来嵌入 UI)。我正在尝试将它添加到我的 maven pom.xml 但出现以下异常: 引起:java.lang.ClassNotFoundException: com.vaadin.server.ServiceDestroyListener at java.net.URLClassLoader$1.run(URLClassLoader.java:366 ) ~[na:1.7.0_75] [...] 兼容:vaadin-spring-boot-starter-1.0.0 ? 是的,它支持它。您可能在 pom.xml 中缺少 Vaadin bom 配置:github.com/alejandro-du/springboot-servlet-rest-vaadin-demo/…【参考方案2】:

解决了!!

问题是由我在用于嵌入 VAADIN 应用程序的 JS 脚本中犯的错误引起的(我已在此处遵循文档:https://vaadin.com/docs/-/part/framework/advanced/advanced-embedding.html),尤其是“serviceUrl”参数的代码片段:

"serviceUrl": "helloworld/",

我理解为设置了应用程序的名称,在我的例子中是“v-my-vaadin-ui”。

但在我的情况下,正确的“serviceUrl”仍然是默认一个“vaadinServlet/”,因此更改为:

"serviceUrl": "v-my-vaadin-ui/",

"serviceUrl": "vaadinServlet/",

一切正常。

下面是嵌入适用于我的 vaadin 应用程序的 JSP 标记的完整代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@tag description="ajax widget tag" pageEncoding="UTF-8"%>

<%@attribute name="v_app_url"%>

<%-- javascript as described here: https://vaadin.com/docs/-/part/framework/advanced/advanced-embedding.html --%>

<div>

    <div id="$v_app_url" class="v-app myvaadinui" >
       <div class="v-app-loading"></div>
       <noscript>
        You have to enable javascript in your browser to use an application built with Vaadin.
       </noscript>
    </div>

    <script type="text/javascript">//<![CDATA[
        if (!window.vaadin)
            alert("Failed to load the bootstrap JavaScript: vaadinBootstrap.js");

            /* The UI Configuration */
            vaadin.initApplication("$v_app_url", 
                "browserDetailsUrl": "$v_app_url/",
                "serviceUrl": "vaadinServlet/",
                "widgetset": "com.vaadin.DefaultWidgetSet",
                "theme": "valo",
                "versionInfo": "vaadinVersion": "7.4.4",
                "vaadinDir": "/VAADIN/",
                "heartbeatInterval": 300,
                "debug": false,
                "standalone": false,
                "authErrMsg": 
                    "message": "Take note of any unsaved data, "+
                               "and <u>click here<\/u> to continue.",
                    "caption": "Authentication problem"
                ,
                "comErrMsg": 
                    "message": "Take note of any unsaved data, "+
                               "and <u>click here<\/u> to continue.",
                    "caption": "Communication problem"
                ,
                "sessExpMsg": 
                    "message": "Take note of any unsaved data, "+
                               "and <u>click here<\/u> to continue.",
                    "caption": "Session Expired"
                
            );//]] >
     </script>

</div>

【讨论】:

以上是关于在基于 SPRING-BOOT JSP 的 web 应用程序中嵌入 VAADIN UI 的 HTTP 405的主要内容,如果未能解决你的问题,请参考以下文章

基于spring-boot的kettle调度

基于spring-boot的应用程序的单元测试方案

spring-boot 基本 JSP 404 未找到

spring-boot4

更改 Spring-boot 静态 Web 资源位置?

基于spring-boot的应用程序的单元+集成测试方案