tip*_*psy 3 java servlets jetty embedded-jetty kotlin
我正在为嵌入式Jetty制作DSL,但在设置characterEncoding和时遇到问题contentType。我希望用户能够为这两个字段指定默认值,但是Jetty使得生活变得艰难。
res.characterEncoding = null给出res.characterEncoding值iso-8859-1。
res.characterEncoding = "",给出res.characterEncoding值"",但res.contentType变为application/json;charset=
res.characterEncoding = ""THEN res.characterEncoding = null的作用与只是做的一样res.characterEncoding = ""
基于这种奇怪的行为,我最终得到了一个荒谬的代码片段:
if (res.characterEncoding.contains(";javalin-default") || res.contentType.contains(";javalin-default")) {
res.contentType = res.contentType.replace(";javalin-default", "")
res.characterEncoding = null
if (res.contentType.contains("application/json")) {
res.contentType = "application/json"
} else {
res.characterEncoding = defaultCharacterEncoding
}
}
Run Code Online (Sandbox Code Playgroud)
但这不是正确的事情。有任何想法吗?
我在这里有一个问题:https : //github.com/tipsy/javalin/issues/259
您正在解决Servlet规范中过于复杂的方面。
意见:该
HttpServletResponse.setContentType(String)方法不应该存在,应该已经存在.setMimeType(String)并且.setCharacterEncoding(Charset)
让我们从字符编码的重要性开始。
当HttpServletResponse.getWriter()被访问时,实现必须解析用于创建的响应字符编码和语言环境PrintWriter。这意味着此时的字符编码将分配一个值。
请注意,也使用了语言环境,这通常被忽略,但是由于您是库编写者,因此应向您指出。请参阅HttpServletResponse.setLocale(Locale)和HttpServletResponse.getLocale()。
还有一些需要考虑的事情是,如果您已经访问过HttpServletResponse.getWriter(),那么使用HttpServletResponse.setCharacterEncoding(String)更高版本将导致无操作,而使用HttpServletResponse.setContentType(String)带有a charset可能会导致将charset其从产生的标题中剥离。(再次,这符合Servlet规范的行为)。
该HttpServletResponse.getCharacterEncoding()可以返回的字符编码,如果手动设置为一个有效的值早,或者基于Content-Type是否已经声明,否则默认为ISO-8859-1。如果正在使用Content-Type它,则首先检查charset参数并使用它。如果Content-Type没有charset,那么它将使用mime-type您的Web元数据中的配置。此调用绝不能产生空或空字符编码。
所使用的Servlet规范的默认HttpServletResponse.getCharacterEncoding()值为ISO-8859-1(此值取自RFC2616,定义了Servlet规范的这一方面时)。
网络元数据来自网络描述符(又名WEB-INF/web.xml),默认描述符,替代描述符,org/eclipse/jetty/http/mime.properties资源,org/eclipse/jetty/http/encoding.properties存在的其他功能(例如GzipHandler)和程序化配置。
在Jetty中,所有用于mime-type的所有各种配置源都将导致配置的Jetty org.eclipse.jetty.http.MimeTypes对象。
当HttpServletResponse.setCharacterEncoding(String)被调用时,它也有责任修改Content-Type的响应字段和头。
假设.getWriter()尚未调用,使用setCharacterEncoding(null)将删除字段和标头上的任何现有charset参数Content-Type。 setCharacterEncoding("utf-8")将在字段和标题上添加/更改charset参数。utf-8Content-Type
当HttpServletResponse.setContentType(String)被调用时,如果charset提供了参数,它也有责任修改字符编码字段。
知道了所有这些,您将意识到必须注意各种API调用的顺序,尤其是在进行HttpServletResponse.getWriter()调用时。
与其使用Servlet HttpServletResponse API进行管理,不如通过Web元数据application/json在启动Webapp时对其进行控制。
在你的情况,你只是在配置MimeTypes上ServletContextHandler,你的JettyServerUtil.kt创造,没有必要进行任何您所使用的黑客。
由于资源中的定义方式(假定的字符集),Jetty ServletContextHandler和MimeTypes配置的默认行为不会添加字符集。application/jsonorg/eclipse/jetty/http/encoding.properties
例:
package jetty;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.IO;
public class MimeTypeJsonExample
{
public static void main(String[] args) throws Exception
{
Server server = new Server(9090);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(JsonServlet.class, "/demo");
context.addServlet(DefaultServlet.class, "/"); // handle static content and errors for this context
HandlerList handlers = new HandlerList();
handlers.addHandler(context);
handlers.addHandler(new DefaultHandler()); // handle non-context errors
server.setHandler(context);
server.start();
try
{
demonstrateJsonBehavior(server.getURI().resolve("/"));
}
finally
{
server.stop();
}
}
private static void demonstrateJsonBehavior(URI serverBaseUri) throws IOException
{
HttpURLConnection http = (HttpURLConnection) serverBaseUri.resolve("/demo").toURL().openConnection();
dumpRequestResponse(http);
System.out.println();
try (InputStream in = http.getInputStream())
{
System.out.println(IO.toString(in, UTF_8));
}
}
private static void dumpRequestResponse(HttpURLConnection http) throws IOException
{
System.out.println();
System.out.println("----");
System.out.printf("%s %s HTTP/1.1%n", http.getRequestMethod(), http.getURL());
System.out.println("----");
System.out.printf("%s%n", http.getHeaderField(null));
http.getHeaderFields().entrySet().stream()
.filter(entry -> entry.getKey() != null)
.forEach((entry) -> System.out.printf("%s: %s%n", entry.getKey(), http.getHeaderField(entry.getKey())));
}
public static class JsonServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
resp.setHeader("X-Charset", resp.getCharacterEncoding());
writer.println("{\"mode\":[\"a=b\"],\"animals\":[[\"kiwi bird\",\"kea\",\"skink\"]]}");
}
}
}
Run Code Online (Sandbox Code Playgroud)
这导致输出...
2018-06-27 09:00:32.754:INFO::main: Logging initialized @360ms to org.eclipse.jetty.util.log.StdErrLog
2018-06-27 09:00:32.898:INFO:oejs.Server:main: jetty-9.4.11.v20180605; built: 2018-06-05T18:24:03.829Z; git: d5fc0523cfa96bfebfbda19606cad384d772f04c; jvm 9.0.4+11
2018-06-27 09:00:32.969:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@5dd6264{/,null,AVAILABLE}
2018-06-27 09:00:33.150:INFO:oejs.AbstractConnector:main: Started ServerConnector@60707857{HTTP/1.1,[http/1.1]}{0.0.0.0:9090}
2018-06-27 09:00:33.151:INFO:oejs.Server:main: Started @764ms
----
GET http://192.168.0.119:9090/demo HTTP/1.1
----
HTTP/1.1 200 OK
Server: Jetty(9.4.11.v20180605)
X-Charset: utf-8
Content-Length: 58
Date: Wed, 27 Jun 2018 14:00:33 GMT
Content-Type: application/json
{"mode":["a=b"],"animals":[["kiwi bird","kea","skink"]]}
2018-06-27 09:00:33.276:INFO:oejs.AbstractConnector:main: Stopped ServerConnector@60707857{HTTP/1.1,[http/1.1]}{0.0.0.0:9090}
2018-06-27 09:00:33.278:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.ServletContextHandler@5dd6264{/,null,UNAVAILABLE}
Run Code Online (Sandbox Code Playgroud)
如您所见,JsonServlet唯一设置了Content-Typemime-type,访问了PrintWriter,设置了一个标头X-Charset以显示当前字符编码值,然后编写了json内容。
在Content-Type由客户端看到的响应报头中不包括假定charset的utf-8。
| 归档时间: |
|
| 查看次数: |
882 次 |
| 最近记录: |