成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(九)--優(yōu)化MVC代碼

ruicbAndroid / 1659人閱讀

摘要:前言在從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架七實(shí)現(xiàn)中實(shí)現(xiàn)了框架的的功能,不過(guò)最后指出代碼的邏輯不是很好,在這一章節(jié)就將這一部分代碼進(jìn)行優(yōu)化。

前言

在從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(七)--實(shí)現(xiàn)MVC中實(shí)現(xiàn)了doodle框架的MVC的功能,不過(guò)最后指出代碼的邏輯不是很好,在這一章節(jié)就將這一部分代碼進(jìn)行優(yōu)化。

優(yōu)化的目標(biāo)是1.去除DispatcherServlet請(qǐng)求分發(fā)器中的http邏輯代碼;2.將ControllerHandlerResultRender中代碼按功能細(xì)分出來(lái),使其各司其職。

修改DispatcherServlet 創(chuàng)建接口

先在com.zbw.mvc包下創(chuàng)建兩個(gè)包handler和render,分別用于放ControllerHandlerResultRender拆分出來(lái)的功能類(lèi)。

再在這兩個(gè)包下創(chuàng)建兩個(gè)接口,以便后面的功能類(lèi)都按這個(gè)接口規(guī)范。

package com.zbw.mvc.handler;

import com.zbw.mvc.RequestHandlerChain;

/**
 * 請(qǐng)求執(zhí)行器 Handler
 */
public interface Handler {
    /**
     * 請(qǐng)求的執(zhí)行器
     */
    boolean handle(final RequestHandlerChain handlerChain) throws Exception;
}
package com.zbw.mvc.render;

import com.zbw.mvc.RequestHandlerChain;

/**
 * 渲染請(qǐng)求結(jié)果 interface
 */
public interface Render {
    /**
     * 執(zhí)行渲染
     */
    void render(RequestHandlerChain handlerChain) throws Exception;
}
實(shí)現(xiàn)RequestHandlerChain

上面兩個(gè)接口都有個(gè)參數(shù)RequestHandlerChain,這個(gè)類(lèi)是整個(gè)請(qǐng)求的執(zhí)行鏈,用于存儲(chǔ)整個(gè)請(qǐng)求需要保存的一些屬性和串聯(lián)整個(gè)請(qǐng)求。

在com.zbw.mvc下創(chuàng)建這個(gè)類(lèi)

package com.zbw.mvc;
import ...

/**
 * http請(qǐng)求處理鏈
 */
@Data
@Slf4j
public class RequestHandlerChain {
    /**
     * Handler迭代器
     */
    private Iterator handlerIt;

    /**
     * 請(qǐng)求request
     */
    private HttpServletRequest request;

    /**
     * 請(qǐng)求response
     */
    private HttpServletResponse response;

    /**
     * 請(qǐng)求http方法
     */
    private String requestMethod;

    /**
     * 請(qǐng)求http路徑
     */
    private String requestPath;

    /**
     * 請(qǐng)求狀態(tài)碼
     */
    private int responseStatus;

    /**
     * 請(qǐng)求結(jié)果處理器
     */
    private Render render;

    public RequestHandlerChain(Iterator handlerIt, HttpServletRequest request, HttpServletResponse response) {
        this.handlerIt = handlerIt;
        this.request = request;
        this.response = response;
        this.requestMethod = request.getMethod();
        this.requestPath = request.getPathInfo();
        this.responseStatus = HttpServletResponse.SC_OK;
    }

    /**
     * 執(zhí)行請(qǐng)求鏈
     */
    public void doHandlerChain() {
        try {
            while (handlerIt.hasNext()) {
                if (!handlerIt.next().handle(this)) {
                    break;
                }
            }
        } catch (Exception e) {
            log.error("doHandlerChain error", e);
            render = new InternalErrorRender();
        }
    }

    /**
     * 執(zhí)行處理器
     */
    public void doRender() {
        if (null == render) {
            render = new DefaultRender();
        }
        try {
            render.render(this);
        } catch (Exception e) {
            log.error("doRender", e);
            throw new RuntimeException(e);
        }
    }
}

