自定义miniTomcat功能(2)

在请求处理上具有责任链功能

存储拦截器类

package com.hole.servlet;

import com.hole.http.HttpSession;
import com.hole.util.Interceptor;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * @description: servlet 上下文
 * @author: guozi
 * @create: 2021-01-22
 */
public class ServletContext {
    /**
     * servlet容器,存储servlet
     **/
    public static Map<String, Object> servlets = new Hashtable<>();

    /**
     * session存储
     **/
    public static Map<String, HttpSession>  sessionContext = new HashMap<>();

    /**
     * 拦截起类存储
     **/
    public static Map<String, String>  interceptorContext = new HashMap<>();



}

拦截器接口

package com.hole.util;
import java.lang.reflect.Method;


/**
 * @describtion: 拦截器接口
 * @author: guozi
 * @create: 2021-01-30
 */
public interface Interceptor {

    /**
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数
     */
     boolean before(Object proxy, Object target, Method method, Object[] args);

     void around(Object proxy, Object target, Method method, Object[] args);

     void after(Object proxy, Object target, Method method, Object[] args);
}

拦截器父类

package com.hole.util;

import com.hole.server.DynamicProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

public class InterceptorObject implements  Interceptor{
    public static final Logger logger = LoggerFactory.getLogger(InterceptorObject.class);

    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        logger.info("no before action to do");
        return true;
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        logger.info("no round action to do");

    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        logger.info("no after action to do");
    }
}

重点,利用反射和代理实现拦截器

package com.hole.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * @describtion: 拦截器和真实对象代理代理
 * @author: guozi
 * @create: 2021-03-22
 */
public class InterceptorProxy implements InvocationHandler {

    private Object target; //真实对象
    private String interceptorClass = null;//拦截器全限定名

    public InterceptorProxy(Object target, String interceptorClass) {
        this.target = target;
        this.interceptorClass = interceptorClass;
    }

    /**
     * 绑定委托对象并返回一个【代理占位】
     *
     * @param target 真实对象
     * @return 代理对象【占位】
     */
    public static Object bind(Object target, String interceptorClass) {
        //取得代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InterceptorProxy(target, interceptorClass));
    }

    @Override
    /**
     * 通过代理对象调用方法,首先进入这个方法.
     *
     * @param proxy --代理对象
     * @param method --方法,被调用方法
     * @param args -- 方法的参数
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (interceptorClass == null) {
            //没有设置拦截器则直接反射原有方法
            return method.invoke(target, args);
        }
        Object result = null;
        //通过反射生成拦截器
        Interceptor interceptor =
                (Interceptor) Class.forName(interceptorClass).newInstance();
        //调用前置方法,是否要执行原有对象的target方法
        if (interceptor.before(proxy, target, method, args)) {
            //反射原有对象方法
            result = method.invoke(target, args);
        } else {//返回false执行around方法
            interceptor.around(proxy, target, method, args);
        }
        //调用后置方法
        interceptor.after(proxy, target, method, args);
        return result;
    }
}

最后,在处理请求前,安装顺序调用拦截器

package com.hole.server;

import com.hole.http.HttpServletRequest;
import com.hole.http.HttpServletResponse;
import com.hole.servlet.ServletContext;
import com.hole.util.InterceptorProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;


/**
 * @describtion: 客户端连接信息处理服务
 * @author: guozi
 * @create: 2021-01-25
 */
public class ServerService implements Runnable{
    /**
     * 连接客户端信息
     */
    private Socket client;
    public static final Logger logger = LoggerFactory.getLogger(ServerService.class);

    public ServerService(Socket socket){
        super();
        this.client = socket;
    }

    @Override
    public void run() {
        InputStream input = null;
        OutputStream output = null;
        try{
            input = this.client.getInputStream();
            output = this.client.getOutputStream();
        }catch (Exception e){
            logger.error("客户端{}连接断开,原因:{}", this.client.getRemoteSocketAddress(), e.getMessage());
            return;
        }

        //采用的是http协议,基于连接信息,创建http请求和响应对象
        HttpServletRequest httpServletRequest = new HttpServletRequest(input);
        HttpServletResponse httpServletResponse = new HttpServletResponse(httpServletRequest, output);

        //判断是否是动态还是静态请求,动态请求包括.action->要给到的处理类
        String url = httpServletRequest.getRequestUrl();
        Processor processor = null;
        if(url.contains(".action")){
            processor = new DynamicProcessor();
        }else{
            processor = new StaticProcessor();
        }
        //servlet处理 , 链式步骤处理过来的请求
        Processor interceptorProxy = processor;
        for(String interceptor : ServletContext.interceptorContext.values()){
             interceptorProxy = (Processor) InterceptorProxy.bind(interceptorProxy,interceptor);
        }
        interceptorProxy.process(httpServletRequest, httpServletResponse);
        try{
            //http是短连接,需要及时关闭
            this.client.close();
        }catch (Exception e){
            logger.error("客户端{}连接断开失败,原因:{}", this.client.getRemoteSocketAddress(), e.getMessage());
        }

    }
}

自定义线程池参考

https://mp.csdn.net/editor/html/114963802   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值