视频地址:http://www.bilibili.com/video/av59814573?p=252
粗略实现了视频的代码,没有完全按视频操作,如不读取xml,使用注解,不使用多线程等。
要点:
//注解类,用来设置servlet处理的url地址的注解,不设置@Target或@Retention会失效
package slq;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyController {
String[] value();
}
//自定义myServlet接口
package slq;
public interface MyServlet {
public void service(MyRequest q,MyResponse p);
}
//处理 /login***的Servlet
package slq;
@MyController({"/login"})
public class LoginServlet implements MyServlet {
@Override
public void service(MyRequest q, MyResponse p) {
String username = q.getParameter("username");
p.println("LoginServlet Welcome ");
p.println(username);
p.println("!");
p.pushToBrowser(200);
}
}
package slq;
//处理 /reg***和 /register***的Servlet
@MyController({"/reg","/register"})
public class RegServlet implements MyServlet {
@Override
public void service(MyRequest q, MyResponse p) {
String username = q.getParameter("username");
String password = q.getParameter("password");
if(username.equals(password)){
p.println("Reg reg success");
p.pushToBrowser(200);
}else{
p.println("Reg reg failed");
p.pushToBrowser(404);
}
}
}
//模拟request,只实现了获取parameter的功能
package slq;
import java.io.InputStream;
import java.net.Socket;
import java.util.HashMap;
public class MyRequest {
private Socket client;
public String uri;
private HashMap<String, String> map = new HashMap();
public MyRequest(Socket client) {
this.client=client;
InputStream is = null;
try {
is = client.getInputStream();
byte[] data=new byte[1024];
int len = is.read(data);
String s = new String(data, 0, len);
getParameterMap(s);
this.uri=s.substring(s.indexOf("/")+1,s.indexOf("?"));
//System.out.println(s+"-----"+this.uri);
} catch (Exception e) {
e.printStackTrace();
}
}
public String getParameter(String key){
return this.map.get(key);
}
public void getParameterMap(String s){
String s1=s.substring(s.indexOf("?")+1,s.indexOf(" HTTP"));
System.out.println("s1-->"+s1);
String[] split = s1.split("&");
for(String sp:split){
String[] spl = sp.split("=");
this.map.put(spl[0],spl[1]);
}
}
}
//模拟reponse,实现了写响应体,响应头的功能,重点是响应是怎么写进client的
package slq;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Date;
public class MyResponse {
private Socket client;
private StringBuilder body;
private StringBuilder head;
private BufferedWriter bw;
private final String CTRF="\r\n";
public MyResponse(Socket client) {
this.client = client;
this.body=new StringBuilder();
this.head=new StringBuilder();
try {
this.bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void println(String s){
body.append(s);
}
public void pushToBrowser(int code) {
setHead(code);
try {
bw.write(head.toString());
bw.write(body.toString());
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void setHead(int code){
head.append("HTTP/1.0 ").append(code==200?"200 OK":"404 BAD").append(CTRF);
head.append("Date:").append(new Date()).append(CTRF);
head.append("Server:SLQ SERVER").append(CTRF);
head.append("MINASE:INORI").append(CTRF);
head.append("Content-type:text/html").append(CTRF);
head.append("Content-length:").append(body.length()).append(CTRF).append(CTRF);
}
}
//程序入口,用读取注解生成urlmapping的hashmap,然后根据请求的url选择响应的servlet,这两步都使用了反射
package slq;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class WebApp {
public HashMap<String,String> mapping;
public static void main(String[] args) throws Exception {
WebApp app=new WebApp();
app.run();
}
public WebApp() throws ClassNotFoundException {
this.mapping=new HashMap();
getMapByClassName("slq.LoginServlet");
getMapByClassName("slq.RegServlet");
//{/reg=slq.RegServlet, /login=slq.LoginServlet, /register=slq.RegServlet}
System.out.println(this.mapping);
}
private void run() throws Exception {
ServerSocket s=new ServerSocket(9090);
while(true){
Socket client = s.accept();
MyRequest myRequest = new MyRequest(client);
MyResponse myResponse = new MyResponse(client);
String classname = mapping.get("/" + myRequest.uri);
if(classname==null)}{
client.close();
continue;
}
Class<?> clz = Class.forName(classname);
MyServlet servlet =(MyServlet) clz.getDeclaredConstructor().newInstance();
servlet.service(myRequest,myResponse);
client.close();
}
}
public void getMapByClassName(String name) throws ClassNotFoundException {
MyController anno = Class.forName(name).getAnnotation(MyController.class);
for(String s:anno.value()){
this.mapping.put(s,name);
}
}
}
post访问http://localhost:9090/login?username=311&password=310
响应体:
<html>
<head>
<title>LoginServlet</title>
</head>
<body>Welcome 311!</body>
</html>
响应头:
content-length →78
content-type →text/html
date →Mon Mar 16 22:48:42 CST 2020
minase →INORI
server →SLQ SERVER