服务器基本功能实现,实现一套接口
1.注解(此注解作用类似于spring中的RequestMapper)
package com.zj;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE , ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapper {
String path() default "" ;
}
2.服务器需要的接口
1)HttpServlet
package com.inter;
public interface HttpServlet {
void service(HttpServletRequest request , HttpServletResponse response) throws Exception ;
}
2)HttpServletRequest
package com.inter;
import java.util.Map;
public interface HttpServletRequest {
/**
* 获取请求参数
* @param key 请求参数
* @return 请求参数的值
*/
String getParameter(String key) ;
/**
* 设置请求编码
* @param charset 编码类型
*/
void setCharacter(String charset) ;
/**
* 获取请求头参数
* @param key
* @return
*/
String getHeadField(String key) ;
/**
* 获取请求ip
*/
String getRequestIP() ;
/**
* 获取所有请求参数
* @return
*/
Map getParameters() ;
}
3)HttpServletResponse
package com.inter;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
public interface HttpServletResponse {
/**
* 设置返回前端编码
**/
void setCharactor(String charset) ;
/**
* 获取浏览器io对象
* @return
*/
OutputStream getOutputStream() ;
/**
* 获取字符流对象
* @throws UnsupportedEncodingException
*/
PrintStream getWriter() throws UnsupportedEncodingException ;
/**
* 设置返回数据类型
* @throws Exception
*/
void setContentTyoe(String type) throws Exception ;
/**
* 设置重定向地址
* @param url
*/
void sendRedirect(String url) ;
}
这套接口是模仿javaweb的
3.接口实现
1)Request
package com.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpCookie;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import org.jboss.com.sun.net.httpserver.Headers;
import org.jboss.com.sun.net.httpserver.HttpExchange;
import com.inter.HttpServletRequest;
/**
* 采用适配器原理将exange对象拆分成Request和Response两个对象
* @author wf
*
*/
public class Request implements HttpServletRequest {
//定义一个Exange对象
private HttpExchange exchange ;
/**
* 保存字符串编码
*/
private String charset = "utf-8" ;
/**
* 请求参数保存
*/
private Map query = null ;
/**
* 参数部分字符串
*/
private String paramesString = "" ;
/**
* 保存当前访问对象的cookie
*/
private HttpCookie cookie ;
/**
* 构造方法
* @param exchange 每次请求的exange对象
*/
public Request(HttpExchange exchange){
this.exchange = exchange ;
}
public String getParameter(String key) {
if(query == null){
query = queryFormat() ;
}
return query.get(key);
}
public Map getParameters() {
if(query == null){
query = queryFormat() ;
}
return query;
}
public void setCharacter(String charset) {
this.charset = charset ;
query = null ;
queryFormat() ;
}
public String getHeadField(String key) {
Headers header = exchange.getRequestHeaders() ;
return (header.get(key) != null ? header.get(key).toString() : null);
}
public String getRequestIP() {
return exchange.getRemoteAddress().getHostName();
}
/**
* 请求参数拆分
*/
private Map queryFormat(){
if(paramesString == null || "".equals(paramesString)){
paramesString = queryGet() ;
}
return getQuerys() ;
}
/**
* 请求参数拆分
*/
private String queryGet(){
//获取请求的地址
String urlString = exchange.getRequestURI().toString() ;
//拿到输出流对象
OutputStream out = null ;
BufferedReader read = new BufferedReader(new InputStreamReader(exchange.getRequestBody())) ;
String line = "" ;
urlString = urlString.contains("?") ? urlString+"&" : urlString + "?" ;
//读取POst请求参数
try{
while((line = read.readLine()) != null){
urlString += line ;
}
}catch(Exception e){
System.out.println(e);
int len = e.toString().getBytes().length ;
exchange.getResponseHeaders().add("Content-Type", "text/html;charset=utf-8");
try {
exchange.sendResponseHeaders(500, len);
out = exchange.getResponseBody() ;
out.write(e.toString().getBytes());
} catch (Exception e2) {
System.out.println(e);
} finally{
if(out != null){
try {
out.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}finally{
if(read != null){
try {
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//拆分参数部分字符串
String parames = "";
if (urlString.contains("?")) {
String[] strs = urlString.split("\\?");
if(strs.length > 1){
parames = strs[1];
}
}
return parames ;
}
/**
* 请求参数拆分
* @param parames
* @return
*/
private Map getQuerys() {
Map map = new HashMap() ;
if (!paramesString.equals("")) {
String[] strs = null ;
if(!paramesString.contains("&")){
strs = new String[]{paramesString};
}else{
strs = paramesString.split("&");
}
for (String string : strs) {
if (string.contains("=")) {
String[] strs1 = string.split("=") ;
if(strs1.length > 1){
String k = strs1[0];
String v = strs1[1];
try {
v = URLDecoder.decode(v, charset) ;
map.put(k, v);
} catch (UnsupportedEncodingException e) {
map.put(k, v);
}
}
}
}
}
return map;
}
}
2)Response
package com.server;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpCookie;
import java.util.Map;
import java.util.Set;
import org.jboss.com.sun.net.httpserver.Headers;
import org.jboss.com.sun.net.httpserver.HttpExchange;
import com.inter.HttpServletResponse;
public class Response implements HttpServletResponse {
//保存浏览器访问对象
private HttpExchange exchange ;
/**
* 保存返回前端编码
*/
private String charset = "utf-8" ;
/**
* 定义缓冲区大小
*/
private final int SIZE = 1024*1024 ;
/**
* 定义一个缓冲区(采用静态代理)
*/
private MyByteArrayOutputStream byteBuf = new MyByteArrayOutputStream(SIZE) ;
/**
* 请求头是否已经返回
*/
private boolean isSendHead = false ;
/**
* 返回头
*/
private Headers header ;
/**
* 重定向地址
*/
private String reUrl = null ;
/**
* @param exchange
*/
public Response(HttpExchange exchange) {
this.exchange = exchange ;
//初始化headers对象
header = exchange.getResponseHeaders() ;
//默认以text/html返回
header.add("Content-Type", "text/html");
}
public void setCharactor(String charset) {
this.charset = charset ;
}
public OutputStream getOutputStream() {
return byteBuf ;
}
public PrintStream getWriter() throws UnsupportedEncodingException {
return new PrintStream(byteBuf , true , charset);
}
public void setContentTyoe(String type) throws Exception {
if(isSendHead){
throw new Exception("header already send !!!") ;
}
if(header.containsKey("Content-Type")){
header.set("Content-Type", type);
return ;
}
header.add("Content-Type", type);
}
public void sendRedirect(String url) {
reUrl = url ;
}
public String getReUrl(){
return reUrl ;
}
/**
* 以下方法全部设置为私有方法供反射调用
*/
private synchronized void flush(){
try {
if(!isSendHead){
exchange.sendResponseHeaders(200 , 0);
isSendHead = true ;
}
exchange.getResponseBody().write(byteBuf.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
}
private String cookieFormat(Map map){
Set set = map.keySet() ;
StringBuffer buf = new StringBuffer() ;
for (String s : set) {
buf.append(s+"="+map.get(s)+";") ;
}
return buf.replace(buf.length()-1, buf.length(), "").toString() ;
}
/**
* 直接返回
*/
protected synchronized void response(int code , String data){
try {
if(!isSendHead){
Headers head = exchange.getResponseHeaders();
head.add("Content-Type", "text/html;charset="+charset);
exchange.sendResponseHeaders(code, data.getBytes(charset).length);
isSendHead = true ;
}
exchange.getResponseBody().write(data.getBytes(charset));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 定义一个自己的字节流对象
* @author Administrator
*
*/
class MyByteArrayOutputStream extends ByteArrayOutputStream {
public MyByteArrayOutputStream(int size){
super(size) ;
}
@Override
public void write(byte[] b) throws IOException {
if(this.size() + 1 >= SIZE){
if(!isSendHead){
exchange.sendResponseHeaders(202, 0);
isSendHead = true ;
}
exchange.getResponseBody().write(byteBuf.toByteArray());
this.reset();
}
super.write(b);
}
@Override
public synchronized void write(byte[] b, int off, int len) {
if(this.size() + len >= SIZE){
try {
if(!isSendHead){
exchange.sendResponseHeaders(202, 0);
isSendHead = true ;
}
exchange.getResponseBody().write(byteBuf.toByteArray());
this.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
super.write(b, off, len);
}
@Override
public synchronized void write(int b) {
if(this.size() + 1 >= SIZE){
try {
if(!isSendHead){
exchange.sendResponseHeaders(202, 0);
isSendHead = true ;
}
exchange.getResponseBody().write(byteBuf.toByteArray());
this.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
super.write(b);
}
}
}
4.Server类的初始化
package com.server;
/******************************************************************************
* 对jdk的HttpServer再封装 *
* 实现一套注解(后端路由表&监听器注册) *
* 模仿javaweb的回话跟踪(Session) *
* 此项目的是练习java的设计模式 *
* 使用到了(单例,适配器,观察者,代理) *
******************************************************************************/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.jboss.com.sun.net.httpserver.HttpExchange;
import org.jboss.com.sun.net.httpserver.HttpHandler;
import org.jboss.com.sun.net.httpserver.HttpServer;
import com.inter.HttpServletRequest;
import com.inter.HttpServletResponse;
import com.zj.RequestMapper;
/**
* 对jdk自带的HttpServer类进行二次封装
* @author wf
*/
public class Server {
/**
* 绑定端口
*/
private int port = 9999 ;
/**
* servlet所在包名
*/
private String servlet = "com.servlet" ;
/**
* 保存访问地址的映射
*/
private Map urls = new HashMap() ;
/**
* 保存方法的映射
*/
private Map
服务器的基本代码已经封装完成
接下来再com.servlet中写一个Servlet做测试
1.UserServlet
package com.servlet;
import java.io.UnsupportedEncodingException;
import com.inter.HttpServlet;
import com.inter.HttpServletRequest;
import com.inter.HttpServletResponse;
import com.zj.RequestMapper;
@RequestMapper(path = "/user.do")
public class UserServlet implements HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response)
throws Exception {
String name = request.getParameter("name") ;
response.getWriter().print(name);
}
@RequestMapper(path="regist")
public void regist(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException{
System.out.println("正在注册");
response.getWriter().print("Success");
}
}
建一个类启动服务器
Test
import com.server.Server;
public class Test {
public static void main(String[] args) throws Exception {
Server server = new Server(9999, "com.servlet") ; //9999表示监听端口,com.servlet表示等下要扫描这个包中的注解
server.init() ;
}
}
跑起来以后再浏览器中输入 http://127.0.0.1:9999/user.do?name=wf
浏览器会输出wf
输入 http://127.0.0.1:9999/user.do?method=regist
服务器端会在控制台输出“正在注册” , 浏览器会输出success
完整代码已经上传到github:https://github.com/wangffei/HttpServer
目前已经支持cookie的解析,支持session,还有一套类似于javaweb的基本语法(代码非常简单,只是平时练习的作品,需要使用的话可以自己扩充修改)