org.atmosphere.cpr.AtmosphereMappingException 在 Spring 引导可执行文件 war 文件中

org.atmosphere.cpr.AtmosphereMappingException in Spring Boot executable war file

我有一个 Spring 引导应用程序,我在其中集成了 Atmosphere Framework.

这是 Application.java 文件:

package com.myproject.something;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.core.env.SimpleCommandLinePropertySource;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        addDefaultProfile(app, new SimpleCommandLinePropertySource(args));
        app.run(args);
    }

    private static void addDefaultProfile(SpringApplication app, SimpleCommandLinePropertySource source) {
        if (!source.containsProperty("spring.profiles.active")
                && !System.getenv().containsKey("SPRING_PROFILES_ACTIVE")) {
            app.setAdditionalProfiles("dev");
        }
    }
}

为了将 Atmosphere Framework 集成 到我的 Spring 引导应用程序中,我一直在松散地关注 this resource combining elements from the official Atmosphere Documentation

我最终得到了 类 MyAtmosphereConfig.javaMyAtmosphereManagedService.java:

package com.myproject.something.atmosphere;
import java.util.Collections;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.atmosphere.cpr.AtmosphereServlet;
import org.atmosphere.cpr.ContainerInitializer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

@Configuration
public class MyAtmosphereConfig {
    @Bean
    public EmbeddedAtmosphereInitializer atmosphereInitializer() {
        return new EmbeddedAtmosphereInitializer();
    }

    @Bean
    public ServletRegistrationBean atmosphereServlet() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new AtmosphereServlet(), "/myAtmosphereUrl");
        registration.addInitParameter("org.atmosphere.cpr.packages", "com.myproject.something.atmosphere");
        registration.setLoadOnStartup(1);
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return registration;
    }

    private static class EmbeddedAtmosphereInitializer extends ContainerInitializer
            implements ServletContextInitializer {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            onStartup(Collections.<Class<?>>emptySet(), servletContext);
        }
    }
}

package com.myproject.something.atmosphere;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;
import org.atmosphere.config.service.Disconnect;
import org.atmosphere.config.service.ManagedService;
import org.atmosphere.config.service.Ready;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceFactory;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ManagedService(path = "/myAtmosphereUrl")
public class MyAtmosphereManagedService {

    private final Logger log = LoggerFactory.getLogger(MyAtmosphereManagedService.class);

    @Inject
    public static AtmosphereResourceFactory factory;

    @Inject
    public AtmosphereResource resource;

    @Ready
    public void onReady() throws JSONException {
        String atmosJSessionId = resource.getRequest().getRequestedSessionId();
        log.info("Initiating Atmosphere client connection with jsession = " + atmosJSessionId);
    }

    @Disconnect
    public void onDisconnect() {
        String atmosJSessionId = resource.getRequest().getRequestedSessionId();
        log.info("Unregistering Atmosphere client connection with jsession = " + atmosJSessionId);  
    }
}

我一直在 Eclipse IDE 中开发,将我的 Spring 引导应用程序作为 Java 应用程序执行。 (右键单击 Application.java -> 运行 As -> Java Application)

运行按照上述方式将其设置为来自 Eclipse IDE 的 Java 应用程序- 前面-我的应用程序的结束部分可以 成功访问 Atmosphere Framework 公开的 URL ,如下所示:

(function() {
  'use strict';
  setTimeout(function() {
    // Setup Atmosphere client
    var myAtmosphereUrl = 'http://localhost:8080/myAtmosphereUrl';
    var socket = atmosphere;
    var subSocket;

    var transport = 'sse';
    var request = {
      url : myAtmosphereUrl,
      contentType : "application/json",
      logLevel : 'debug',
      transport : transport,
      trackMessageLength : true,
      reconnectInterval : 5000
    };
      request.onOpen = function(response) {
      transport = response.transport;
      request.uuid = response.request.uuid;
      console.log("onOpen called!");
    };
      request.onMessage = function(response) {
      transport = response.transport;
      request.uuid = response.request.uuid;
      console.log("onMessage called!");
    };
    subSocket = socket.subscribe(request);
  }, 1000);
})();

浏览器控制台 的前端,我看到 HTTP 200 状态代码,在 Eclipse IDE 的后端] 控制台 ,它给我日志消息 Initiating Atmosphere client connection with jsession = A4A8790C27D531FE7B2CD82B5B9C9447

不幸的是,在打包我的项目到可执行war文件并将其作为服务部署在Debian服务器上之后,它不再工作了,在后端的日志中留下一条错误消息:

