學習smart-framework-mvn分發

基於servlet 思路:java

  1. 啓動時獲取使用Controller 和 Request註解的類,存入map,並處理{}參數。
  2. 對servlet訪問進行分發,訪問的路徑到map中取對應的類和方法,而後執行。

基礎類

枚舉

public enum HttpMethod {
    GET,POST,PUT,DELETE
}

須要的bean部分

RequestBean正則表達式

private HttpMethod requestMethod; //訪問方式
private String requestUrl; //訪問路徑

ActionBean安全

private Class<?> actionClass; //類
private Method actionMethod; //方法

註解

Controlleride

@Target(ElementType.TYPE) //類級別
@Retention(RetentionPolicy.RUNTIME) //在運行時有效
@Documented
public @interface Controller {
    String value() default "";
}

Request性能

@Target(ElementType.METHOD) //方法級別
@Retention(RetentionPolicy.RUNTIME) //在運行時有效
@Documented
public @interface Request {
    String value() default ""; //url
    HttpMethod method() default HttpMethod.GET;
}

存儲controller的map

public class RequestHandler {
    private static final Map<RequestBean, ActionBean> ACTIONMAP = new HashMap<>();

    public static Map<RequestBean, ActionBean> getActionMap() {
        return ACTIONMAP;
    }

    static {
        //獲取全部action
        List<Class<?>> actionList = ClassHelper.getClassListByAnnotation(Controller.class);
        for (Class<?> actionClass : actionList) {
            Method[] actionMethods = actionClass.getDeclaredMethods();
            if (actionMethods != null && actionMethods.length > 0) {
                for (Method actionMethod : actionMethods) {
                    //是否包含path註解
                    if (actionMethod.isAnnotationPresent(Request.class)) {
                        String url = actionMethod.getAnnotation(Request.class).value();
                        HttpMethod method = actionMethod.getAnnotation(Request.class).method();
                        // 將請求路徑中的佔位符 {\w+} 轉換爲正則表達式 (\\w+)
                        url = url.replaceAll("\\{\\w+\\}", "(\\\\w+)");
                        ACTIONMAP.put(new RequestBean(method, url), new ActionBean(actionClass, actionMethod));
                    }
                }
            }
        }
    }

}

serlvet 分發

@WebServlet("/*")
public class DispatcherServlet extends HttpServlet{
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse) res;
        //方法 路徑
        String currentRequestMethod = request.getMethod();
        String currentRequestURL = request.getPathInfo();

        // 屏蔽特殊請求
        if (currentRequestURL.equals("/favicon.ico")) {
            return;
        }
        Map<RequestBean, ActionBean> actionMap = RequestHandler.getActionMap();
        for (Map.Entry<RequestBean, ActionBean> actionEntry : actionMap.entrySet()) {
            RequestBean requestBean = actionEntry.getKey();
            String requestURL = requestBean.getRequestUrl(); // 正則表達式
            HttpMethod requestMethod = requestBean.getRequestMethod();

            // 獲取正則表達式匹配器(用於匹配請求 URL 並從中獲取相應的請求參數)
            Matcher matcher = Pattern.compile(requestURL).matcher(currentRequestURL);
            // 判斷請求方法與請求 URL 是否同時匹配
            if (requestMethod.name().equals(currentRequestMethod) && matcher.matches()) {
                ActionBean actionBean = actionEntry.getValue();
                Class<?> actionClass = actionBean.getActionClass();
                Method actionMethod = actionBean.getActionMethod();

                //取出參數列表
                List<Object> params = new ArrayList<>();
                for (int i = 1; i <= matcher.groupCount(); i++) {
                    String param = matcher.group(i);
                    // 若爲數字,則須要強制轉換,並放入參數列表中
                    Class<?>[] parameterTypes = actionBean.getActionMethod().getParameterTypes();
                    Class<?> parameterType = parameterTypes[i - 1];
                    if (parameterType.equals(String.class)) {
                        params.add(param);
                    }else if (parameterType.equals(int.class)) {
                        params.add(Integer.parseInt(param));
                    }else if (parameterType.equals(long.class)) {
                        params.add(Long.parseLong(param));
                    }else if (parameterType.equals(double.class)) {
                        params.add(Double.parseDouble(param));
                    }
                }

                try {
                    // 建立 Action 實例
                    Object actionInstance = actionClass.newInstance();
                    // 調用 Action 方法(傳入請求參數)
                    actionMethod.setAccessible(true); // 取消類型安全檢測(可提升反射性能)
                    Object result = actionMethod.invoke(actionInstance, params.toArray());
                    response.getWriter().print(JSON.toJSONString(result));
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

                //匹配到就跳出
                break;
            }

        }
    }
}
相關文章
相關標籤/搜索