在這個(gè)類(lèi)中除了存儲(chǔ)http請(qǐng)求信息以外,還有Handler迭代器handlerIt和請(qǐng)求結(jié)果處理器Render。

doHandlerChain()方法就會(huì)迭代執(zhí)行handlerIt中的Handler的handle()方法,并且會(huì)根據(jù)每個(gè)Handler返回的值來(lái)判斷是否繼續(xù)往下執(zhí)行下一個(gè)Handler。

doRender()方法用于調(diào)用Render中的render()方法。

更改DispatcherServlet

接下來(lái)就可以修改DispatcherServlet請(qǐng)求轉(zhuǎn)發(fā)器了。

package com.zbw.mvc;
import ...

/**
 * DispatcherServlet 所有http請(qǐng)求都由此Servlet轉(zhuǎn)發(fā)
 */
@Slf4j
public class DispatcherServlet extends HttpServlet {

    /**
     * 請(qǐng)求執(zhí)行鏈
     */
    private final List HANDLER = new ArrayList<>();

    /**
     * 執(zhí)行請(qǐng)求
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        RequestHandlerChain handlerChain = new RequestHandlerChain(HANDLER.iterator(), req, resp);
        handlerChain.doHandlerChain();
        handlerChain.doRender();
    }
}

可以看到現(xiàn)在DispatcherServlet已經(jīng)很簡(jiǎn)潔了,把請(qǐng)求的邏輯代碼交給RequestHandlerChain處理,自己沒(méi)有多余的http邏輯代碼。

實(shí)現(xiàn)幾種Handler

上面只創(chuàng)建了Handler的接口沒(méi)有實(shí)現(xiàn)類(lèi),現(xiàn)在就實(shí)現(xiàn)幾個(gè)Handler的實(shí)現(xiàn)類(lèi)。這些實(shí)現(xiàn)類(lèi)只實(shí)現(xiàn)了簡(jiǎn)單的一些http請(qǐng)求的功能,大家可以自己根據(jù)情況開(kāi)發(fā)更多的實(shí)現(xiàn)類(lèi)。

PreRequestHandler

首先是PreRequestHandler,用于預(yù)處理http的一些信息,比如設(shè)置http編碼,處理請(qǐng)求url,打印一些信息等。

package com.zbw.mvc.handler;
import ...

/**
 * 請(qǐng)求預(yù)處理
 */
@Slf4j
public class PreRequestHandler implements Handler {
    @Override
    public boolean handle(final RequestHandlerChain handlerChain) throws Exception {
        // 設(shè)置請(qǐng)求編碼方式
        handlerChain.getRequest().setCharacterEncoding("UTF-8");
        String requestPath = handlerChain.getRequestPath();
        if (requestPath.length() > 1 && requestPath.endsWith("/")) {
            handlerChain.setRequestPath(requestPath.substring(0, requestPath.length() - 1));
        }
        log.info("[Doodle] {} {}", handlerChain.getRequestMethod(), handlerChain.getRequestPath());
        return true;
    }
}
SimpleUrlHandler

接下來(lái)是SimpleUrlHandler,用于處理靜態(tài)資源,當(dāng)碰到資源是靜態(tài)資源時(shí)就直接轉(zhuǎn)發(fā)請(qǐng)求到Tomcat默認(rèn)的servlet去。

package com.zbw.mvc.handler;
import ...

/**
 * 普通url請(qǐng)求執(zhí)行
 * 主要處理靜態(tài)資源
 */
@Slf4j
public class SimpleUrlHandler implements Handler {
    /**
     * tomcat默認(rèn)RequestDispatcher的名稱(chēng)
     * TODO: 其他服務(wù)器默認(rèn)的RequestDispatcher.如WebLogic為FileServlet
     */
    private static final String TOMCAT_DEFAULT_SERVLET = "default";

