1、HTTPServer
package core;
import annotations.Servlet;
import baseservlet.AbstractServlet;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
public class HTTPServer {
/**
* 监听端口
*/
public static int port = 8080;
/**
* Key值为Servlet的别名(uri),value为该Servlet对象
* default权限
*/
static HashMap<String, AbstractServlet> map;
static {
//包名,可以通过application.properties设置
getServlets("servlet");
}
static ServerSocket serverSocket = null;
public void acceptWait() {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
//工作队列
ArrayBlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
//线程池的基本大小,即在没有任务需要执行的时候线程池的大小
int corePoolSize = 10;
//线程池中允许的最大线程数
int maximumPoolSize = 50;
//空闲线程存活时间
long keepAliveTime = 100L;
//时间单位
TimeUnit unit = TimeUnit.SECONDS;
//拒绝策略
RejectedExecutionHandler rejectionStrategy = new ThreadPoolExecutor.DiscardOldestPolicy();
ThreadPoolExecutor tpe = new ThreadPoolExecutor(corePoolSize,
maximumPoolSize,keepAliveTime,unit,workQueue, Executors.defaultThreadFactory(),rejectionStrategy);
while (!serverSocket.isClosed()) {
try {
//单线程,阻塞式监听(bio)
Socket socket = serverSocket.accept();
RequestHandler handler = new RequestHandler(socket);
tpe.execute(handler);
handler.start();
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
private static void getServlets(String packageName) {
//class类的集合
Set<Class<?>> classes = new LinkedHashSet<>();
try {
String packageDirName = packageName.replace(".", "/");
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
findAndAddClassesInPackageByFile(packageName, filePath,true,classes);
}else if("jar".equals(protocol)){
//扫描JAR包
}
}
//遍历class集合
if (map == null){
map = new HashMap<>(classes.size());
}
for (Class<?> aClass : classes) {
//如果该class有Servlet注解
if (aClass.isAnnotationPresent(Servlet.class)){
try {
//添加至map集合中
map.put(aClass.getAnnotation(Servlet.class).value(), (AbstractServlet) aClass.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void findAndAddClassesInPackageByFile(String packageName,
String packagePath, final boolean recursive, Set<Class<?>> classes) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
@Override
public boolean accept(File file) {
return (recursive && file.isDirectory())
|| (file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "."
+ file.getName(), file.getAbsolutePath(), recursive,
classes);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0,
file.getName().length() - 6);
try {
// 添加到集合中去
// classes.add(Class.forName(packageName + '.' +
// className));
// 经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
classes.add(Thread.currentThread().getContextClassLoader()
.loadClass(packageName + '.' + className));
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}
}
2、Request
package core;
import java.io.IOException;
import java.io.InputStream;
public class Request {
private InputStream is;
private String url;
private String method;
public Request(){
}
public Request(InputStream is){
this.is = is;
parse();
}
public String getMethod() {
return method;
}
public String getUrl(){
return url;
}
/**
* 解析url
*/
public void parse(){
StringBuilder request = new StringBuilder(Response.BUFFER_SIZE);
byte[] buffer = new byte[Response.BUFFER_SIZE];
int i = 0;
try{
i = is.read(buffer);
} catch (IOException e) {
e.printStackTrace();
}
for (int j = 0; j < i; j++) {
request.append((char)buffer[j]);
}
System.out.println(request.toString());
parseUrl(request.toString());
}
/**
*
* @param request
* @return
*/
private void parseUrl(String request) {
int index1,index2;
//查看socket获取的请求头是否有值
index1 = request.indexOf(' ');
if (index1 != -1){
this.method = request.substring(0, index1);
index2 = request.indexOf(' ', index1 + 1);
if (index2 > index1){
this.url = request.substring(index1 + 1,index2);
}
}
}
}
3、Response
package core;
import java.io.*;
public class Response {
public static final Integer BUFFER_SIZE = 2048;
private static final String WEB_ROOT = "D:";
private static final String RESPONSE_HEADER = "HTTP/1.1 200 Read File Success\r\n" +
"Content-Type: text/html;charset=UTF-9\r\n" + "\r\n";
private Request request;
private OutputStream outputStream;
public Response(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void setRequest(Request request) {
this.request = request;
}
public void sendStaticResource() throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
FileInputStream fis = null;
File file = new File(WEB_ROOT, request.getUrl());
String returnMsg = null;
try {
if (file.exists() && !file.isDirectory()) {
fis = new FileInputStream(file);
StringBuilder sb = new StringBuilder();
int length;
while ((length = fis.read(buffer, 0, buffer.length)) != -1) {
sb.append(new String(buffer, 0, length, "gbk"));
}
returnMsg = "HTTP/1.1 200 OK\r\n" +
"Content-Type: text/html \r\n" +
"Content-Length: " + sb.length() + "\r\n" +
"\r\n" +
sb.toString();
} else {
String errorMsg = "<h1>" + file.getName() + " file or directory not exists</h1>";
returnMsg = "HTTP/1.1 404 File Not Fount\r\n" +
"Content-Type: text/html \r\n" +
"Content-Length: " + errorMsg.length() + "\r\n" +
"\r\n" +
errorMsg;
}
outputStream.write(returnMsg.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
fis.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
public void sendResponseContent(StringBuilder message){
try {
outputStream.write(new StringBuilder(RESPONSE_HEADER).append(message).toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、Requesthandler,收到请求就会开启一个线程去处理
package core;
import baseservlet.AbstractServlet;
import com.sun.net.httpserver.HttpServer;
import java.net.Socket;
public class RequestHandler extends Thread{
private Socket socket;
public RequestHandler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
//接收请求参数
Request request = new Request(socket.getInputStream());
AbstractServlet abstractServlet = HTTPServer.map.get(request.getUrl());
//创建用于返回浏览器的对象
Response response = new Response(socket.getOutputStream());
response.setRequest(request);
if (abstractServlet != null){
abstractServlet.service(request,response);
}else{
//找不到对应的Servlet则直接访问文件
response.sendStaticResource();
}
//如果http短连接则关闭socket
//socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5、GenericServlet,定义servlet里的方法
package baseservlet;
import core.Request;
import core.Response;
public interface GenericServlet {
public void init();
public void destroy();
public void service(Request request , Response response);
}
6、AbstractServlet
package baseservlet;
import core.Request;
import core.Response;
public abstract class AbstractServlet implements GenericServlet{
private static final String GET_METHOD = "GET";
private static final String POST_METHOD = "POST";
@Override
public void service(Request request, Response response) {
if(GET_METHOD.equalsIgnoreCase(request.getMethod())){
doGet(request,response);
}else if (POST_METHOD.equalsIgnoreCase(request.getMethod())){
doPost(request,response);
}
}
public abstract void doGet(Request request, Response response);
public abstract void doPost(Request request, Response response);
@Override
public void init() {
}
@Override
public void destroy() {
}
}
7、测试用的servlet
package servlet;
import annotations.Servlet;
import baseservlet.AbstractServlet;
import core.Request;
import core.Response;
//标注路径
@Servlet("/user")
public class UserServlet extends AbstractServlet {
@Override
public void doGet(Request request, Response response) {
doPost(request,response);
}
@Override
public void doPost(Request request, Response response) {
//执行业务代码
response.sendResponseContent(new StringBuilder("<h1>Your are requesting the UserServlet</h1>"));
}
}
8、Main 主启动类
import core.HTTPServer;
public class Main {
//主启动类
public static void main(String[] args) {
HTTPServer httpServer = new HTTPServer();
httpServer.acceptWait();
}
}
在上一篇的基础上,实现了访问servlet