fried cake server---私の油揚げ餅(2)資源実行アーキテクチャ
リソース実行アーキテクチャ......少し玄ですが、正直に言うと、いわゆるリソース実行アーキテクチャは最初はif......else文の群れにすぎませんでしたが、開発が進むにつれて大きくなり、最後まで最悪でした.前回のSocketProcessクラスを覚えていますか?最初は実行方法が含まれていましたが、面倒でうるさいし、拡張しにくいです.
これが第1版のリソースアクチュエータで、とても乱れているでしょう
その後、リソース実行アーキテクチャを再構築し、エージェントモデルを作りました.
このラックは2つのインタフェース、1つのエージェントクラス、およびいくつかの実装クラスから構成されています.
1つ目はエフェクタインタフェースであり、このインタフェースを実現したクラスはhttpリクエストを受け入れて応答することができる.
さらにエージェントクラスを実行するには、このクラスは責任チェーンモードを使用していますが、実はこのexecutorArrayはプロファイルに配置できますが、まだそんなに遠いことは考えていないので、先に置いておきました.しかし、拡張は依然として容易であり、CheckableExecutorインタフェースを実現し、クラス名をexecutorArray配列に記入して登録すれば、実行シーケンスに追加できます.
次はJspExecutor、サーブレットExecutor、ResourceExecutorの3つの実装クラスです.
jspリソース、servletリソース、通常のファイルリソースにそれぞれ対応していますが、前の2つのエフェクタは環境外のクラスロード、jspコンパイル、システムデータ構造など多くの問題に関連しています.後の章に置きます.
次は一般的なエクスプローラです
「String file Name=RequestHanler.loadRealPath(request);」を除いてreviewしました.この一言のほかに、ほかに疑問はないはずです.この文については、request urlからファイルリソースへのマッピングですが、最初は簡単なフォルダパスマッピングをすればよかったのですが、その後、プロジェクトマウントProjectDeployerといくつかの関連をしましたが、この実現は重要ではありません.皆さんは理解しているはずです.
では、これらの種類があれば、私たちの揚げ餅は簡単な応答ができるはずですが...
興味のある友達は自分で書いてみてもいいですが、実はこの一歩は、難しくはありません.難しいのは後ろです.
へへへ、次号は遠端classLoaderの書き方とserverのデータ構造を紹介して、ゆっくりと
package server;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import jsp.JspConvertor;
import project.ProjectInfo;
import servlet.bean.ServletInfo;
import util.Constant;
import util.HttpError;
import util.LocalClassLoader;
import util.ServerMessage;
import webHttp.HttpRequestImpl;
import webHttp.HttpResponseImpl;
import webHttp.RequestHanler;
import webHttp.SessionPool;
/**
*
* : , ,
*
* jms
*
* @author
*
*/
public class SocketProcess extends Thread {
ServerSocketChannel serverSocket = null;
/**
*
* @param serverSocket
*/
public SocketProcess(ServerSocketChannel serverSocket) {
this.serverSocket = serverSocket;
}
/**
* serverSocket
* servlet
*
*/
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(1024 * 8);
SocketChannel channel = null;
try {
//
channel = serverSocket.accept();
if (channel != null && channel.read(buffer) > 0) {
String requestInfo = new String(buffer.array(), 0, buffer
.position());
HttpRequestImpl request = RequestHanler
.getHttpRequest(requestInfo);
AppRunTime runtime = AppRunTime.getInstance();
String[] uri = request.getContextPath().split(Constant.WEB_SP);
ProjectInfo project = runtime.getProjectMap().get(uri[1]);
if(project==null)return;
// session
SessionPool sessionPool = SessionPool.getInstance(project.getId());
HttpSession session = sessionPool.getSession(channel.socket().getInetAddress().getHostAddress());
request.bind(session);
// servlet
if(excuteServlet(channel, project, request)==false)
{
// jsp
if(request.getServletPath().endsWith(Constant.FileType_SP_JSP))
excuteJsp(channel, project, request);
//
else
excuteResource(channel, project, request);
}
//
buffer.clear();
if (channel.isOpen()) {
buffer.put(" ".getBytes());
buffer.flip();
channel.write(buffer);
channel.finishConnect();
channel.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* jsp
* @param channel
* @param project
* @param request
*/
private void excuteJsp(SocketChannel channel, ProjectInfo project,
HttpServletRequest request) {
String fileName = RequestHanler.loadRealPath(request);
File jspFile = new File(fileName);
// jsp
if(!jspFile.exists())
{
sendExceptionMessage(channel,HttpError.ERROR_404);
return;
}
JspConvertor convertor = new JspConvertor(jspFile,project);
try {
File servletFile = convertor.getCompiledServlet();
ClassLoader loader = LocalClassLoader.getInstance(servletFile.getParent());
HttpServlet servlet = (HttpServlet) loader.loadClass(servletFile.getName().replace(Constant.FileType_SP_Class, "")).newInstance();
HttpServletResponse response = new HttpResponseImpl(channel);
servlet.service(request, response);
} catch (Exception e) {
sendExceptionMessage(channel,HttpError.ERROR_404);
}
}
/**
* , error404 page not found
* @param channel
* @param message
*/
private void sendExceptionMessage(SocketChannel channel ,String message){
ByteBuffer buffer = ByteBuffer.allocate(1024 * 8);
buffer.put(HttpError.ERROR_404.getBytes());
buffer.flip();
try {
channel.write(buffer);
} catch (IOException e) {
System.err.println(ServerMessage.connection_exception);
}
buffer.clear();
}
/**
*
*
* @param channel
* @param project
* @param request
* @throws Exception
*/
private void excuteResource(SocketChannel channel, ProjectInfo project, HttpServletRequest request) throws Exception {
ByteBuffer buffer = ByteBuffer.allocate(1024 * 8);
String fileName = RequestHanler.loadRealPath(request);
buffer.clear();
File file = new File(fileName);
if (file.exists() && file.canRead()) {
FileChannel fc = new FileInputStream(file).getChannel();
while (fc.read(buffer) > 0) {
buffer.flip();
channel.write(buffer);
buffer.clear();
}
} else {// , 404 page not found
sendExceptionMessage(channel,HttpError.ERROR_404);
}
}
/**
* servlet
*
* @param channel
* @param project
* @param request
* @return servlet
* @throws Exception if
*/
private boolean excuteServlet(SocketChannel channel, ProjectInfo project,HttpServletRequest request) throws Exception {
for (ServletInfo info : project.getServletInfo()) {
//
Pattern p = Pattern.compile(Constant.WEB_SP+project.getWebPath()+info.getUrl_pattern());
Matcher m = p.matcher(request.getRequestURI());
if (m.matches()==false) continue;
//
ClassLoader loader = LocalClassLoader.getInstance(project .getPatch());
HttpServlet servlet = (HttpServlet) loader.loadClass( info.getServletClass()).newInstance();
HttpServletResponse response = new HttpResponseImpl(channel);
// filter servlet
FilterChain chain = info.getFilterChain();
chain.doFilter(request, response);
servlet.init(info.getServletConfig());
servlet.service(request, response);
servlet.destroy();
return true;
}
return false;
}
}
これが第1版のリソースアクチュエータで、とても乱れているでしょう
その後、リソース実行アーキテクチャを再構築し、エージェントモデルを作りました.
このラックは2つのインタフェース、1つのエージェントクラス、およびいくつかの実装クラスから構成されています.
1つ目はエフェクタインタフェースであり、このインタフェースを実現したクラスはhttpリクエストを受け入れて応答することができる.
public interface Executor {
/**
* ,
* ,
*
* @param request
* @param response
*/
public void forward(HttpServletRequest request,HttpServletResponse response) throws Exception;
}
第2のインタフェースはExecutorのサブインタフェースCheckableExecutorが実現したクラスが実行可能かどうかを判断する
public interface CheckableExecutor extends Executor{
public void init(ProjectInfo project);
/**
*
* @return
*/
public boolean isExecutable(HttpServletRequest request);
}
さらにエージェントクラスを実行するには、このクラスは責任チェーンモードを使用していますが、実はこのexecutorArrayはプロファイルに配置できますが、まだそんなに遠いことは考えていないので、先に置いておきました.しかし、拡張は依然として容易であり、CheckableExecutorインタフェースを実現し、クラス名をexecutorArray配列に記入して登録すれば、実行シーケンスに追加できます.
package executor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import project.ProjectInfo;
import executor.impl.JspExecutor;
import executor.impl.ResourceExecutor;
import executor.impl.ServletExecutor;
public class BaseExecutor implements Executor {
@SuppressWarnings("unchecked")
private Class<CheckableExecutor>[] executorArray = new Class[]{JspExecutor.class,ServletExecutor.class,ResourceExecutor.class};
// executor
private ProjectInfo project;
/**
*
* @param project
*/
public BaseExecutor(ProjectInfo project){
this.project = project;
}
/**
*
*
* @param request
* @return
* @throws Exception
* @throws InstantiationException
*/
public Executor getExecutor(HttpServletRequest request) throws InstantiationException, Exception {
//
for(Class<CheckableExecutor> exeClass:executorArray)
{
CheckableExecutor executor = exeClass.newInstance();
executor.init(project);
if(executor.isExecutable(request)) return executor;
}
return null;
}
/**
* ,
*/
@Override
public void forward(HttpServletRequest request,HttpServletResponse response) throws Exception{
Executor exe = getExecutor(request);
exe.forward(request, response);
}
}
次はJspExecutor、サーブレットExecutor、ResourceExecutorの3つの実装クラスです.
jspリソース、servletリソース、通常のファイルリソースにそれぞれ対応していますが、前の2つのエフェクタは環境外のクラスロード、jspコンパイル、システムデータ構造など多くの問題に関連しています.後の章に置きます.
次は一般的なエクスプローラです
package executor.impl;
import java.io.File;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import project.ProjectInfo;
import util.HttpError;
import webHttp.RequestHanler;
import exceptions.HttpException;
import executor.CheckableExecutor;
public class ResourceExecutor implements CheckableExecutor {
public void init(ProjectInfo project) {
//
}
/**
*
*/
@Override
public void forward(HttpServletRequest request, HttpServletResponse response)
throws Exception {
ByteBuffer buffer = ByteBuffer.allocate(1024 * 8);
String fileName = RequestHanler.loadRealPath(request);
buffer.clear();
File file = new File(fileName);
if (file.exists() && file.canRead()) {
FileChannel fc = new FileInputStream(file).getChannel();
while (fc.read(buffer) > 0) {
buffer.flip();
response.getOutputStream().write(buffer.array());
buffer.clear();
}
} else {// , 404 page not found
throw new HttpException(HttpError.ERROR_404);
}
}
@Override
/**
*
* ResourceExecutor, , ,
*/
public boolean isExecutable(HttpServletRequest request) {
return true;
}
}
「String file Name=RequestHanler.loadRealPath(request);」を除いてreviewしました.この一言のほかに、ほかに疑問はないはずです.この文については、request urlからファイルリソースへのマッピングですが、最初は簡単なフォルダパスマッピングをすればよかったのですが、その後、プロジェクトマウントProjectDeployerといくつかの関連をしましたが、この実現は重要ではありません.皆さんは理解しているはずです.
では、これらの種類があれば、私たちの揚げ餅は簡単な応答ができるはずですが...
興味のある友達は自分で書いてみてもいいですが、実はこの一歩は、難しくはありません.難しいのは後ろです.
へへへ、次号は遠端classLoaderの書き方とserverのデータ構造を紹介して、ゆっくりと