提供socket服务并实现请求的分发。
服务器监听客户端请求——解析请求头——根据请求映射关系分发处理——调用service方法——执行doGet或doPost方法——响应请求。
1、服务器持续监听客户端请求。
/**
* @author jiang
* @Description Server
*/
public class Server {
@SuppressWarnings("all")
public static void startServer(int port) throws Exception {
System.out.println("server init...");
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = null;
while(true) {
/** 在8080端口循环监听 */
socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
MyRequest myRequest = new MyRequest(inputStream);
MyResponse myResponse = new MyResponse(outputStream);
/** 根据请求映射关系处理请求 */
String clazz = new Mapper().getMyServletMapper().get(myRequest.getRequestURL());
if (clazz != null) {
/** 反射创建对象并调用service方法 */
Class<MyServlet> myClazz = (Class<MyServlet>) Class.forName(clazz);
MyServlet myServlet = myClazz.newInstance();
myServlet.service(myRequest, myResponse);
}
}
}
}
2、封装请求对象,解析请求信息
/**
* @author jiang
* @Description 请求对象
*/
public class MyRequest {
private String requestURL;
private String requestMethod;
public String getRequestURL() {
return requestURL;
}
public String getRequestMethod() {
return requestMethod;
}
public MyRequest(InputStream inputStream) throws IOException {
byte[] requestData = new byte[1024];
String msg = null;
int len = 0;
if((len = inputStream.read(requestData)) > 0) {
msg = new String(requestData, 0, len);
}
// **********************************请求头信息************************************************
// GET /test HTTP/1.1
// Host: localhost:8080
// User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
// Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
// Accept-Encoding: gzip, deflate
// Connection: keep-alive
// Upgrade-Insecure-Requests: 1
// *****************************************************************************************
/** 获取请求头第一行 --- GET /test HTTP/1.1 */
String head = msg.split("\n")[0];
/** 获取请求方法和请求url */
String[] data = head.split("\\s");
requestMethod = data[0];
requestURL = data[1];
}
}
3、封装响应对象
/**
* @author jiang
* @Description 响应对象
*/
public class MyResponse {
private OutputStream outputStream;
public MyResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void write(String msg) throws IOException {
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK\n") // 设置状态码
.append("Content-Type: text/html\n") //设置mime类型
.append("\r\n")
.append("<html>")
.append("<body>")
.append(msg)
.append("</body>")
.append("</html>");
outputStream.write(sb.toString().getBytes());
outputStream.close();
}
}
4、配置请求处理映射关系
/**
* @author jiang
* @Description 请求url对应处理类的映射关系
*/
public class Mapper {
public static Map<String, String> myServletMapper = new HashMap<String, String>();
static {
myServletMapper.put("/test", "com.abc.server.MyServlet");
}
public Map<String, String> getMyServletMapper() {
return myServletMapper;
}
}
5、编写请求处理基类
/**
* @author jiang
* @Description 请求处理基类
*/
public abstract class MyHttpServlet {
private static final String METHOD_GET = "GET";
private static final String METHOD_POST = "POST";
protected abstract void doGet(MyRequest req, MyResponse resp) throws IOException;
protected abstract void doPost(MyRequest req, MyResponse resp) throws IOException;
protected void service(MyRequest req, MyResponse resp) throws IOException {
if (METHOD_GET.equals(req.getRequestMethod())) {
doGet(req, resp);
} else if (METHOD_POST.equals(req.getRequestMethod())) {
doPost(req, resp);
}
}
}
6、编写请求实现类
/**
* @author jiang
* @Description 请求处理实现类
*/
public class MyServlet extends MyHttpServlet {
@Override
protected void doGet(MyRequest req, MyResponse resp) throws IOException {
resp.write("success");
}
@Override
protected void doPost(MyRequest req, MyResponse resp) {
}
}
7、编写启动类,启动服务
/**
* @author jiang
* @Description 启动类
*/
public class Starter {
public static void main(String[] args) throws Exception {
Server.startServer(8080);
}
}
运行截图: