一.运行机制
1.Servlet容器:Servlet规范定义了一个API标准,基于这个标准,程序员只需要实现业务逻辑,而无须关心核心逻辑,从而达到任务分工,简化工作量,服务至上的目的
2. 所有的Servlet都实现了一个统一的接口,Servlet接口申明了5个签名方法:
Init(ServletConfig config)
Service(ServletRequest request,ServletResponse response)
Destory( )
getServeltConfig()
getServletInfo()
3. 流程:
4. 流程图:
5. 这样设计便存在了一个严重的安全问题,容器中Sevice方法中的Sevletrequest参数ServletResponse参数,可以取到里面所有方法,这样一来,所有的参数暴露出来了,很明显,这样是不合适的,所以这里提供了一个解决方案-使用门面模式对Servletrequest和ServletResponse进行传递,这样一来,程序员只能访问固定的方法了,保障程序的健壮性。
6. 流程图:
二.实战代码
1. Constans
package JayKing.ASimpleServlet;
import java.io.File;
public class Constans {
public static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
public static final String errorMessage = "HTTP/1.1 404 File Not Found\r\n" + "Content-Type: text/html\r\n"
+ "Content-Length: 23\r\n" + "\r\n" + "File Not Found
";
}
2. HttpServer
package JayKing.ASimpleServlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
public static Boolean shutdown = false;
public static void main(String[] args) {
HttpServer server = new HttpServer();
server.await();
}
private void await() {
int port = 8080;
ServerSocket serversocket = null;
try {
serversocket = new ServerSocket(port, 100, InetAddress.getByName("localhost"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (!shutdown) {
Socket socket = null;
InputStream in = null;
OutputStream out = null;
try {
socket = serversocket.accept();
in = socket.getInputStream();
out = socket.getOutputStream();
Request request = new Request(in);
request.parse();
Response response = new Response(out);
response.setRequset(request);
if (request.getUri().startsWith("/servlet/")) {
ServletProcessor processor = new ServletProcessor();
processor.process(request, response);
} else {
System.out.println("Uri:"+request.getUri());
StaticResourceProcessor processor = new StaticResourceProcessor();
processor.process(request, response);
}
socket.close();
shutdown = request.getUri().equals(Constans.SHUTDOWN_COMMAND);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3. Requset
package JayKing.ASimpleServlet;
import java.io.IOException;
import java.io.InputStream;
public class Request implements ServletRequest{
public InputStream in;
public String uri;
public Request(InputStream in) {
this.in = in;
}
public String getUri() {
return uri;
}
public String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
if (index1 != -1) {
index2 = requestString.indexOf(' ', index1 + 1);
if (index2 > index1) {
return requestString.substring(index1 + 1, index2);
}
}
return null;
}
public void parse() {
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = in.read(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
i = -1;
}
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
uri = parseUri(request.toString());
}
}
4. RequestFacade
package JayKing.ASimpleServlet;
public class RequestFacade implements ServletRequest {
private ServletRequest resquest;
public RequestFacade(Request request) {
this.resquest = resquest;
}
}
5. Rseponse
package JayKing.ASimpleServlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
public class Response implements ServletResponse{
public static final int BUFFER_SIZE = 1024;
Request request;
OutputStream out;
public Response(OutputStream out) {
this.out = out;
}
public void setRequset(Request request) {
this.request = request;
}
public void sendStaticRescourse() throws IOException {
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;
File file = new File(Constans.WEB_ROOT, request.getUri());
try {
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE);
while(ch!=-1){
out.write(bytes,0,BUFFER_SIZE);
ch=fis.read(bytes,0,BUFFER_SIZE);
}
} catch (FileNotFoundException e) {
out.write(Constans.errorMessage.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis!= null) {
fis.close();
}
}
}
}
6. ResponseFacade
package JayKing.ASimpleServlet;
public class ResponseFacade implements ServletResponse {
private ServletResponse response;
public ResponseFacade(Response response) {
this.response = response;
}
}
7. Servlet
package JayKing.ASimpleServlet;
public interface Servlet {
public void init();
public void service(ServletRequest servletrequest,ServletResponse servletresposne);
public void destory();
}
8. ServletProcessor
package JayKing.ASimpleServlet;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
public class ServletProcessor {
public void process(Request request, Response response) {
String uri = request.getUri();
String ServletName = uri.substring(uri.lastIndexOf("/") + 1);
ClassLoader classloader = null;
Class myClass = null;
String repository = null;
URLClassLoader loader = null;
URL[] urls = new URL[1];
URLStreamHandler streamhandler = null;
File classPath = new File(Constans.WEB_ROOT);
try {
repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
urls[0] = new URL(null, repository, streamhandler);
loader = new URLClassLoader(urls);
myClass = loader.loadClass(ServletName);
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Servlet servlet = null;
RequestFacade requestFacade = new RequestFacade(request);
ResponseFacade responseFacade = new ResponseFacade(response);
try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
9. ServletRequest
package JayKing.ASimpleServlet;
public interface ServletRequest {
}
10. ServletResponse
package JayKing.ASimpleServlet;
public interface ServletResponse {
}
11. StaticResponseProcessor
package JayKing.ASimpleServlet;
import java.io.IOException;
public class StaticResourceProcessor {
public void process(Request request,Response response){
try {
response.sendStaticRescourse();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
三.运行程序
静态资源:打开浏览器在地址栏中输入URL:Http://localhost:8080/index.html
Servlet资源:打开浏览器在地址栏中输入URL:Http://localhost:8080/Servlet/MyServlet