当前位置: 首页 > 知识库问答 >
问题:

让Jersey 2与嵌入式Tomcat一起工作的依赖性是什么

充星腾
2023-03-14

基于这个问题的答案-[如何将Jersey REST Web服务添加到嵌入式tomcat中?

这似乎对其他人有用。是否有人有一个GIT项目或maven项目所需的依赖项列表,该项目将用于嵌入式tomcat(v8. x或更新版本)和泽西v2. x的REST终结点?

这是POM文件

http://maven.apache.org/xsd/maven-4.0.0.xsd"

<artifactId>unsprung-tomcat-container</artifactId>
<version>0.1.0-beta</version>
<packaging>jar</packaging>

<properties>
    <tomcat.version>8.5.23</tomcat.version>
    <jersey.version>2.26</jersey.version>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.2.4</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.inject</groupId>
        <artifactId>jersey-hk2</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>${jersey.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

下面是启动tomcat的类:

公共类Main{

// constants
private static final String JERSEY_SERVLET_NAME = "jersey-container-servlet";

// Base URI the HTTP server will listen on
public static final String APP_NAME = "api";
public static final String BASE_URI = "http://localhost:8080/"+APP_NAME+"/";

// attributes
private static String baseUrl;

public static Tomcat startServer(boolean useSsl) throws Exception {
    // create server configuration
    final ResourceConfig rc = new ResourceConfig()
                    .packages("cs.toolkit.ms.tomcat")
                    .registerClasses(GsonMessageBodyHandler.class;

    String port = System.getenv("PORT");
    if (port == null || port.isEmpty()) {
        port = "8080";
    }

    String contextPath = "";
    String appBase = ".";

    Tomcat tomcat = new Tomcat();
    tomcat.setPort(Integer.valueOf(port));
    tomcat.getHost().setAppBase(appBase);

    Context context = tomcat.addContext(contextPath, appBase);
    Tomcat.addServlet(context, JERSEY_SERVLET_NAME,
            new ServletContainer(rc));
    context.addServletMappingDecoded("/api/*", JERSEY_SERVLET_NAME);

    tomcat.start();

    return tomcat;
}

}

下面是包含endpoint的资源类

@Path("/")

公共类MyResource{

/**
 * Method handling HTTP GET requests.The returned object will be sent 
 * to the client as "text/plain" media type.
 *
 * @param requestType - request type URI
 * @return TestPojo object
 */
@GET
@Path("{requestType}")
@Produces(MediaType.APPLICATION_JSON)
public TestPojo getIt(@PathParam("requestType") String requestType) {
    TestPojo pojo = new TestPojo();
    pojo.setName(requestType);

    return pojo;
}

}

...启动服务器后,这里是我用来测试endpoint的代码

    ClientConfig clientConfig = new ClientConfig();


    Client client = ClientBuilder.newBuilder()
            .withConfig(clientConfig)
            .build();

    client.register(GsonMessageBodyHandler.class);
    target = client.target(Main.BASE_URI);

    String responseMsg = target.path("hello").request().get(String.class);

...这是我得到的错误

javax。ws。rs.NotAuthorizedException:HTTP 401未经授权

共有1个答案

魏风华
2023-03-14

我找出了在restendpoint上启动和接受请求的嵌入式tomcat实例所需的依赖项。

pom文件:

    `<properties>
        <!--using tomcat 8.x-->
        <tomcat.version>8.5.47</tomcat.version>
        <tomcat-logging.version>8.5.2</tomcat-logging.version>
        <jersey-mvc.version>2.28</jersey-mvc.version>
        <json.version>2.8.6</json.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>`

    <dependencies>
        <!--Jersey 2 support-->
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-mvc-freemarker</artifactId>
            <version>${jersey-mvc.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
                <!--jersey-mvc-jsp already has jersey-mvc-->
                <exclusion>
                    <groupId>org.glassfish.jersey.ext</groupId>
                    <artifactId>jersey-mvc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>${jersey-mvc.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-mvc-jsp</artifactId>
            <version>${jersey-mvc.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Dependencies for Embedded Tomcat -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-servlet-api</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-logging-juli</artifactId>
            <version>${tomcat-logging.version}</version>
        </dependency>
        <dependency>
            <!-- required for LifecycleContainer -->
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

        <!--JSON support-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>${json.version}</version>
        </dependency>

        <!--unit testing-->
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey-mvc.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>1.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

主要的班

    public class Main {
    // constants
    public static int PORT = 8443;

    public static final String KEYSTORE_SERVER_FILE = "keystore_server";
    public static final String KEYSTORE_SERVER_PWD = "asdfgh";
    public static final String TRUSTORE_SERVER_FILE = "truststore_server";
    public static final String TRUSTORE_SERVER_PWD = "asdfgh";

    // attributes
    private static Tomcat tomcat;

    public static void stop() throws LifecycleException {
        tomcat.stop();
    }

    public static void start(String... args) throws Exception {
        // set system properties for configuring tomcat
        System.setProperty("tomcat.util.scan.StandardJarScanFilter.jarsToSkip", "*.jar"); // skip TLD/JSP scanning

        // create server instance
        tomcat = new Tomcat();

        //set tomcat port form yml configuration file
        tomcat.setPort(PORT);
        System.out.println("Tomcat running on port : " + PORT);

        // set SSL connector
        Connector httpsConnector = getSslConnector();
        tomcat.getService().addConnector(httpsConnector);
        tomcat.setConnector(httpsConnector);

        // create web-app
        File base = new File("src/main/webapp");
        Context context = tomcat.addContext("/api", base.getAbsolutePath());
        tomcat.addWebapp(null, "", base.getAbsolutePath());

        System.out.println("WEB-URI base path: " + base.getAbsolutePath());


        Tomcat.addServlet(context, "jersey-container-servlet", resourceConfig());
        context.addServletMapping("/*", "jersey-container-servlet");

        // start server
        tomcat.start();

    }

    private static Connector getSslConnector() {
        Path ksfPath = FileSystems.getDefault().getPath(KEYSTORE_SERVER_FILE);
        Path tsfPath = FileSystems.getDefault().getPath(TRUSTORE_SERVER_FILE);

        Connector connector = new Connector();
        connector.setPort(PORT);
        connector.setSecure(true);
        connector.setScheme("https");
        connector.setAttribute("keystoreType", "JKS");
        connector.setAttribute("keystorePass", KEYSTORE_SERVER_PWD);
        connector.setAttribute("keystoreFile",
                ksfPath.toFile().getAbsolutePath() );
        connector.setAttribute("trustStorePassword", TRUSTORE_SERVER_PWD);
        connector.setAttribute("trustStoreFile",
                tsfPath.toFile().getAbsolutePath() );
        connector.setAttribute("clientAuth", "false");
        connector.setAttribute("protocol", "HTTP/1.1");
        connector.setAttribute("sslProtocol", "TLSv1.2");
        connector.setAttribute("maxThreads", "200");
        connector.setAttribute("SSLEnabled", true);

        return connector;
     }    

    private static ServletContainer resourceConfig() {
        System.out.println("Scanning package: " + Main.class.getPackage().getName());
        final ResourceConfig config = new ResourceConfig()
                .packages(Main.class.getPackage().getName())
                .registerClasses( GsonMessageBodyHandler.class
                                , SecurityFilter.class
                                , AuthenticationExceptionMapper.class )
                .register(Resource.class)
                .register(MyResource.class)
                ;

        return new ServletContainer(config);
    }

}

具有Rest终结点的资源类

    @Path("/")
public class MyResource {

    /**
     * Method handling HTTP GET requests.The returned object will be sent 
     * to the client as "text/plain" media type.
     *
     * @param requestType - request type URI
     * @return TestPojo object
     */
    @GET
    @Path("{requestType}")
    @Produces(MediaType.APPLICATION_JSON)
    public TestPojo getIt(@PathParam("requestType") String requestType) {
        TestPojo pojo = new TestPojo();
        pojo.setName(requestType);

        return pojo;
    }
}

JSON读者-作者

`@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)`

    public class GsonMessageBodyHandler implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
    // constants
    private static final String UTF_8 = "UTF-8";

    // attributes
    private Gson gson;

    // support

    //Customize the gson behavior here
    private Gson getGson() {
        if (gson == null) {
            final GsonBuilder gsonBuilder = new GsonBuilder();
            gson = gsonBuilder.disableHtmlEscaping()
                    .setPrettyPrinting()
                    .serializeNulls()
                    .create();
        }
        return gson;
    }

    @Override
    public boolean isReadable(Class<?> type, Type genericType,
            java.lang.annotation.Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public Object readFrom(Class<Object> type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, String> httpHeaders, InputStream entityStream) {
        InputStreamReader streamReader = null;
        try {
            streamReader = new InputStreamReader(entityStream, UTF_8);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            Type jsonType;
            if (type.equals(genericType)) {
                jsonType = type;
            } else {
                jsonType = genericType;
            }
            return getGson().fromJson(streamReader, jsonType);
        } finally {
            try {
                streamReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public long getSize(Object object, Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public void writeTo(Object object, Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, Object> httpHeaders,
            OutputStream entityStream) throws IOException,
            WebApplicationException {
        OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
        try {
            Type jsonType;
            if (type.equals(genericType)) {
                jsonType = type;
            } else {
                jsonType = genericType;
            }
            getGson().toJson(object, jsonType, writer);
        } finally {
            writer.close();
        }
    }
}

身份验证支持

@Provider
@PreMatching

    public class SecurityFilter implements ContainerRequestFilter {

    @Inject
    javax.inject.Provider<UriInfo> uriInfo;
    private static final String REALM = "HTTPS Example authentication";

    @Override
    public void filter(ContainerRequestContext filterContext) throws IOException {
        User user = authenticate(filterContext);
        filterContext.setSecurityContext(new Authorizer(user));
    }

    private User authenticate(ContainerRequestContext filterContext) {
        // Extract authentication credentials
        String authentication = filterContext.getHeaderString(HttpHeaders.AUTHORIZATION);
        if (authentication == null) {
            throw new AuthenticationException("Authentication credentials are required", REALM);
        }
        if (!authentication.startsWith("Basic ")) {
            return null;
            // additional checks should be done here
            // "Only HTTP Basic authentication is supported"
        }
        authentication = authentication.substring("Basic ".length());
        String[] values = new String(DatatypeConverter.parseBase64Binary(authentication), Charset.forName("ASCII")).split(":");
        if (values.length < 2) {
            throw new WebApplicationException(400);
            // "Invalid syntax for username and password"
        }
        String username = values[0];
        String password = values[1];
        if ((username == null) || (password == null)) {
            throw new WebApplicationException(400);
            // "Missing username or password"
        }

        // Validate the extracted credentials
        User user;

        if (username.equals("user") && password.equals("password")) {
            user = new User("user", "user");
            System.out.println("USER AUTHENTICATED");
        } else {
            System.out.println("USER NOT AUTHENTICATED");
            throw new AuthenticationException("Invalid username or password\r\n", REALM);
        }
        return user;
    }

    public class Authorizer implements SecurityContext {

        private User user;
        private Principal principal;

        public Authorizer(final User user) {
            this.user = user;
            this.principal = new Principal() {

                public String getName() {
                    return user.username;
                }
            };
        }

        public Principal getUserPrincipal() {
            return this.principal;
        }

        public boolean isUserInRole(String role) {
            return (role.equals(user.role));
        }

        public boolean isSecure() {
            return "https".equals(uriInfo.get().getRequestUri().getScheme());
        }

        public String getAuthenticationScheme() {
            return SecurityContext.BASIC_AUTH;
        }
    }

    public class User {

        public String username;
        public String role;

        public User(String username, String role) {
            this.username = username;
            this.role = role;
        }
    }
}

异常处理:

@Provider

    public class AuthenticationExceptionMapper implements ExceptionMapper<AuthenticationException> {

    @Override
    public Response toResponse(AuthenticationException e) {
        if (e.getRealm() != null) {
            return Response
                    .status(Status.UNAUTHORIZED)
                    .header("WWW-Authenticate", "Basic realm=\"" + e.getRealm() + "\"")
                    .type("text/plain")
                    .entity(e.getMessage())
                    .build();
        } else {
            return Response
                    .status(Status.UNAUTHORIZED)
                    .type("text/plain")
                    .entity(e.getMessage())
                    .build();
        }
    }

}

注意:Exc0019类没什么特别的。

请求和响应中的POJO

    public class TestPojo {
    private String name = "TEST";
    private int id = 0x3;

    // ctor
    public TestPojo() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }


}

最后是测试类

    public class ResourceTest {
    // constants
    public static final String TRUSTORE_CLIENT_FILE = "./truststore_client";
    public static final String TRUSTSTORE_CLIENT_PWD = "asdfgh";
    public static final String KEYSTORE_CLIENT_FILE = "./keystore_client";
    public static final String KEYSTORE_CLIENT_PWD = "asdfgh";

    public ResourceTest() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
        Main.start(new String[1]);
    }

    @AfterClass
    public static void tearDownClass() throws LifecycleException {
        Main.stop();
    }

    @Before
    public void setUp() {
    }

    @After
    public void tearDown() {
    }

    /**
     * Test of get method, of class Resource.
     * @throws java.lang.InterruptedException
     */
    @Ignore
    public void testGet() throws InterruptedException {
        System.out.println("get");

        synchronized(this) {
            this.wait(30000);
        }

        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    /**
     * Test of getUser method, of class Resource.
     */
    @Test
    public void testGetTestPojoWithAuth() {
        System.out.println("get TestPojo with basic authentication");

        SslConfigurator sslConfig = SslConfigurator.newInstance()
                .securityProtocol("TLSv1.2")
                .trustStoreFile(TRUSTORE_CLIENT_FILE)
                .trustStorePassword(TRUSTSTORE_CLIENT_PWD)
                .keyStoreFile(KEYSTORE_CLIENT_FILE)
                .keyPassword(KEYSTORE_CLIENT_PWD);

        final SSLContext sslContext = sslConfig.createSSLContext();
        Client client = ClientBuilder.newBuilder()
                                    .register(HttpAuthenticationFeature.basic("user", "password"))
                                    .sslContext(sslContext)
                                    .register(GsonMessageBodyHandler.class)
                                    .build();

        client.property(ClientProperties.CONNECT_TIMEOUT, 1000);
        client.property(ClientProperties.READ_TIMEOUT, 10000);

        String requestType = "test-type";
        TestPojo responseMsg = client.target( "https://localhost:"+Main.PORT+"/api/")
                                    .path("/" + requestType)
                                    .request()
                                    .get()
                                    .readEntity(TestPojo.class);

        assertEquals(requestType, responseMsg.getName());
    }

    /**
     * Test of getUser method, of class Resource.
     */
    @Test
    public void testGetTestPojoWithInvalidAuth() {
        System.out.println("get TestPojo with invalid authentication");

        SslConfigurator sslConfig = SslConfigurator.newInstance()
                .securityProtocol("TLSv1.2")
                .trustStoreFile(TRUSTORE_CLIENT_FILE)
                .trustStorePassword(TRUSTSTORE_CLIENT_PWD)
                .keyStoreFile(KEYSTORE_CLIENT_FILE)
                .keyPassword(KEYSTORE_CLIENT_PWD);

        final SSLContext sslContext = sslConfig.createSSLContext();
        Client client = ClientBuilder.newBuilder()
                                    .register(HttpAuthenticationFeature.basic("bad-user", "bad-password"))
                                    .sslContext(sslContext)
                                    .register(GsonMessageBodyHandler.class)
                                    .build();

        client.property(ClientProperties.CONNECT_TIMEOUT, 1000);
        client.property(ClientProperties.READ_TIMEOUT, 10000);

        String requestType = "test-type";
        Response response = client.target( "https://localhost:"+Main.PORT+"/api/")
                                    .path("/" + requestType)
                                    .request()
                                    .get();

        assertEquals(401, response.getStatus());
    }

}

请注意以下事项:

所有类都在应用程序项目中的同一个包中找到。这允许我在设置ResouceConfig.packages(...)方法时只使用Main.class包名称。

您需要在项目的/src/main下创建一个“webapp”文件夹,否则容器可能无法正常启动。这是tomcat遗留下来的东西。

您的证书将用于创建您自己的证书…;)或者您可以只注释掉SSL代码。你的选择

祝你好运

 类似资料:
  • 我想从Spring Boot应用程序创建一个war文件,我可以将其部署到独立的Tomcat容器中,而不是使用嵌入式容器。 我可以创建war文件,并使用单独运行它,它工作得很好。 我使用(使用Gradle、Tomcat7、Java1.7)构建了应用程序。 但当我将war文件部署到独立的Tomcat并启动它时,根据日志显示,应用程序似乎没有错误地启动,但我无法访问任何资源,控制器URL也无法工作。 当

  • 我正在编写一个Web项目,它使用了Apache Tomcat 5.0和JDK 1.4.2之上的Spring框架2.5。 当Tomcat启动时,它从未加载Spring。 Web.xml如下: "web-Application ationContext.xml"就像: 控制台提供了以下日志堆栈跟踪: 严重:配置类org的应用程序侦听器时出错。springframework。网状物上下文ContextL

  • 因此,如果我不能重写字符串作为它的最终结果(因此阻止我重写它的compareTo()方法来调用compareToIgnoreCase()),那么还有其他方法可以实现吗? 任何帮助都是非常感谢的。

  • 我已经成功地在我的Windows机器上安装了gnuradio,并尝试将随附的python环境(Python 2.7)与PyCharm v2018集成。我创建了一个新项目,并为包添加了一个用户定义的路径,以指向所有gnuradio库的位置(C:\Program Files\GNURadio-3.7\lib\site-包)。 在Pycharm可以毫无怨言地看到所有gnuradio包的意义上,一切似乎都

  • 我们在Jetty上使用Spring Boot(2.7.x)。依赖扫描器告诉我们,依赖树中仍然有Tomcat依赖。 当查看spring boot starter jetty 2.7.1的POM时,我发现spring boot starter jetty依赖于tomcat embed el。tomcat嵌入el包含来自javax的类。el和组织。阿帕奇。el包,所以我认为这是Tomcat的表达式语言解

  • 问题内容: 对于Java,依赖注入作为纯OOP工作,即,您提供要实现的接口,并且在框架代码中接受实现已定义接口的类的实例。 现在,对于Python,您可以以相同的方式进行操作,但是对于Python,我认为该方法的开销太大。那么,您将如何以Pythonic的方式实现它呢? 用例 说这是框架代码: 基本方法 最幼稚(也许是最好的?)方法是要求将外部函数提供给构造函数,然后从该方法中调用它。 框架代码: