一直以来,整合Apache HTTP Server和其他Java容器时,可能你最好的选择就是mod_jk,但是mod_jk在Apache和外部Java服务器之间使用socket来进行协议转换,性能不能尽如人意。
正如我上一篇博客里说的,mod_java通过在apache嵌入的JVM中直接执行Java来响应HTTP请求,当然是要快于mod_jk的。
但是缺点是,不是Servlet API(虽然实现Servlet API不是很难,但是工作量肯定很大的),优点是,接口很清晰,很灵活,可以做到的事情也就很多。
那么如何开发一个基于mod_java的java handler呢?OK,假设你要在Apache里响应所有/test/*上的请求.
你要做的是:
1)配置Apache启用mod_java
LoadModule java_module modules/mod_java.so
<mod_java your_main_class>
JVMLibrary D:\jdk6\jre\bin\server\jvm.dll
CurDir D:\apache-tomcat-6.0.14
ADDJVMOpt -Djava.class.path=D:\apache-tomcat-6.0.14\bin\bootstrap.jar;D:\dev\vccode\mod_java\mod_java.jar
ADDJVMOpt -Djava.library.path=D:\apache-tomcat-6.0.14\bin
ADDJVMOpt -Dcatalina.home=D:\apache-tomcat-6.0.14
ADDJVMOpt -Duser.dir=D:\apache-tomcat-6.0.14
ADDJVMParam start
ADDJVMStopParam stop
ADDJavaHandler javatest com.yovn.apache.modj.HelloWorld
</mod_java>
这里main_class是可选的,如果有,那么JVM启动时自动调用main方法。
2)在配置文件里加入你将要开发的Java Handler
想上面文件中的
ADDJavaHandler javatest com.yovn.apache.modj.HelloWorld
这里 javatest是handler名字,后面是你的实现的class
3)在配置文件里告诉Apache 你的handler名字对应的路径
<Location /test>
SetHandler javatest
</Location>
完成这些配置动作后,apache在收到到/test/*的请求后mod_java会call你的handler class的processRequest方法了。
RequestHandler接口如下定义,你的Handler都需要实现该接口:
package com.yovn.apache.modj;
import java.io.IOException;
/**
* @author yovn
*
*/
public interface RequestHandler {
public abstract void processRequest(ModJRequest request) throws IOException,
ModJavaException;
}
正如你看到的很简单的接口,但是ModJRequest就不简单了,该接口代表你跟Apache通行的直接的接口,目前定义如下:
package com.yovn.apache.modj;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* @author yovn
*
*/
public interface ModJRequest {
/**
*
* @param name
* @return the request header value of that name
*/
String getRequestHeader(String name);
/**
*
* @return similar as HttpServletRequest.getRequestURI()
*/
String getRequestURI();
/**
*
* @param name header name
* @param value header value
*/
void setResponseHeader(String name,String value);
/**
*
* @param type 'text/html' etc..
*/
void setContentType(String type);
/**
*
* @param code response code
*/
void setResponseCode(int code);
/**
*
* @return HTTP method
*/
String getMethod();
/**
* Give you the chance when you need push datas to client
* Also,you can use it to close a connection
* Note:
* HTTP Server may close the connection when it timeout automatically.
* When you pass use an invalid connection id to call some function , it will failed.
* @see com.yovn.apache.modj.ApacheModule#flushConnection(long, byte[], int, int)
* @see com.yovn.apache.modj.ApacheModule#closeConnection(long)
* @return the connection id for this request.
*/
long getConnectionId();
/**
* same as HttpServletRequest.getServletInputStream
* @return
*/
InputStream getRequestInputStream();
/**
* same as HttpServletResponse.getServletOutputStream
* @return
*/
OutputStream getResponseOutputStream();
/**
* You should not call the {@link #getRequestInputStream()} before you call this method this method.
* In other words, You should either use this method or {@link #getRequestInputStream()} to do read data from clients
* @return the direct byte buffer from native side
* @throws IOException
*/
ByteBuffer readTotalRequestBody()throws IOException;
/**
* Use apache's apr_send_fd to send a file.
* Before send file, you may need setup proper HTTP headers, such as 'Content-Disposition'
* @param fileName
* @return
* @throws IOException
*/
boolean sendFile(String fileName)throws IOException;
}
如你所看,基本可以做任何事情(如果还有你想要而没有请一定要告诉我哦)!
下面给个发送文件的例子:
/**
*
*/
package com.yovn.apache.modj;
import java.io.File;
import java.io.IOException;
/**
* @author yovn
*
*/
public class HelloWorld implements RequestHandler {
/**
*
*/
public HelloWorld() {
// TODO Auto-generated constructor stub
}
/*
* (non-Javadoc)
*
* @see com.yovn.apache.modj.RequestHandler#processRequest(ModJRequest request)
*/
public void processRequest(ModJRequest request) throws IOException,
ModJavaException {
request.setContentType("APPLICATION/OCTET-STREAM");
File f=new File("D:\\cspace\\mod_java\\release\\ddd.bin");
request.setResponseHeader("Content-Disposition", "attachment;filename=\"ddd.bin\"");
request.setResponseHeader("Content-Length",f.length()+"");
request.sendFile(f.getCanonicalPath());
}
}
下载:
mod_java_0.1