基于java Scoket的TCP协议 简单实现http服务器,用浏览器当作客户端,达到javaWeb中类似于访问Servlet的效果。
(对http协议和Servlet要有一定了解)
改进版
执行效果:
- http服务器端:
客户端 (login.html):
登陆后: 测试账号:zjl 123456
思路
- 浏览器端:是一个html的表单,输入姓名密码后点击登陆即可,访问服务器地址为localhost:8080/login,然后会自动连接服务器并发送http协议的请求消息。
- 服务器:接收到客户端的消息后进行解析,在请求消息中解析出客户端欲请求的资源(这里是/login),请求方式(get或者post),和请求参数,然后封装到Request实体中。然后就要根据请求资源来获得对应的Servlet了,请求资源和Servlet的全路径类名的映射关系放在web.xml这个文件,所以利用dom4j解析web.xml文件即可得到Servlet的全路径类名,再利用反射即可创建出此servlet的实例。有了Servlet的实例后调用Servlet实例的service方法并把封装后的Request对象和Reponse对象作为参数传入即可,这样就执行了Servlet的service方法,再用reponse调用print方法即可向客户端发送响应消息。
思路图形化
代码目录结构
web.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<web-app>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>demo.ServletImpl.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
核心代码
public class startServer {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(8080);
System.out.println("http服务器启动成功....");
//多线程处理每个请求
while(true){
Socket client = server.accept();
new ServerThread(client).start();
}
}
}
/**
* 服务器处理浏览器请求线程
*/
class ServerThread extends Thread{
private Request request; //请求
private Response reponse; //响应
private Socket client; //客户端套接字
//初始化request,reponse
public ServerThread(Socket client) {
try {
this.client = client;
request = new Request(client.getInputStream());
reponse = new Response(client.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
System.out.println(client.getRemoteSocketAddress()+" 发出请求");
//浏览器会默认请求网站图标资源,我们这里忽略掉这个请求
if (request.getUrl().equals("/favicon.ico"))
return;
//1-根据请求的url获得Servlet
Servlet servlet = ServletFactory.getServlet(request.getUrl());
//请求资源不存在404
if (servlet == null){
reponse.setCode(404);
reponse.print("");
}
//2-执行Servlet
if (servlet != null){
servlet.service(request,reponse);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
根据请求资源获取Servlet代码
- 下面web.xml文件的路径xmlpath需根据自己电脑环境设置否则会找不到该文件
/**
* Servlet工厂
*
* 根据url和xml文件创建Servlet
*
*
*/
public class ServletFactory {
//Servlet上下文环境
private static ServletContext context = new ServletContext();
//web.xml文件路径
private static String xmlpath = "http服务器/src/demo/web.xml";
private ServletFactory(){
}
/**
* 读取web.xml文件把servlet和url的关系进行配置存储
*/
static {
try {
//1-获得doucument
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(xmlpath));
//2-获得根元素 <web-app>
Element rootElement = document.getRootElement();
//3-获得所有子元素
List<Element> elements = rootElement.elements();
//4-遍历处理所有子元素
for (Element e : elements) {
if ("servlet-mapping".equals(e.getName())) {
Element servlet_name = e.element("servlet-name");
Element url_pattern = e.element("url-pattern");
context.getUrl_map().put(url_pattern.getText(),servlet_name.getText());
}
else if ("servlet".equals(e.getName())) {
Element servlet_name = e.element("servlet-name");
Element servlet_class = e.element("servlet-class");
context.getServlet_map().put(servlet_name.getText(),servlet_class.getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
/**
* 获得Servlet
*/
public static synchronized Servlet getServlet(String url) throws Exception {
String servletClass = context.getServlet_map().get(context.getUrl_map().get(url));
return servletClass != null ? (Servlet)Class.forName(servletClass).newInstance() : null;
}
}
ServletContext上下文环境
/**
* Servlet的上下文环境
*/
public class ServletContext {
//Servlet别名和Servlet全路径类名的映射关系
private Map<String,String> servlet_map;
//url和 Servlet别名的映射关系
private Map<String,String> url_map;
public ServletContext() {
servlet_map = new HashMap<>();
url_map = new HashMap<>();
}
public Map<String, String> getServlet_map() {
return servlet_map;
}
public Map<String, String> getUrl_map() {
return url_map;
}
}
Servlet抽象类代码
/**
* Servlet抽象类
*/
public abstract class Servlet {
public void service(Request request,Response reponse) throws Exception {
this.doGet(request,reponse);
this.doPost(request,reponse);
}
public abstract void doGet(Request request,Response reponse) throws Exception;
public abstract void doPost(Request request,Response reponse) throws Exception;
}
执行LoginServlet代码
import demo.domain.Request;
import demo.domain.Response;
import demo.domain.Servlet;
public class LoginServlet extends Servlet {
@Override
public void doGet(Request request, Response reponse) throws Exception {
String name = request.getParameter("name");
String password = request.getParameter("password");
if (name!= null && password !=null && name.equals("zjl") && password.equals("123456"))
reponse.print("登陆成功!");
else
reponse.print("登陆失败!");
}
@Override
public void doPost(Request request, Response reponse) throws Exception {
doGet(request,reponse);
}
}
完成上述之后,现在你可以实现自己自定义的Servlet去处理每一个请求,只要去继承Servlet抽象类即可,然后再在web.xml中配置一下Setvlet的属性即可.
完整代码地址
链接:https://pan.baidu.com/s/1NN7oNdD5m1U_36YI_wNvrA 密码:w80h