    /**
     * 默認(rèn)的RequestDispatcher,處理靜態(tài)資源
     */
    private RequestDispatcher defaultServlet;

    public SimpleUrlHandler(ServletContext servletContext) {
        defaultServlet = servletContext.getNamedDispatcher(TOMCAT_DEFAULT_SERVLET);

        if (null == defaultServlet) {
            throw new RuntimeException("沒(méi)有默認(rèn)的Servlet");
        }

        log.info("The default servlet for serving static resource is [{}]", TOMCAT_DEFAULT_SERVLET);
    }


    @Override
    public boolean handle(final RequestHandlerChain handlerChain) throws Exception {
        if (isStaticResource(handlerChain.getRequestPath())) {
            defaultServlet.forward(handlerChain.getRequest(), handlerChain.getResponse());
            return false;
        }
        return true;
    }

    /**
     * 是否為靜態(tài)資源
     */
    private boolean isStaticResource(String url) {
        return url.startsWith(Doodle.getConfiguration().getAssetPath());
    }
}
JspHandler

然后是處理jsp頁(yè)面的實(shí)現(xiàn)類(lèi)JspHandler,當(dāng)碰到資源是jsp頁(yè)面時(shí)就直接轉(zhuǎn)發(fā)請(qǐng)求到Tomcat的jsp的servlet去。

package com.zbw.mvc.handler;
import ...

/**
 * jsp請(qǐng)求處理
 * 主要負(fù)責(zé)jsp資源請(qǐng)求
 */
public class JspHandler implements Handler {
    /**
     * jsp請(qǐng)求的RequestDispatcher的名稱(chēng)
     */
    private static final String JSP_SERVLET = "jsp";

    /**
     * jsp的RequestDispatcher,處理jsp資源
     */
    private RequestDispatcher jspServlet;

    public JspHandler(ServletContext servletContext) {
        jspServlet = servletContext.getNamedDispatcher(JSP_SERVLET);
        if (null == jspServlet) {
            throw new RuntimeException("沒(méi)有jsp Servlet");
        }
    }

    @Override
    public boolean handle(final RequestHandlerChain handlerChain) throws Exception {
        if (isPageView(handlerChain.getRequestPath())) {
            jspServlet.forward(handlerChain.getRequest(), handlerChain.getResponse());
            return false;
        }
        return true;
    }

    /**
     * 是否為jsp資源
     */
    private boolean isPageView(String url) {
        return url.startsWith(Doodle.getConfiguration().getViewPath());
    }
}
ControllerHandler

最后就是ControllerHandler,這個(gè)和從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(七)--實(shí)現(xiàn)MVC中的ControllerHandler功能一樣,用于處理請(qǐng)求中數(shù)據(jù)和controller對(duì)應(yīng)的關(guān)系。

package com.zbw.mvc.handler;
import ...

/**
 * Controller請(qǐng)求處理
 */
@Slf4j
public class ControllerHandler implements Handler {
    /**
     * 請(qǐng)求信息和controller信息關(guān)系map
     */
    private Map pathControllerMap = new ConcurrentHashMap<>();
    /**
     * bean容器
     */
    private BeanContainer beanContainer;

    public ControllerHandler() {
        beanContainer = BeanContainer.getInstance();

        Set> mappingSet = beanContainer.getClassesByAnnotation(RequestMapping.class);
        this.initPathControllerMap(mappingSet);
    }

    @Override
    public boolean handle(final RequestHandlerChain handlerChain) throws Exception {
        String method = handlerChain.getRequestMethod();
        String path = handlerChain.getRequestPath();
        ControllerInfo controllerInfo = pathControllerMap.get(new PathInfo(method, path));
        if (null == controllerInfo) {
            handlerChain.setRender(new NotFoundRender());
            return false;
        }
        Object result = invokeController(controllerInfo, handlerChain.getRequest());
        setRender(result, controllerInfo, handlerChain);
        return true;
    }

