基于这个问题的答案-[如何将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未经授权
我找出了在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的方式实现它呢? 用例 说这是框架代码: 基本方法 最幼稚(也许是最好的?)方法是要求将外部函数提供给构造函数,然后从该方法中调用它。 框架代码: