minicat 1.0我们实现了返回固定的字符串"Hello minicat"。
minicat 2.0封装Request和Response对象,返回html静态资源文件。
minicat 3.0需求:
请求servlet动态资源
思路分析:
想实现servlet动态资源请求,就需要将Servlet初始化在容器中(Map)。
如何初始化呢?
配置web.xml之前,需要先自定义一个DemoServlet,需要有常见的doGet和doPost方法。
进一步想平时写Servlet都需要继承HttpServlet抽象类,所以先自己定义一个HttpServlet抽象类,以便后续做容器初始化。
先定义Servlet接口
public interface Servlet {
void init() throws Exception;
void destroy() throws Exception;
void service(Request request,Response response) throws Exception;
}
HttpServlet实现Servlet
public abstract class HttpServlet implements Servlet {
public abstract void doGet(Request request,Response response);
public abstract void doPost(Request request,Response response);
@Override
public void service(Request request, Response response) throws Exception {
if ("GET".equalsIgnoreCase(request.getMethod())) {
doGet(request,response);
}else{
doPost(request,response);
}
}
}
接下来就是常规的DemoServlet编写了
public class DemoServlet extends HttpServlet{
@Override
public void doGet(Request request, Response response) {
String content = "get request
";
try {
response.output(HttpProtocolUtil.getHttpHeader200(content.getBytes().length)+content);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doPost(Request request, Response response) {
String content = "post request
";
try {
response.output(HttpProtocolUtil.getHttpHeader200(content.getBytes().length)+content);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void init() throws Exception {
}
@Override
public void destroy() throws Exception {
}
}
DemoServlet准备完成后,就可以配置web.xml了
<web-app>
<servlet>
<servlet-name>demoservlet-name>
<servlet-class>server.DemoServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>demoservlet-name>
<url-pattern>/demourl-pattern>
servlet-mapping>
web-app>
web.xml已经配置完成,解析来就需要对它进行解析,也就是初始化的过程,所以需要放在上一篇的start()方法中初始化。
public void start() throws Exception {
// 加载解析相关配置,web.xml
loadServlet();
// 后面内容暂时省略....
}
/**
* 加载解析web.xml,初始化servlet
*/
private void loadServlet() {
// 将web.xml配置文件读取到input流中
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
SAXReader saxReader = new SAXReader();
try {
// 转换成Document对象
Document document = saxReader.read(resourceAsStream);
// 获取根对象
Element rootElement = document.getRootElement();
// 通过dom4j解析web.xml中的内容,放入到Map中
List<Element> selectNodes = rootElement.selectNodes("//servlet");
for (Element element : selectNodes) {
// demo
Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
String servletName = servletnameElement.getStringValue();
// server.DemoServlet
Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
String servletClass = servletclassElement.getStringValue();
// 根据servlet-name的值找到url-pattern
Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
// /demo
String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
// 使用反射初始化servlet加载到map中
//servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClas).newInstance());
}
} catch (DocumentException | ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
眼尖的同学估计看到了,这一步骤其实就是在loadServlet()方法中实现的
添加map容器
private Map<String,HttpServlet> servletMap = new HashMap<String,HttpServlet>();
// 伪代码
private void loadServlet() {
// doSomething...
servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
// doSomething...
}
已经初始化map容器了,那就需要在start方法中引用,start方法完整代码如下
/**
* minicat启动需要初始化展开的一些操作
*/
public void start() throws Exception {
// 加载解析相关配置,web.xml
loadServlet();
// 监听端口
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("---->>>minicat start on port:"+port);
//minicat 1.0 返回固定字符串
// while (true) {
// String data = "Hello minicat!";
// Socket socket = serverSocket.accept();
// // 有了socket,接收到请求,获取输出流
// OutputStream outputStream = socket.getOutputStream();
// String responseText = HttpProtocolUtil.getHttpHeader200(data.getBytes().length)+data;
// outputStream.write(responseText.getBytes());
// socket.close();
// }
// minicat 2.0 返回静态资源html
// while (true) {
// Socket socket = serverSocket.accept();
// // 获取输入流
// InputStream inputStream = socket.getInputStream();
//
// //封装Request和Response
// Request request = new Request(inputStream);
// Response response = new Response(socket.getOutputStream());
//
// response.outputHtml(request.getUrl());
// socket.close();
//
// }
// minicat 3.0 返回动态资源servlet
while (true) {
Socket socket = serverSocket.accept();
// 获取输入流
InputStream inputStream = socket.getInputStream();
//封装Request和Response
Request request = new Request(inputStream);
Response response = new Response(socket.getOutputStream());
// 静态资源处理
if(servletMap.get(request.getUrl()) == null) {
response.outputHtml(request.getUrl());
}else{
// 动态资源servlet请求
HttpServlet httpServlet = servletMap.get(request.getUrl());
httpServlet.service(request,response);
}
socket.close();
}
}