    /**
     * 執(zhí)行controller方法
     */
    private Object invokeController(ControllerInfo controllerInfo, HttpServletRequest request) {
        Map requestParams = getRequestParams(request);
        List methodParams = instantiateMethodArgs(controllerInfo.getMethodParameter(), requestParams);

        Object controller = beanContainer.getBean(controllerInfo.getControllerClass());
        Method invokeMethod = controllerInfo.getInvokeMethod();
        invokeMethod.setAccessible(true);
        Object result;
        try {
            if (methodParams.size() == 0) {
                result = invokeMethod.invoke(controller);
            } else {
                result = invokeMethod.invoke(controller, methodParams.toArray());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 設(shè)置請(qǐng)求結(jié)果執(zhí)行器
     */
    private void setRender(Object result, ControllerInfo controllerInfo, RequestHandlerChain handlerChain) {
        if (null == result) {
            return;
        }
        Render render;
        boolean isJson = controllerInfo.getInvokeMethod().isAnnotationPresent(ResponseBody.class);
        if (isJson) {
            render = new JsonRender(result);
        } else {
            render = new ViewRender(result);
        }
        handlerChain.setRender(render);
    }

    /**
     * 初始化pathControllerMap
     */
    private void initPathControllerMap(Set> mappingSet) {
        mappingSet.forEach(this::addPathController);
    }

    /**
     * 添加controllerInfo到pathControllerMap中
     */
    private void addPathController(Class clz) {
        RequestMapping requestMapping = clz.getAnnotation(RequestMapping.class);
        String basePath = requestMapping.value();
        if (!basePath.startsWith("/")) {
            basePath = "/" + basePath;
        }
        for (Method method : clz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping methodRequest = method.getAnnotation(RequestMapping.class);
                String methodPath = methodRequest.value();
                if (!methodPath.startsWith("/")) {
                    methodPath = "/" + methodPath;
                }
                String url = basePath + methodPath;
                Map> methodParams = this.getMethodParams(method);
                String httpMethod = String.valueOf(methodRequest.method());
                PathInfo pathInfo = new PathInfo(httpMethod, url);
                if (pathControllerMap.containsKey(pathInfo)) {
                    log.warn("url:{} 重復(fù)注冊(cè)", pathInfo.getHttpPath());
                }
                ControllerInfo controllerInfo = new ControllerInfo(clz, method, methodParams);
                this.pathControllerMap.put(pathInfo, controllerInfo);
                log.info("mapped:[{},method=[{}]] controller:[{}@{}]",
                        pathInfo.getHttpPath(), pathInfo.getHttpMethod(),
                        controllerInfo.getControllerClass().getName(), controllerInfo.getInvokeMethod().getName());
            }
        }
    }

    /**
     * 獲取執(zhí)行方法的參數(shù)
     */
    private Map> getMethodParams(Method method) {
        Map> map = new HashMap<>();
        for (Parameter parameter : method.getParameters()) {
            RequestParam param = parameter.getAnnotation(RequestParam.class);
            // TODO: 不使用注解匹配參數(shù)名字
            if (null == param) {
                throw new RuntimeException("必須有RequestParam指定的參數(shù)名");
            }
            map.put(param.value(), parameter.getType());
        }
        return map;
    }

    /**
     * 獲取HttpServletRequest中的參數(shù)
     */
    private Map getRequestParams(HttpServletRequest request) {
        Map paramMap = new HashMap<>();
        //GET和POST方法是這樣獲取請(qǐng)求參數(shù)的
        request.getParameterMap().forEach((paramName, paramsValues) -> {
            if (ValidateUtil.isNotEmpty(paramsValues)) {
                paramMap.put(paramName, paramsValues[0]);
            }
        });
        // TODO: Body、Path、Header等方式的請(qǐng)求參數(shù)獲取
        return paramMap;
    }

    /**
     * 實(shí)例化方法參數(shù)
     */
    private List instantiateMethodArgs(Map> methodParams, Map requestParams) {
        return methodParams.keySet().stream().map(paramName -> {
            Class type = methodParams.get(paramName);
            String requestValue = requestParams.get(paramName);
            Object value;
            if (null == requestValue) {
                value = CastUtil.primitiveNull(type);
            } else {
                value = CastUtil.convert(type, requestValue);
                // TODO: 實(shí)現(xiàn)非原生類(lèi)的參數(shù)實(shí)例化
            }
            return value;
        }).collect(Collectors.toList());
    }

}
初始化HANDLER列表和去除TomcatServer的多余代碼

剛才實(shí)現(xiàn)的幾個(gè)HANDLER還需要初始化,就在DispatcherServletinit()方法中初始化。注意初始化的順序會(huì)決定其在RequestHandlerChain執(zhí)行鏈中執(zhí)行的先后。

...
@Slf4j
public class DispatcherServlet extends HttpServlet {
    ...

    /**
     * 初始化Servlet
     */
    @Override
    public void init() throws ServletException {
        HANDLER.add(new PreRequestHandler());
        HANDLER.add(new SimpleUrlHandler(getServletContext()));
        HANDLER.add(new JspHandler(getServletContext()));
        HANDLER.add(new ControllerHandler());
    }
    ...
}

然后去除TomcatServerJspServletDefaultServlet兩個(gè)servlet的初始化,因?yàn)橐呀?jīng)在 JspHandlerSimpleUrlHandler中初始化了這兩個(gè)servlet。

...
@Slf4j
public class TomcatServer implements Server {
    ...
    public TomcatServer(Configuration configuration) {
        try {
            this.tomcat = new Tomcat();
            tomcat.setBaseDir(configuration.getDocBase());
            tomcat.setPort(configuration.getServerPort());

            File root = getRootFolder();
            File webContentFolder = new File(root.getAbsolutePath(), configuration.getResourcePath());
            if (!webContentFolder.exists()) {
                webContentFolder = Files.createTempDirectory("default-doc-base").toFile();
            }

            log.info("Tomcat:configuring app with basedir: [{}]", webContentFolder.getAbsolutePath());
            StandardContext ctx = (StandardContext) tomcat.addWebapp(configuration.getContextPath(), webContentFolder.getAbsolutePath());
            ctx.setParentClassLoader(this.getClass().getClassLoader());

            WebResourceRoot resources = new StandardRoot(ctx);
            ctx.setResources(resources);
            
            // 去除了JspHandler和SimpleUrlHandler這兩個(gè)servlet的注冊(cè)
            
            tomcat.addServlet(configuration.getContextPath(), "dispatcherServlet", new DispatcherServlet()).setLoadOnStartup(0);
            ctx.addServletMappingDecoded("/*", "dispatcherServlet");
        } catch (Exception e) {
            log.error("初始化Tomcat失敗", e);
            throw new RuntimeException(e);
        }
    }
}
實(shí)現(xiàn)幾種Render

上面創(chuàng)建的Render接口也需要一些實(shí)現(xiàn)類(lèi)。同樣的,這些Render也只是實(shí)現(xiàn)基本的功能 ,大家可以自己根據(jù)情況開(kāi)發(fā)更多。

DefaultRender

這個(gè)是默認(rèn)的Render,設(shè)置HttpServletResponse中的status為RequestHandlerChain中StatusCode。

package com.zbw.mvc.render;
import ...
/**
 * 默認(rèn)渲染 200
 */
public class DefaultRender implements Render {
    @Override
    public void render(RequestHandlerChain handlerChain) throws Exception {
        int status = handlerChain.getResponseStatus();
        handlerChain.getResponse().setStatus(status);
    }
}
InternalErrorRender

這個(gè)Render返回StatusCode為500

package com.zbw.mvc.render;
import ...
/**
 * 渲染500
 */
public class InternalErrorRender implements Render {
    @Override
    public void render(RequestHandlerChain handlerChain) throws Exception {
        handlerChain.getResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}
NotFoundRender

這個(gè)Render返回StatusCode為404

package com.zbw.mvc.render;
import ...

/**
 * 渲染404
 */
public class NotFoundRender implements Render {
    @Override
    public void render(RequestHandlerChain handlerChain) throws Exception {
        handlerChain.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND);
    }
}
JsonRender

這個(gè)Render返回json數(shù)據(jù),當(dāng)Handler請(qǐng)求發(fā)現(xiàn)返回?cái)?shù)據(jù)為json格式時(shí),就用這個(gè)Render

