java jetty的classpath_java游戏服引入jetty

本文介绍了如何在Java游戏中处理HTTP请求,首先讲解了使用JDK自带的HttpServer创建轻量级服务,然后详细阐述了Jetty的使用,包括配置文件方式和注解方式,展示了如何在Java游戏中内嵌Jetty以处理HTTP请求,适合并发不高但需要处理HTTP请求的场景。
摘要由CSDN通过智能技术生成

心怀不惧,才能翱翔于天际 --赵云

不管java游戏服采用何种通信协议,几乎都要有处理http请求的需求。因为现在很多游戏服都会接入第三方平台的登录、查询、验证、执行命令等操作(如游戏Web后台需查询玩家数据,修改玩家数据,封号禁言发奖等),而这第三方的请求就几乎都为http请求,因而java游戏服需要有相应的http请求处理方案。

所幸游戏服的http请求往往都是轻量级的,毕竟第三方平台的操作既不频繁也不多。因此我们在选择web连接方案时,最好是能够直接 “嵌入” java游戏服的,而不需要再建立一个web工程。

早期的时候(在JDK1.6时),都是用JDK自带的HttpServer实现的,当然现在也还可以用它,也简单好用。它的使用流程是:

第1步,创建一个HttpServer,并绑定端口和设置最大连接数;

第2步,设置HttpContext服务器监听器上下文,设置匹配URL的公共路径(如/querry)和用来处理请求的HttpHandler;

第3步,调用start方法启动即可。关闭时调用相应stop(int delaySec)。

HttpServerProvider provider = HttpServerProvider.provider();

HttpServer httpserver = null;

try{

httpserver = provider.createHttpServer(new InetSocketAddress(6688), 10);// 设置端口及最大连接数

httpserver.createContext("/querry", new HttpQuerryHandler());

httpserver.setExecutor(Executors.newCachedThreadPool()); // 设置线程池

httpserver.start();

}

catch (Exception e){

log.error("can't start http service of querry ");

}

注意,上述的HttpQuerryHandler需实现HttpHandler接口,继而实现其中的handle(HttpExchange var1)方法,如:

public class HttpQuerryHandler implements HttpHandler{

@Override

public void handle(HttpExchange httpExchange) throws IOException {

String requestMethod = httpExchange.getRequestMethod();

if (requestMethod.equalsIgnoreCase("GET")){

URI requestedUri = httpExchange.getRequestURI();

String param = requestedUri.getQuery(); //如192.168.1.5:6688/querry?user=xiaosheng996&psw=123

System.out.println("param:" + param); //user=xiaosheng996&psw=123

Headers responseHeaders = httpExchange.getResponseHeaders();

responseHeaders.set("Content-Type", "text/plain");

httpExchange.sendResponseHeaders(200, 0);

OutputStream responseBody = httpExchange.getResponseBody();

String result = "{\"ret\": \"ok\"}";

responseBody.write(result.getBytes());

responseBody.flush();

responseBody.close();

}

}

}

这样也实现了处理Http请求。在大多数Http请求不多并发又不大的情况这种已完全足够了。

Jetty是现在用得比较多的一种轻量级Servlet容器,扩展性强而非常灵活,通过引入jetty库,便能“嵌入”在java工程中,非常方便。

Jetty和Tomcat都是使用广泛的Servlet引擎,相对而言Tomcat是重量级的,它在处理少数非常繁忙的连接上更有优势,也就是说连接生命周期如果短,Tomcat的总体性能更高。而Jetty在处理高并发且长时间连接请求的场景下显得更快速高效。

Jetty的使用流程和JDK的HttpServer差不多:

第1步,创建一个Jetty Server,并设置连接器;

第2步,设置web应用上下文WebAppContext,它既可以用传统的服务配置文件的方式设定,也可以用注解的方式设定;

第3步,调用start方法启动即可。关闭时调用相应stop()方法。

在Jetty里Context是包含了在某一特定URL或Virtual Host下的一组Handler的Handler。可以这样理解,Context本身也是一种Handler,它里面包含了许多的Handler,这些Handler都只能处理某个特定URL下的请求。Jetty里的Context有ContextHandler,ServletContext和WebAppContext。

配置文件方式如下:

/**

* 构造jetty web服务

* @param descriptor 配置文件路径

* @param resourceBase 根目录,如果需要隐藏用A,否则用.

* @param maxThreads 连接线程数

* @param ports 监听的端口

* @throws Exception

*/

