jetty.xml用于配置服务器Server。默认的情况下,配置了线程池,connector,还有处理请求的handler。我们可以通过添加handler来为服务器添加一些默认的功能。
下面的例子,用于为服务器添加统计功能,统计各个web应用的访问数量。
在这之前先看看默认的handler,
<Set name="handler">
<New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
</Item>
<Item>
<New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
handler的类型是HandlerCollection,之前的文章中提到了HandlerCollection的作用:多个Handler的集合,请求到来时,依次调用各个handler处理这请求,即使某个请求已经做出响应,仍然继续执行。第一个handler是ContextHandlerCollection用于根据context path请求相应的webapp。这个handler会对请求做出响应。
那么我们可以将我们自定义的handler添加到这个handler之后。这个handler的实现如下,
package org.eclipse.jetty.myhandler;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
public class MyHandler extends AbstractHandler {
// 多线程保证
private ConcurrentHashMap<String, Integer> record = new ConcurrentHashMap<String, Integer>();
@Override
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// 判断请求是否被处理,也就是context path是否存在
if (baseRequest.isHandled()){
// path已经访问过 ,count + 1
if (record.containsKey(target)){
record.replace(target, record.get(target) + 1);
}
// path还未访问过, count = 1
else{
record.put(target, 1);
}
return;
}
// 不存在时,打印信息
System.out.println(target + "is not existed.");
}
}
主要就是定义一个hashmap用于存放路径和访问数,主要的处理流程如注释所示,不是很复杂。注意编写handler的时候,需要引入相应的包。
将文件打包,如test.jar。那么这个包放置到哪里比较合适呢?
查看start.ini文件,
OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations
其中ext,文件用于存放扩展文件。那么我们的扩展功能放置到这里还是比较合适的。
接下来修改jetty.xml,将handler添加上去。
<Set name="handler">
<New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
</Item>
<Item>
<New id="CountHandler" class="org.eclipse.jetty.myhandler.MyHandler"/>
</Item>
<Item>
<New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
其中的CountHandler就是我们新定义的handler。
假设这时我们已经放置了webapp,webapp的context path是“webapp1”。
启动服务器,分别访问路径,
http://localhost:8080/webapp1/
http://localhost:8080/webapp12/
http://localhost:8080/webapp/
http://localhost:8080/webapp333/
http://localhost:8080/webapp1/
那么可以看到控制打印出的信息,
也就是说上面访问的地址中2~4都是不存在的。
接下来看看webapp1被访问了几次。修改上面的代码,如下
// 判断请求是否被处理,也就是context path是否存在
if (baseRequest.isHandled()) {
// path已经访问过 ,count + 1
if (record.containsKey(target)) {
record.replace(target, record.get(target) + 1);
}
// path还未访问过, count = 1
else {
record.put(target, 1);
}
return;
}
if ("/countCondition".equalsIgnoreCase(target)) {
response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().print(record.toString());
return;
}
// 不存在时,打印信息
System.out.println(target + "is not existed.");
添加新的context path用于在页面上显示访问的数据。由于countContidion在webapps目录下没有对应的webapp,因此ContextHandlerCollection不会对这个请求做出响应,因此在我们自定义的handler中对这个请求做出响应,将其拦截,防止调用DefaultHandler返回404页面。
通过在页面上输入地址,
http://localhost:8080/countCondition
可以看到如下页面,
可以看到前面访问页面/webapp1了两次,数据正确。
总结:
通过上面的小例子发现:我们可以通过修改jetty.xml实现一些服务器的功能,也就是针对任何的webapp都适用的功能。而handler是其中可塑性较强的部分,不但可以添加新的Handler,还可以修改默认Handler的类型为HandlerList等。