新建一个空的java项目。
客户端发送的是一些字节数组,需要对字节数组进行解析后放入到IO流中。所以,新建request和response这两个对象==>>Myrequest&Myresponse。 回顾一下http协议中请求所包含的内容,并对这些内容进行解析。
package com.mashibing;
import java.io.InputStream;
/**
* @author msb
* @version : 1.0
*请求类
*/
public class myRequest {
//请求方法 GET/POST
private String requestMethod;
//请求地址
private String requestUrl;
//最终是要创建对象的
public myRequest(InputStream inputStream) throws Exception{
//构造方法是为了给两个属性赋值
//缓冲区域
byte[] buffer = new byte[1024];
//读取数据的长度
int len = 0;
//定义请求的变量
String str = null;
//读取数据
if ((len = inputStream.read(buffer)) > 0){//判断是否为空
str = new String(buffer,0,len);
}
//切割,得到字符串数组,获取请求头的字符串
String data = str.split("\n")[0];
//对获得的请求头进行切割 GET / HTTP/1.1
String[] params = data.split(" ");
//创建request对象
this.requestMethod = params[0];
this.requestUrl = params[1];
}
public String getRequestMethod() {
return requestMethod;
}
public void setRequestMethod(String requestMethod) {
this.requestMethod = requestMethod;
}
public String getRequestUrl() {
return requestUrl;
}
public void setReQuestUrl(String requestUrl) {
this.requestUrl = requestUrl;
}
}
现在已经知道,request是请求对象,response是响应对象。
输出数据不需要做解析。
package com.mashibing;
import java.io.OutputStream;
/**
* @author msb
* @version : 1.0
*响应类
*/
public class myResponse {
private OutputStream outputStream;
public myResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}
//写的操作,写的数据返回给对应的客户端
public void write(String str) throws Exception{
//新建一个可变字符串
StringBuilder builder = new StringBuilder();
//添加对应的属性
builder.append("HTTP/1.1 200 OK\n")
.append("Content-Type:text/html\n")//告诉浏览器传输的文件格式
.append("\r\n")
.append("<html>")
.append("<boday>")
.append("<h1>"+str+"</h1>")
.append("</body>")
.append("</html>");
this.outputStream.write(builder.toString().getBytes());//将响应数据传输出去
this.outputStream.flush();
this.outputStream.close();
}
}
请求对象request创建完成,响应对象response响应完成,还剩小程序applet没有完成,定义的接口也没有完成。 还有一个隐藏的环节:请求对象需要分辨向哪个程序传递请求数据,这中间隐藏着一个映射关系。 新建一个类myMapping表示映射关系。
package com.mashibing;
import java.util.HashMap;
/**
* @author msb
* @version : 1.0
*请求与处理类的映射关系
*/
public class myMapping {
public static HashMap<String, String> mapping = new HashMap<String, String>();
//建立一个静态代码块并优先执行
static {
mapping.put("/mytomcat", "com.mashibing.myServlet");
}
public HashMap<String, String> getMapping(){
return mapping;
}
}
编写接口,并在com.mashibing.MyServlet中新建接口的实现类。在这里,接口也可以使用抽象类来代替。
package com.mashibing;
/**
* @author msb
* @version : 1.0
*/
public abstract class myHttpServlet {
//定义常量(用来在方法中进行判断)
public static final String METHOD_GET = "GET";
public static final String METHOD_POST = "POST";
//定义一个方法来进行判断请求的类别
public abstract void doGet(myRequest request,myResponse response) throws Exception;
public abstract void doPost(myRequest request,myResponse response) throws Exception;
/**
* 根据请求方式判断调用哪种处理方法
* @param request
* @param response
*/
public void service(myRequest request,myResponse response) throws Exception{
if (METHOD_GET.equals(request.getRequestMethod())){
doGet(request, response);
}else if (METHOD_POST.equals(request.getRequestMethod())){
doPost(request, response);
}
}
}
父类(抽象类)写完之后,下面书写子类实现
package com.mashibing;
/**
* @author msb
* @version : 1.0
*/
public class myServlet extends myHttpServlet {
@Override
public void doGet(myRequest request, myResponse response) throws Exception {
response.write("mytomcat");
}
@Override
public void doPost(myRequest request, myResponse response) throws Exception {
response.write("post tomcat");
}
}
到这里,接收请求,响应请求,接口,映射,小程序都已经完成了。还有一个常服务的模块没有写。
常服务接收客户端的网络请求。既然是网络请求,要遵守socket套接字。
package com.mashibing;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author msb
* @version : 1.0
*/
public class myServer {
/**
*定义服务端的接收程序,接收socket请求
* @param port
* 端口号
*/
public static void StartServer(int port) throws Exception{
//定义服务端套接字
ServerSocket serverSocket = new ServerSocket(port);
//定义客户端套接字
Socket socket = null;
while (true){
socket = serverSocket.accept();
//获取输入输出流
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
//定义请求对象
myRequest request = new myRequest(inputStream);
//定义响应对象
myResponse response = new myResponse(outputStream);
//判断将数据传入到哪个小程序
String clazz = new myMapping().getMapping().get(request.getRequestUrl());
if (clazz!=null){
//Class<myServlet> myServletClass = Class.forName(clazz);
Class<myServlet> myServletClass = (Class<myServlet>) Class.forName(clazz);
//根据myServletClass创建对象
myServlet myServlet = myServletClass.newInstance();
myServlet.service(request,response);
}
}
}
public static void main(String[] args) {
try {
StartServer(10086);
} catch (Exception e) {
e.printStackTrace();
}
}
}
myserver常服务书写完成,在主方法中书写StartServer方法并添加端口号,使用try catch抛出异常后启动。 程序启动后,打开浏览器新标签页,输入localhost:端口号/mytomcat。
现在程序看起来没有问题,也能进行实现。这只是一个单线程环境的一个模拟,在多线程环境下程序运行可能就会有问题了。方便以后对servlet的学习。