public JettyServer(String descriptor, String resourceBase, int maxThreads, int port) throws Exception {

this.port = port;

this.server = new Server(new QueuedThreadPool(maxThreads));

ServerConnector connector = new ServerConnector(server);

connector.setPort(port);

this.server.setConnectors(new ServerConnector[] { connector });

WebAppContext context = new WebAppContext();

context.setDescriptor(descriptor);

context.setResourceBase(resourceBase);

context.setClassLoader(Thread.currentThread().getContextClassLoader());

context.setConfigurationDiscovered(true);

context.setParentLoaderPriority(true);

this.server.setHandler(context);

this.server.start();

System.out.println("started JettyServer:" + this.toString()+",config path:"+context.getResourceBase());

}

配置文件:

xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

id="WebApp" version="2.5">

QuerryService

servlet.QuerryService

QuerryService

/QuerryService

处理请求的servlet类,需实现HttpServlet:

public class QuerryService extends PubDefaultServlet {

private static final long serialVersionUID = 3832841412181110307L;

@Override

protected void process(HttpServletRequest req, HttpServletResponse resp)

throws Exception {

System.out.println("enter");

}

}

PubDefaultServlet.java

/**

* servlet父类,覆盖get,post方法

*/

public abstract class PubDefaultServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

protected Logger logger = Logger.getLogger(getClass());

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

req.setCharacterEncoding("UTF-8");

resp.setCharacterEncoding("UTF-8");

resp.setContentType("text/html; charset=UTF-8");

resp.setHeader("Content-Type", "text/html; charset=UTF-8");

logger.info("service :" + req.getRequestURI() + "|" + req.getRemoteAddr() + "|" + req.getMethod() + "|"

+ req.getHeaderNames() + "|" + req.getParameterMap());

super.service(req, resp);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

try {

process(req, resp);

} catch (Exception e) {

resp.getWriter().write(e.getMessage());

logger.error("process :" + req.getRequestURI() + "|" + req.getRemoteAddr() + "|" + req.getMethod() + "|"

+ req.getParameterMap(), e);

}

}

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doPost(req, resp);

}

protected abstract void process(HttpServletRequest req, HttpServletResponse resp) throws Exception;

}

如果不走配置,也可以用如下注解的方式

/**

* 构造jetty web服务

*

* @param serveltList servelt列表

* @param maxThreads 线程池数量

* @param ports 监听的端口

* @throws Exception

*/

public JettyServer(Set> servletClazzs, int maxThreads, int port) throws Exception {

this.port = port;

this.server = new Server(new QueuedThreadPool(maxThreads));

ServerConnector connector = new ServerConnector(server);

connector.setPort(port);

this.server.setConnectors(new ServerConnector[] { connector });

WebAppContext context = new WebAppContext();

context.setConfigurationDiscovered(false);

context.setBaseResource(Resource.newClassPathResource(""));

for (Class> clazz : servletClazzs) {

WebServletAnnotation webServlet = new WebServletAnnotation(context, clazz.getName(), null);

webServlet.apply();

}

context.setClassLoader(Thread.currentThread().getContextClassLoader());

this.server.setHandler(context);

this.server.start();

WEB_SERVERS.add(this);

}

而它的处理请求的servlet实现为:

@HttpServlet

@WebServlet(urlPatterns = "HttpRequest", description = "http请求")

public class HttpRequestServlet extends PubDefaultServlet {

private static final long serialVersionUID = 1L;

@Override

protected void process(HttpServletRequest req, HttpServletResponse resp) throws Exception {

String[] username = req.getParameterValues("username");

String[] password = req.getParameterValues("password");

String[] content = req.getParameterValues("content");

System.out.println("username:"+username[0]+"\npassword:"

+password[0]+"\ncontent:"+content[0]+"\nthreadName:"+Thread.currentThread().getName());

resp.getWriter().write("收到微信小程序的信息:["+username[0]+"|"+password[0]+"|"+content[0]+"]");

//resp.getWriter().write("{\"result\":0,\"data\":\"成功\"}");

resp.getWriter().flush();

}

}

将所有的servlet放在一个包下,然后扫描这个包,获得所有的servlet,作为参数Set> servletClazzs传入JettyServer构造函数,即可实现java游戏服内置jetty,但这种方式在后台需要一个注解处理器才能起作用,所以还得针对上面的注解编写处理器WebServletAnnotation。

处理器的实现参照以下文章:

Servlet传统配置方式和Servlet3.0使用注解的方式

另外,欲了解Jetty的框架原理及源码可参考,个人觉得它和Netty框架类似:

Jetty 源码分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值