package com.arz.server; import java.io.IOException; import java.io.OutputStream; public class Response { private OutputStream outStream; protected Response(OutputStream outStream) { this.outStream = outStream; } public void print(String info){ try{ outStream.write(info.getBytes()); }catch(IOException e){ e.printStackTrace(); } } public void println(String info){ try{ outStream.write((info+"\r\n").getBytes()); }catch(IOException e){ e.printStackTrace(); } } }
5.创建servlet类,这个servlet是个抽象类,因为在实际开发中这个类里面的service方法是我们来实现的所以也简单
package com.arz.servlet; import com.arz.server.Request; import com.arz.server.Response; public abstract class Servlet { public abstract void service(Request request,Response response); }
6.创建ServletContext这个类也是和java中的ServletContext对应。其实就是一个servlet的容器,里面是键-值对的形式保存在map中。这可以对应到整个web.xml。因为web.xml里面放着很多一对一对的servlet元素
package com.arz.servlet; import java.util.HashMap; import java.util.Map; public class ServletContext { private Map<String,Servlet>context = new HashMap<String, Servlet>(); public Map<String, Servlet> getContext() { return context; } public void setContext(Map<String, Servlet> context) { this.context = context; } public Servlet getServlet(String servletName){ if(context != null){ return context.get(servletName); } return null; } }
7.下面是ServletMapping这个是存放web.xml中的<servlet-mapping>元素的对应关系
package com.arz.servlet; public class ServletMapping { private String servletName; private String urlPattern; public String getServletName() { return servletName; } public void setServletName(String servletName) { this.servletName = servletName; } public String getUrlPattern() { return urlPattern; } public void setUrlPattern(String urlPattern) { this.urlPattern = urlPattern; } public ServletMapping(String str,String url){ this.servletName = str; this.urlPattern = url; } }
8.下面的类是解析web.xml并且将servlet-name,servlet-calssdui对应起来保存在ServletContext里面。将servlet-name,url-pattern对应起来保存在ServletMapping这样当知道是什么url时就可以找到对应的class来进行。这里解析xml使用的是jdom方式,你也可以使用其他方法解析。我会将jdom包放在附件中service
package com.arz.servlet; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import org.jdom.xpath.XPath; public class WebApp { private static String WEB_ROOT = "/home"; private ServletContext servletContext; private Map<String, ServletMapping> servletMappings = new HashMap<String, ServletMapping>(); private WebApp(){ parseWebXml(); } private static WebApp webApp; public static WebApp getWebApp(){ if(webApp == null){ webApp = new WebApp(); } return webApp; } private void parseWebXml(){ //使用jdom解析XML SAXBuilder builder = new SAXBuilder(); try{ Document doc = builder.build(new File(WEB_ROOT+"/WEB_INFO/web.xml")); XPath xpath = XPath.newInstance("//servlet"); servletContext = new ServletContext(); List list = xpath.selectNodes(doc.getRootElement()); //将xml中的servlet-name对应到class类 for(Iterator i = list.iterator(); i.hasNext();){ Element e = (Element)i.next(); String servletname = e.getChildText("servlet-name"); String servletClass = e.getChildText("servlet_class"); Servlet servlet = (Servlet)Class.forName(servletClass).newInstance(); servletContext.getContext().put(servletname, servlet); } //将xml中的servlet-name对应到url-pattern(地址栏的请求路径) xpath = XPath.newInstance("//servlet-mapping"); List mappings = xpath.selectNodes(doc.getRootElement()); for(Iterator i = mappings.iterator(); i.hasNext(); ){ Element e =(Element)i.next(); String servletName = e.getChildText("servlet-name"); String urlPattern = e.getChildText("url-pattern"); ServletMapping mapping = new ServletMapping(servletName,urlPattern); servletMappings.put(urlPattern,mapping); } }catch(Exception e){ e.printStackTrace(); } } public ServletContext getServletContext() { return servletContext; } public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } public Map<String, ServletMapping> getServletMappings() { return servletMappings; } public void setServletMappings(Map<String, ServletMapping> servletMappings) { this.servletMappings = servletMappings; } }
9.现在写一个测试的Servlet。然后将这个Servlet配置在web.xml中等待请求
package com.arz.servlet; import java.text.SimpleDateFormat; import java.util.Date; import com.arz.server.Request; import com.arz.server.Response; public class TestServlet extends Servlet { private static SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override public void service(Request request, Response response) { // TODO Auto-generated method stub String html = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=gbk\"/>"+ "</head>"+ "<body>"+ "<h2>通信测试.....</h2>"+ "<h2>服务器当前时间是:"+SDF.format(new Date())+"</h2>"+ "</body></html>"; response.print(html); } }
这样就大功告成,现在在浏览器中输入http://127.0.0.1:8080/项目名/配置的servlet名(url-pattern)这样就可以看到你输入的html了。
10.简单对上面的过程描述一下
A.“Tomcat”启动,监听着本机端口8080
B.浏览器发送请求:http://127.0.0.1:8080/项目名/配置的servlet名(url-pattern)。没有携带参数被Tomcat捕捉
C.通过socket对象Tomcat封装好HttpServletRequest、HttpServletResponse为执行Servlet的service方法提供参数。并且构造好HttpContext和HttpServlet等对象也就是那六个对象
D.通过解析web.xml调用对应的Servlet类。
E.剩下的事就是我们程序员做的,实例这个类重写service方法或者是doGet()/doPost()
在这里我们应当注意我们使用的Servlet的各种类都tomcat创建的。java只是提供了接口。真正实现的是Tomcat