package com.zbw.mvc.render;
import ...

/**
 * 渲染json
 */
@Slf4j
public class JsonRender implements Render {
    private Object jsonData;
    public JsonRender(Object jsonData) {
        this.jsonData = jsonData;
    }
    @Override
    public void render(RequestHandlerChain handlerChain) throws Exception {
        // 設(shè)置響應(yīng)頭
        handlerChain.getResponse().setContentType("application/json");
        handlerChain.getResponse().setCharacterEncoding("UTF-8");
        // 向響應(yīng)中寫(xiě)入數(shù)據(jù)
        try (PrintWriter writer = handlerChain.getResponse().getWriter()) {
            writer.write(JSON.toJSONString(jsonData));
            writer.flush();
        }
    }
}
ViewRender

這個(gè)Render跳轉(zhuǎn)到頁(yè)面,將ModelAndView中的信息存到HttpServletRequest中并跳轉(zhuǎn)到對(duì)應(yīng)頁(yè)面

package com.zbw.mvc.render;
import ...

/**
 * 渲染頁(yè)面
 */
@Slf4j
public class ViewRender implements Render {
    private ModelAndView mv;
    public ViewRender(Object mv) {
        if (mv instanceof ModelAndView) {
            this.mv = (ModelAndView) mv;
        } else if (mv instanceof String) {
            this.mv = new ModelAndView().setView((String) mv);
        } else {
            throw new RuntimeException("返回類(lèi)型不合法");
        }
    }
    @Override
    public void render(RequestHandlerChain handlerChain) throws Exception {
        HttpServletRequest req = handlerChain.getRequest();
        HttpServletResponse resp = handlerChain.getResponse();
        String path = mv.getView();
        Map model = mv.getModel();
        model.forEach(req::setAttribute);
        req.getRequestDispatcher(Doodle.getConfiguration().getViewPath() + path).forward(req, resp);
    }
}
結(jié)語(yǔ)