2017-10-16 10:51:11.143 ERROR 21296 --- [http-nio-8080-exec-2] o.atmosphere.cpr.AsynchronousProcessor   : No AtmosphereHandler found. Make sure you define it inside WEB-INF/atmosphere.xml or annotate using @___Service
2017-10-16 10:51:11.146 ERROR 21296 --- [http-nio-8080-exec-2] o.a.c.c.C.[.[.[/].[atmosphereServlet]    : Servlet.service() for servlet [atmosphereServlet] in context with path [] threw exception

org.atmosphere.cpr.AtmosphereMappingException: No AtmosphereHandler found. Make sure you define it inside WEB-INF/atmosphere.xml or annotate using @___Service
  at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:147) ~[atmosphere-runtime-2.4.5.jar!/:2.4.5]
  at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:115) ~[atmosphere-runtime-2.4.5.jar!/:2.4.5]
  at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:68) ~[atmosphere-runtime-2.4.5.jar!/:2.4.5]
  at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2287) ~[atmosphere-runtime-2.4.5.jar!/:2.4.5]
  at org.atmosphere.cpr.AtmosphereServlet.doPost(AtmosphereServlet.java:191) ~[atmosphere-runtime-2.4.5.jar!/:2.4.5]
  at org.atmosphere.cpr.AtmosphereServlet.doGet(AtmosphereServlet.java:177) ~[atmosphere-runtime-2.4.5.jar!/:2.4.5]
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) ~[spring-boot-1.4.1.RELEASE.jar!/:1.4.1.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:105) ~[spring-boot-actuator-1.4.1.RELEASE.jar!/:1.4.1.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  ...
  at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:107) ~[spring-boot-actuator-1.4.1.RELEASE.jar!/:1.4.1.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.3.RELEASE.jar!/:4.3.3.RELEASE]
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:677) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_111]
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_111]
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.5.jar!/:8.5.5]
  at java.lang.Thread.run(Thread.java:745) [na:1.8.0_111]

浏览器控制台给了我一个 HTTP 500 - Internal Server Error 状态码。

可执行文件war的创建由Maven命令maven package触发,并以这种方式在pom.xml中配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.myproject</groupId>
    <artifactId>something</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>MySomething</name>
    <description>My Something Description</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
    </parent>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>build-info</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <executable>true</executable>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-rest-core</artifactId>
            <version>2.6.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.atmosphere</groupId>
            <artifactId>atmosphere-runtime</artifactId>
            <version>2.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.atmosphere</groupId>
            <artifactId>atmosphere-spring</artifactId>
            <version>2.4.4</version>
        </dependency>
    </dependencies>
</project>

我已经尝试将 atmosphere.xml 文件放入 war 文件WEB-INF 文件夹中,但似乎仍然未拾取带有 @ManagedService 注释的 Servlet。

这是atmosphere.xml的内容,没有解决错误:

<atmosphere-handlers>
    <atmosphere-handler support-session="true"
                        context-root="/"
                        broadcaster="org.atmosphere.cpr.DefaultBroadcaster"
                        class-name="com.myproject.something.atmosphere.MyAtmosphereManagedService">
    </atmosphere-handler>
</atmosphere-handlers>

谁能告诉我我的配置有什么问题,或者这可能是与嵌入式 Tomcat、Atmosphere 和 Spring Boot 的次要版本相关的错误?


编辑:

可以通过克隆 official Atmosphere-Spring-Boot Sample project 并更改 pom.xml 将项目打包到 war 文件来重现此错误:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.atmosphere.samples</groupId>
        <artifactId>atmosphere-samples</artifactId>
        <version>2.5.0-SNAPSHOT</version>
    </parent>
    <artifactId>spring-boot-sample-atmosphere</artifactId>
    <name>Spring Boot Atmosphere Sample</name>
    <description>Spring Boot Atmosphere Sample</description>
    <url>http://projects.spring.io/spring-boot/</url>
  <packaging>war</packaging>

    <organization>
        <name>Pivotal Software, Inc.</name>
        <url>http://www.spring.io</url>
    </organization>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${springboot-version}</version>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <dependency>
            <groupId>org.atmosphere</groupId>
            <artifactId>atmosphere-runtime</artifactId>
            <version>${atmosphere-version}</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>atmosphere-javascript</artifactId>
            <version>2.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${springboot-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${spring-version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${springboot-version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

我找到了两个修复程序。

第一次修复:
1. 将 pom.xml 中的 Spring 引导版本更改为:

<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.7.RELEASE</version>
</parent>

2。完成!

第二次修复:(如果不能更改版本)

  1. 将您的项目打包成一个jar文件,然后@ManagedServices被识别。

注意:您可能需要在打包前将静态文件(js和html)复制到您的pom.xml中。

如果您正在使用 Spring boot 2 然后使用下面的配置测试。

@Bean
public ServletRegistrationBean < HttpServlet > PushServlet() {
    ServletRegistrationBean pushServlet = new ServletRegistrationBean(new org.primefaces.push.PushServlet(), "/primepush/*");
    pushServlet.addInitParameter("org.atmosphere.annotation.packages", "org.primefaces.push");
    pushServlet.addInitParameter("org.atmosphere.cpr.packages", "com.ik");
    pushServlet.setAsyncSupported(true);
    pushServlet.setLoadOnStartup(0);
    pushServlet.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return pushServlet;
}

com.ik是你的工程包名,就是scan