1 创建一个简单的servlet
代码示例:
package springmvc;
import JAVA.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet{
/**
* 一个最简单的servlet
*/
private static final long serialVersionUID = 7683475760018217521L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data="这是我的第一个servlet!";
System.out.println(data);
}
}
web.xml中的标签确定了servlet的访问路径
<!DOCTYPE web-App PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>littleServlet</servlet-name>
<servlet-class>springmvc.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>littleServlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
</web-app>
servlet完成之后需要需要将他打包成项目(war/jar),并解压完成,形成完整的项目目录,供后续自己写的Tomcat使用。通常情况下,所有的项目都会放入tomcat的webapps目录下。
代码示例
package springboot.tomcat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Principal;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import springboot.util.ProjectUtil;
/**
* @author liuhongya328
*
*/
public class TomcatServer {
static int threads = 10;
private static ExecutorService pool = Executors.newCachedThreadPool();
/**
* @param args
*/
public static void main(String[] args) throws Exception{
//加载项目,获取tomcat需要发布的所有项目及项目下的所有servlet信息
final Map<String, ProjectUtil.WebXml> projectIno = ProjectUtil.load();
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("Tomcat 启动成功");
while(!serverSocket.isClosed()) {
//阻塞获取新连接
Socket socket = serverSocket.accept();
pool.submit(()->{
//接收数据
InputStream inputStream = socket.getInputStream();;
//请求响应结果
OutputStream outputStream = socket.getOutputStream();
try {
System.out.println("收到请求:-------");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String msg = null;
StringBuilder requestInfo = new StringBuilder();
while((msg = reader.readLine())!=null) {
if(msg.length()==0) {
break;
}
requestInfo.append(msg).append("rn");
}
System.out.println(requestInfo.toString()+"--------");
//请求需要访问的servlet,这个servlet相当于业务代码的controller,是需要放入tomcat中启动的项目,用原生的servlet便于从底层代码理解
//1.获取请求方式 及请求路径 GET /SpringMVC/servlet/littleServlet HTTP/1.1
String firstLine = requestInfo.toString().split("rn")[0];
String projectName = firstLine.split(" ")[1].split("/")[1];
String servletPath = firstLine.split(" ")[1].replace("/"+projectName, "");
//找到servlet对应的名称--j2ee规范
String servletName = projectIno.get(projectName).servletMapping.get(servletPath).toString();
//找到servlet对应的实例
Servlet servlet = (Servlet) projectIno.get(projectName).servletInstances.get(servletName);
//将socket的inputsteam 转成 request对象 ,如果想servlet接收和传递消息,需要实现自己的HttpServletRequest/HttpServletResponse即可。
//这里的创建仅作展示,实际没有作用,并不会传递socket的信息。
HttpServletRequest servletReuqest = createRequest();
HttpServletResponse servletResponse = createResponse();
//servlet的生命周期
servlet.service(servletReuqest, servletResponse);
outputStream.write("HTTP/1.1 200 OKrn".getBytes());
outputStream.write("Content-Length: 12rnrn".getBytes());
outputStream.write("Hello World!".getBytes());
outputStream.flush();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket.close();
return null;
});
}
serverSocket.close();
}
private static HttpServletRequest createRequest() {
return new HttpServletRequest() {
@Override
public Object getAttribute(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Enumeration<String> getAttributeNames() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getCharacterEncoding() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
// TODO Auto-generated method stub
}
@Override
public int getContentLength() {
// TODO Auto-generated method stub
return 0;
}
@Override
public long getContentLengthLong() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getContentType() {
// TODO Auto-generated method stub
return null;
}
@Override
public ServletInputStream getInputStream() throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getParameter(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Enumeration<String> getParameterNames() {
// TODO Auto-generated method stub
return null;
}
@Override
public String[] getParameterValues(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, String[]> getParameterMap() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getProtocol() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getScheme() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServerName() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getServerPort() {
// TODO Auto-generated method stub
return 0;
}
@Override
public BufferedReader getReader() throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRemoteAddr() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRemoteHost() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAttribute(String name, Object o) {
// TODO Auto-generated method stub
}
@Override
public void removeAttribute(String name) {
// TODO Auto-generated method stub
}
@Override
public Locale getLocale() {
// TODO Auto-generated method stub
return null;
}
@Override
public Enumeration<Locale> getLocales() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isSecure() {
// TODO Auto-generated method stub
return false;
}
@Override
public RequestDispatcher getRequestDispatcher(String path) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRealPath(String path) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRemotePort() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getLocalName() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getLocalAddr() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLocalPort() {
// TODO Auto-generated method stub
return 0;
}
@Override
public ServletContext getServletContext() {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncContext startAsync() throws IllegalStateException {
// TODO Auto-generated method stub
return null;
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
throws IllegalStateException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAsyncStarted() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAsyncSupported() {
// TODO Auto-generated method stub
return false;
}
@Override
public AsyncContext getAsyncContext() {
// TODO Auto-generated method stub
return null;
}
@Override
public DispatcherType getDispatcherType() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAuthType() {
// TODO Auto-generated method stub
return null;
}
@Override
public Cookie[] getCookies() {
// TODO Auto-generated method stub
return null;
}
@Override
public long getDateHeader(String name) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getHeader(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Enumeration<String> getHeaders(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Enumeration<String> getHeaderNames() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getIntHeader(String name) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getMethod() {
//示例
return "GET";
}
@Override
public String getPathInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPathTranslated() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getContextPath() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getQueryString() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRemoteUser() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isUserInRole(String role) {
// TODO Auto-generated method stub
return false;
}
@Override
public Principal getUserPrincipal() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRequestedSessionId() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRequestURI() {
// TODO Auto-generated method stub
return null;
}
@Override
public StringBuffer getRequestURL() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletPath() {
// TODO Auto-generated method stub
return null;
}
@Override
public HttpSession getSession(boolean create) {
// TODO Auto-generated method stub
return null;
}
@Override
public HttpSession getSession() {
// TODO Auto-generated method stub
return null;
}
@Override
public String changeSessionId() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isRequestedSessionIdValid() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isRequestedSessionIdFromCookie() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isRequestedSessionIdFromURL() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isRequestedSessionIdFromUrl() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
// TODO Auto-generated method stub
return false;
}
@Override
public void login(String username, String password) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void logout() throws ServletException {
// TODO Auto-generated method stub
}
@Override
public Collection<Part> getParts() throws IOException, ServletException {
// TODO Auto-generated method stub
return null;
}
@Override
public Part getPart(String name) throws IOException, ServletException {
// TODO Auto-generated method stub
return null;
}
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> httpUpgradeHandlerClass)
throws IOException, ServletException {
// TODO Auto-generated method stub
return null;
}
};
}
private static HttpServletResponse createResponse() {
return new HttpServletResponse() {
@Override
public String getCharacterEncoding() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getContentType() {
// TODO Auto-generated method stub
return null;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return null;
}
@Override
public PrintWriter getWriter() throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setCharacterEncoding(String charset) {
// TODO Auto-generated method stub
}
@Override
public void setContentLength(int len) {
// TODO Auto-generated method stub
}
@Override
public void setContentLengthLong(long length) {
// TODO Auto-generated method stub
}
@Override
public void setContentType(String type) {
// TODO Auto-generated method stub
}
@Override
public void setBufferSize(int size) {
// TODO Auto-generated method stub
}
@Override
public int getBufferSize() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void flushBuffer() throws IOException {
// TODO Auto-generated method stub
}
@Override
public void resetBuffer() {
// TODO Auto-generated method stub
}
@Override
public boolean isCommitted() {
// TODO Auto-generated method stub
return false;
}
@Override
public void reset() {
// TODO Auto-generated method stub
}
@Override
public void setLocale(Locale loc) {
// TODO Auto-generated method stub
}
@Override
public Locale getLocale() {
// TODO Auto-generated method stub
return null;
}
@Override
public void addCookie(Cookie cookie) {
// TODO Auto-generated method stub
}
@Override
public boolean containsHeader(String name) {
// TODO Auto-generated method stub
return false;
}
@Override
public String encodeURL(String url) {
// TODO Auto-generated method stub
return null;
}
@Override
public String encodeRedirectURL(String url) {
// TODO Auto-generated method stub
return null;
}
@Override
public String encodeUrl(String url) {
// TODO Auto-generated method stub
return null;
}
@Override
public String encodeRedirectUrl(String url) {
// TODO Auto-generated method stub
return null;
}
@Override
public void sendError(int sc, String msg) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void sendError(int sc) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void sendRedirect(String location) throws IOException {
// TODO Auto-generated method stub
}
@Override
public void setDateHeader(String name, long date) {
// TODO Auto-generated method stub
}
@Override
public void addDateHeader(String name, long date) {
// TODO Auto-generated method stub
}
@Override
public void setHeader(String name, String value) {
// TODO Auto-generated method stub
}
@Override
public void addHeader(String name, String value) {
// TODO Auto-generated method stub
}
@Override
public void setIntHeader(String name, int value) {
// TODO Auto-generated method stub
}
@Override
public void addIntHeader(String name, int value) {
// TODO Auto-generated method stub
}
@Override
public void setStatus(int sc) {
// TODO Auto-generated method stub
}
@Override
public void setStatus(int sc, String sm) {
// TODO Auto-generated method stub
}
@Override
public int getStatus() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getHeader(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<String> getHeaders(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<String> getHeaderNames() {
// TODO Auto-generated method stub
return null;
}
};
}
}
获取项目信息的工具类
package springboot.util;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.Servlet;
/**
*
* 加载项目信息
*
* */
public class ProjectUtil {
public static Map<String,WebXml> load() throws Exception{
final Map<String,WebXml> projetInfo = new HashMap<String,WebXml>();
//j2ee定义的是tomcat下的webapp目录,本地我取自己打包的war包目录
String webapps = "E:\learning\SpringMVC\SpringMVC\webapps";
//读取tomcat发布的所有的项目
File[] projects = new File(webapps).listFiles(projectName -> projectName.isDirectory());
for(File project : projects) {
//根据每个项目的web.xml读取servlet信息
WebXml webXml = new XMLConfigUtil().load(project.getPath()+"\WEB-INF\web.xml");
webXml.projectPath = project.getPath();
//类加载,加载class文件-----war包或者jar包中解压的class文件
webXml.loadServlet();
projetInfo.put(project.getName(), webXml);
}
return projetInfo;
}
public class WebXml{
public String projectPath = null;
//查找项目中所有的servlet
public Map<String,Object> servlets = new HashMap<String,Object>();
public Map<String,Object> servletMapping = new HashMap<String,Object>();
//实例对象
public Map<String,Object> servletInstances = new HashMap<String,Object>();
public void loadServlet() throws Exception {
//jvm加载class文件
URL url = new URL("file:"+projectPath+"\WEB-INF\classes\");
URLClassLoader classLoader = new URLClassLoader(new URL[] {url});
//加载servlet,创建servlet对象
for(Entry<String,Object> entry : servlets.entrySet()) {
//servlet的名称
String servletName = entry.getKey();
//servlet类的完整路径
String servletClassName = entry.getValue().toString();
//加载
Class<?> clazz = classLoader.loadClass(servletClassName);
//反射创建对象,这就是为什么j2ee规范 servlet要继承HttpServlet,
Servlet servlet = (Servlet) clazz.newInstance();
this.servletInstances.put(servletName, servlet);
}
}
}
}
解析web.xml的工具类
package springboot.util;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import springboot.util.ProjectUtil.WebXml;
public class XMLConfigUtil extends DefaultHandler {
// 查找项目中所有的servlet
public Map<String, Object> servlets = new HashMap<String, Object>();
public Map<String, Object> servletMapping = new HashMap<String, Object>();
// 实例对象
public Map<String, Object> servletInstances = new HashMap<String, Object>();
private String tag;// 存储操作的标签
private boolean isMapping = false;
private String currentServlet;
private String currentServletMapping;
public WebXml load(String path) throws SAXException, IOException, ParserConfigurationException {
// SAX解析
// 1、获取SAX解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2、从解析工厂中获取解析器
SAXParser parse = factory.newSAXParser();
XMLConfigUtil handler = new XMLConfigUtil();
// 5、解析
parse.parse(path, this);
// 6、获取数据
ProjectUtil.WebXml webXMl = new ProjectUtil().new WebXml();
webXMl.servlets = this.servlets;
webXMl.servletMapping = this.servletMapping;
return webXMl;
}
@Override
public void startDocument() throws SAXException {
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (null != qName) {
tag = qName;// 存储标签名
if (tag.equals("servlet")) {
isMapping = false;
} else if (tag.equals("servlet-mapping")) {
isMapping = true;
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String contents = new String(ch, start, length).trim();
if (null != contents) {// 处理空的问题
if (isMapping) {// 操作servlet-mapping
if (tag.equals("servlet-name")) {
currentServletMapping = contents;
} else if (tag.equals("url-pattern")) {
String urlPattern = contents;
servletMapping.put(urlPattern, currentServlet);
}
} else {// 操作servlet
if (tag.equals("servlet-name")) {
currentServlet = contents;
currentServletMapping = contents;
} else if (tag.equals("servlet-class")) {
String servletClass = contents;
servlets.put(currentServlet, servletClass);
}
}
}
}
}
本次代码没有实现request和response是的交互,返回都是写死的outputStream.write(“Hello World!”.getBytes())。
如果需要实现,需要写自己的request和response。