至此,MVC的優(yōu)化完成了,同時(shí)整個(gè)doodle框架的代碼也算是完成了。

雖然doodle早已完成,但是講解的文章托托延延到現(xiàn)在才完成。

在剛完成doodle時(shí)感覺(jué)整個(gè)框架已經(jīng)成型了,但是在寫(xiě)這個(gè)系列文章的過(guò)程中才真正發(fā)現(xiàn)欠缺的還有非常非常多,甚至覺(jué)得把它稱(chēng)為框架都有些抬舉它了呢。

只能說(shuō)在實(shí)現(xiàn)它然后再寫(xiě)這個(gè)系列的文章之后對(duì)spring的崇拜之心更加深了,其被javaer廣泛使用和拜讀果然是有原因的。

另外也感謝大家閱讀這個(gè)系列的文章,如果對(duì)大家有所幫助的話(huà)可以去給我的項(xiàng)目加個(gè)star,有什么問(wèn)題和建議也可以提出來(lái)交流交流。

這個(gè)系列的所有文章我都放在我的博客上了:http://zzzzbw.cn/

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(一)--前言

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(二)--實(shí)現(xiàn)Bean容器

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(三)--實(shí)現(xiàn)IOC

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(六)--加強(qiáng)AOP功能

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(七)--實(shí)現(xiàn)MVC

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(八)--制作Starter

從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(九)--優(yōu)化MVC代碼

源碼地址:doodle

原文地址:從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(九)--優(yōu)化MVC代碼

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76715.html

