java - Spring Boot 应用程序中的 Vaadin 23 Rest-API 和 UI

标签 java spring-boot rest vaadin vaadin-flow

我使用 Vaadin 23.3.5 开发了一个小型应用程序。到目前为止,我仅将 Spring Boot Security 与默认的 LoginView 结合使用来进行身份验证,然后使用 MainLayout 来浏览我的应用程序。但现在我需要能够从应用程序外部访问某些信息。因此,最好的方法是实现 REST-API。

但无论我尝试什么,我似乎都无法让它发挥作用。我读到,当我想要无状态 Web 服务时,我不应该将 JAX-RS 与 Spring Boot 应用程序一起使用,因此我尝试坚持使用 Spring 提供的库。我还尝试将其他人的工作示例集成到我的应用程序中,但没有一个对我有用。

我想要进行一些配置,当我使用 http://localhost:8080/project/ui 时,我可以访问我的 View 层(即 LoginView),但是当我使用 http://localhost:8080/project 时/api,我希望能够调用我的网络服务。

在我的 applicatoin.properties 中,我声明“/project”为我的上下文路径,“/ui/*”为我的 urlMapping,如下所示:

server.servlet.context-path=/project
server.port=${PORT:8080}

vaadin.urlMapping=/ui/*
vaadin.excludeUrls=/api/**

我的类中使用的配置从 VaadinWebSecurity 扩展:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        setLoginView(http, LoginView.class, LOGOUT_SUCCESS_URL);

        this.applyUrlMapping("api");

        http.rememberMe().key("ABC")
            .tokenValiditySeconds(2 * 24 * 60 * 60)
            .userDetailsService(this.userDetailsService);
        http.logout()
            .invalidateHttpSession(true)
            .deleteCookies("JSESSIONID", "remember-me");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
        web.ignoring().antMatchers("/images/*.png");
    }

最后我想通过 postman 访问我的 Controller 类:

@RequestMapping("/test")
@RestController()
public class TestRestController {


    @GetMapping("/hello")
public String hello() {
return "Hello World!";
    }

}

在浏览器中使用 http://localhost:8080/project/test/hello 时,我似乎可以访问“hello”方法,但有两件事不起作用:

  1. 无法识别“/api/*”路径
  2. (这一点更关键)当我使用 postman 访问相同的资源时,我可以使用一些自动生成的文档作为响应而不是“Hello World”...
<!doctype html><!--
This file is auto-generated by Vaadin.
-->
<html lang="en">
 <head>
  <script initial="">window.Vaadin = window.Vaadin || {};window.Vaadin.VaadinLicenseChecker = {  maybeCheck: (productInfo) => {  }};window.Vaadin.devTools = window.Vaadin.devTools || {};window.Vaadin.devTools.createdCvdlElements = window.Vaadin.devTools.createdCvdlElements || [];const originalCustomElementDefineFn = window.customElements.define;window.customElements.define = function (tagName, constructor, ...args) {const { cvdlName, version } = constructor;if (cvdlName && version) {  const { connectedCallback } = constructor.prototype;  constructor.prototype.connectedCallback = function () {    window.Vaadin.devTools.createdCvdlElements.push(this);    if (connectedCallback) {      connectedCallback.call(this);    }  }}originalCustomElementDefineFn.call(this, tagName, constructor, ...args);};</script>
  <script initial="">window.Vaadin = window.Vaadin || {};window.Vaadin.ConsoleErrors = window.Vaadin.ConsoleErrors || [];const browserConsoleError = window.console.error.bind(window.console);console.error = (...args) => {    browserConsoleError(...args);    window.Vaadin.ConsoleErrors.push(args);};window.onerror = (message, source, lineno, colno, error) => {const location=source+':'+lineno+':'+colno;window.Vaadin.ConsoleErrors.push([message, '('+location+')']);};window.addEventListener('unhandledrejection', e => {    window.Vaadin.ConsoleErrors.push([e.reason]);});</script>
  <script initial="">window.Vaadin = window.Vaadin || {};window.Vaadin.TypeScript= {};</script>
  <meta name="_csrf_parameter" content="_csrf">
  <meta name="_csrf_header" content="X-CSRF-TOKEN">
  <meta name="_csrf" content="df39cb78-0c37-4125-8d87-68e986050db5"><base href=".">
  <script type="text/javascript">window.JSCompiler_renameProperty = function(a) { return a;}</script>
  <script type="module">import { inject } from "/project/ui/VAADIN/@vite-plugin-checker-runtime";
inject({
  overlayConfig: {},
  base: "/project/ui/VAADIN/",
});</script>
  <script type="module" src="/project/ui/VAADIN/@vite/client"></script>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body, #outlet {
      height: 100vh;
      width: 100%;
      margin: 0;
    }
  </style> <!-- index.ts is included here automatically (either by the dev server or during the build) -->
  <script type="module" src="/project/ui/VAADIN/generated/vite-devmode.ts"></script>
  <script type="module" src="/project/ui/VAADIN/generated/vaadin.ts"></script>
  <style>.v-reconnect-dialog,.v-system-error {position: absolute;color: black;background: white;top: 1em;right: 1em;border: 1px solid black;padding: 1em;z-index: 10000;max-width: calc(100vw - 4em);max-height: calc(100vh - 4em);overflow: auto;} .v-system-error {color: indianred;pointer-events: auto;} .v-system-error h3, .v-system-error b {color: red;}</style>
  <style>[hidden] { display: none !important; }</style>
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="apple-touch-fullscreen" content="yes">
  <meta name="apple-mobile-web-app-title" content="project">
  <meta name="theme-color" content="#ffffff">
  <meta name="apple-mobile-web-app-status-bar-style" content="#ffffff">
  <link rel="manifest" href="manifest.webmanifest">
  <link sizes="16x16" rel="shortcut icon" href="icons/icon-16x16.png" type="image/png">
  <link sizes="32x32" rel="icon" href="icons/icon-32x32.png" type="image/png">
  <link sizes="96x96" rel="icon" href="icons/icon-96x96.png?1713631522" type="image/png">
  <link sizes="180x180" rel="apple-touch-icon" href="icons/icon-180x180.png?-533695959" type="image/png">
  <link sizes="2048x2732" rel="apple-touch-startup-image" media="screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-2048x2732.png?-1201942874" type="image/png">
  <link sizes="2732x2048" rel="apple-touch-startup-image" media="screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-2732x2048.png?266277477" type="image/png">
  <link sizes="1668x2388" rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-1668x2388.png?-1539431919" type="image/png">
  <link sizes="2388x1668" rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-2388x1668.png?598404288" type="image/png">
  <link sizes="1668x2224" rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-1668x2224.png?1678662124" type="image/png">
  <link sizes="2224x1668" rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-2224x1668.png?746534339" type="image/png">
  <link sizes="1620x2160" rel="apple-touch-startup-image" media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-1620x2160.png?-770300885" type="image/png">
  <link sizes="2160x1620" rel="apple-touch-startup-image" media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-2160x1620.png?-525914264" type="image/png">
  <link sizes="1536x2048" rel="apple-touch-startup-image" media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-1536x2048.png?713310212" type="image/png">
  <link sizes="2048x1536" rel="apple-touch-startup-image" media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-2048x1536.png?1750378074" type="image/png">
  <link sizes="1284x2778" rel="apple-touch-startup-image" media="screen and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="icons/icon-1284x2778.png?1984992155" type="image/png">
  <link sizes="2778x1284" rel="apple-touch-startup-image" media="screen and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="icons/icon-2778x1284.png?389448020" type="image/png">
  <link sizes="1170x2532" rel="apple-touch-startup-image" media="screen and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="icons/icon-1170x2532.png?-743684054" type="image/png">
  <link sizes="2532x1170" rel="apple-touch-startup-image" media="screen and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="icons/icon-2532x1170.png?2114630635" type="image/png">
  <link sizes="1125x2436" rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="icons/icon-1125x2436.png?-688834165" type="image/png">
  <link sizes="2436x1125" rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="icons/icon-2436x1125.png?-221066565" type="image/png">
  <link sizes="1242x2688" rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="icons/icon-1242x2688.png?-313405698" type="image/png">
  <link sizes="2688x1242" rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="icons/icon-2688x1242.png?20506735" type="image/png">
  <link sizes="828x1792" rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-828x1792.png?1276193420" type="image/png">
  <link sizes="1792x828" rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-1792x828.png?1725405299" type="image/png">
  <link sizes="1242x2208" rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="icons/icon-1242x2208.png?1508207887" type="image/png">
  <link sizes="2208x1242" rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="icons/icon-2208x1242.png?-167637239" type="image/png">
  <link sizes="750x1334" rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-750x1334.png?-1346703542" type="image/png">
  <link sizes="1334x750" rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-1334x750.png?-1196513029" type="image/png">
  <link sizes="640x1136" rel="apple-touch-startup-image" media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="icons/icon-640x1136.png?893776263" type="image/png">
  <link sizes="1136x640" rel="apple-touch-startup-image" media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="icons/icon-1136x640.png?-1834685424" type="image/png">
  <script>if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('sw.js')
  });
}</script>
 </head>
 <body><!-- This outlet div is where the views are rendered -->
  <div id="outlet"></div>
  <script>window.Vaadin = window.Vaadin || {};
window.Vaadin.registrations = window.Vaadin.registrations || [];
window.Vaadin.registrations.push({"is":"flow/SpringInstantiator","version":"23.3.0.alpha1"},{"is":"routing/server","version":"23.3.0.alpha1"},{"is":"flow/AtmospherePushConnection","version":"2.7.3.slf4jvaadin4"},{"is":"java","version":"17.0.5"});</script><vaadin-dev-tools url="" springbootlivereloadport="35729"></vaadin-dev-tools>
 </body>
</html>

我尝试使用来自 Stackoverflow 和 Vaadin 官方论坛的代码示例,以及来自 Github 和其他地方的示例。但我发现没有任何示例或描述能够满足我的要求,因为“:8080/project/ui/”和“:8080/project/api/”一起工作。

有人可以给我指出正确的方向吗?

最佳答案

@RequestMapping("/test") 

不包含api!所以应该是:

@RequestMapping("/api/test")

那么您还必须调整安全配置:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
   .requestMatchers(new AntPathRequestMatcher("/api/**").permitAll();

    super.configure(http);
    setLoginView(http, LoginView.class, LOGOUT_SUCCESS_URL);


    http.rememberMe().key("ABC")
        .tokenValiditySeconds(2 * 24 * 60 * 60)
        .userDetailsService(this.userDetailsService);

    http.logout()
        .invalidateHttpSession(true)
        .deleteCookies("JSESSIONID", "remember-me");
}

@Override
public void configure(WebSecurity web) throws Exception {
    super.configure(web);
    web.ignoring().antMatchers("/images/*.png");
}

关于java - Spring Boot 应用程序中的 Vaadin 23 Rest-API 和 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75372808/

相关文章:

java - 如何计算 Android 应用程序运行时间 ~Android

java - 即使在设置 noCursorTimeout 后也找不到 mongo 游标

spring - 如何在 Spring Boot 休息服务方法中设置响应 header value ?

java - org.json JSONObject 在从 Spring Boot Controller 返回时向 JSONObject 添加额外的对象

jquery - 不允许通过 REST api 和 jquery 405 方法创建 Jira 问题

java - @Autowired 注释的放置

java - 使用 Java 桌面应用程序中的 API 更新 Dropbox(或 Drive)共享文件中的数据

ssl - Spring Boot 调用 HTTPS 端点

java - 将空字符串设置为 xsi :nil=true

mongodb - Sinatra + MongoDB 导致 unRESTful API?