相關(guān)文章

  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架

    摘要:不過(guò)仔細(xì)了解了一段時(shí)候發(fā)現(xiàn),其實(shí)他的原理是很簡(jiǎn)單的,所以想要自己也動(dòng)手實(shí)現(xiàn)一個(gè)功能類(lèi)似的框架。原文地址從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架 前言 最近在看spring-boot框架的源碼,看了源碼之后更是讓我感受到了spring-boot功能的強(qiáng)大。而且使用了很多的設(shè)計(jì)模式,讓人在看的時(shí)候覺(jué)得有點(diǎn)難以下手。 不過(guò)仔細(xì)了解了一段時(shí)候發(fā)現(xiàn),其實(shí)他的原理是很簡(jiǎn)單的,所以想要自己也動(dòng)手實(shí)現(xiàn)一個(gè)功能類(lèi)似的...

    neuSnail 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)

    摘要:接下來(lái)就可以把這個(gè)切點(diǎn)類(lèi)加入到我們之前實(shí)現(xiàn)的功能中了。實(shí)現(xiàn)的切點(diǎn)功能首先改裝注解,把之前改成來(lái)存儲(chǔ)表達(dá)式。測(cè)試用例在上一篇文章從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架四實(shí)現(xiàn)中的測(cè)試用例的基礎(chǔ)上修改測(cè)試用例。 前言 在上一節(jié)從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP中我們實(shí)現(xiàn)了AOP的功能,已經(jīng)可以生成對(duì)應(yīng)的代理類(lèi)了,但是對(duì)于代理對(duì)象的選擇只能通過(guò)指定的類(lèi),這樣確實(shí)不方便也不合理。...

    wupengyu 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(八)--制作Starter

    摘要:服務(wù)器相關(guān)配置啟動(dòng)類(lèi)資源目錄目錄靜態(tài)文件目錄端口號(hào)目錄目錄實(shí)現(xiàn)內(nèi)嵌服務(wù)器在上一章文章從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的框架七實(shí)現(xiàn)已經(jīng)在文件中引入了依賴(lài),所以這里就不用引用了。 spring-boot的Starter 一個(gè)項(xiàng)目總是要有一個(gè)啟動(dòng)的地方,當(dāng)項(xiàng)目部署在tomcat中的時(shí)候,經(jīng)常就會(huì)用tomcat的startup.sh(startup.bat)的啟動(dòng)腳本來(lái)啟動(dòng)web項(xiàng)目 而在spring-b...

    AprilJ 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(六)--加強(qiáng)AOP功能

    摘要:在前面的文章中實(shí)現(xiàn)的功能時(shí),目標(biāo)類(lèi)都只能被一個(gè)切面代理,如果想要生成第二個(gè)代理類(lèi),就會(huì)把之前的代理類(lèi)覆蓋。改裝原有功能現(xiàn)在要改裝原來(lái)的的實(shí)現(xiàn)代碼,讓的功能加入到框架中為了讓切面能夠排序,先添加一個(gè)注解,用于標(biāo)記排序。 前言 在前面從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(四)--實(shí)現(xiàn)AOP和從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易的Java MVC框架(五)--引入aspectj實(shí)現(xiàn)AOP切點(diǎn)這兩節(jié)文章...

    Loong_T 評(píng)論0 收藏0
  • 從零開(kāi)始實(shí)現(xiàn)一個(gè)簡(jiǎn)易Java MVC框架(二)--實(shí)現(xiàn)Bean容器

    摘要:容器實(shí)際上就是存放所有的地方,即以及相關(guān)信息對(duì)應(yīng)其實(shí)體的容器,為什么稱(chēng)之為呢,因?yàn)樵谥?,定義信息和實(shí)例的東西叫。了解到這個(gè)以后接下來(lái)就可以開(kāi)始編寫(xiě)容器了,在包下創(chuàng)建一個(gè)類(lèi)叫。獲取容器實(shí)例至此,這個(gè)容器就完成了。 項(xiàng)目準(zhǔn)備 首先確保你擁有以下環(huán)境或者工具 idea java 8 maven 3.3.X lombok插件 然后我們創(chuàng)建一個(gè)maven工程,編寫(xiě)pom.xml引入一些需要的...

    paulquei 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<