亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

手寫一個(gè)SpringMVC

ernest.wang / 2665人閱讀

摘要:網(wǎng)上很多關(guān)于的分析,但很少有手動(dòng)實(shí)現(xiàn)的,這里通過(guò)一個(gè)簡(jiǎn)單的實(shí)現(xiàn)基本功能,僅供學(xué)習(xí)參考。下面編寫一個(gè)和測(cè)試下代碼如下代碼如下請(qǐng)求學(xué)習(xí)交流,歡迎加群

網(wǎng)上很多關(guān)于springmvc的分析,但很少有手動(dòng)實(shí)現(xiàn)的,這里通過(guò)一個(gè)簡(jiǎn)單的demo實(shí)現(xiàn)mvc基本功能,僅供學(xué)習(xí)參考。

我們先簡(jiǎn)單了解下springmvc請(qǐng)求流程,如下圖:

從圖上得知,最先處理請(qǐng)求的是dispatcherServlet,它接受請(qǐng)求并查詢得到攔截器鏈HandlerExecutionChain,HandlerAdapter經(jīng)過(guò)適配器調(diào)用具體的處理器(Controller).

查看源碼可以到spring-webmvc.jar中,org.springframework.web.servlet/DispatcherServlet.class,其中方法doDispatch()完成了一個(gè)請(qǐng)求到返回?cái)?shù)據(jù)的完整操作.

下面我們開(kāi)始動(dòng)手了,先創(chuàng)建一個(gè)javaweb工程,寫一個(gè)Servlet,如下:

@WebServlet(urlPatterns = "/*", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {

    private List clzList = new ArrayList<>();
    private Map beansMap = new HashMap<>();
    private Map urlMapping = new HashMap<>();

    @Override
    public void init() throws ServletException {
        try {
            //掃描配置  這里是包名
            scanPackages("com.iti.smvc");
            //實(shí)例化對(duì)象
            doInstance();
            //建立對(duì)象之間的依賴ioc
            ioc();
            //建立url到controller的映射
            doMapping();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注:servlet3.0不再需要web.xml, 這里將成員變量寫入servlet并不是很好的實(shí)現(xiàn),會(huì)導(dǎo)致線程不安全
這個(gè)servlet要做一些初始化的工作,如:
1.掃描包名,將class對(duì)象裝入clzList列表
2.遍歷clzList列表,實(shí)例化有Controller和Service標(biāo)注的類
3.依賴注入,將service注入到controller
4.建立url與controller中方法url的mapping關(guān)系

我們依次來(lái)實(shí)現(xiàn)他們:
下面的是掃描配置方法

private void scanPackages(String packageUrl) {
        String fileUrl = getClass().getClassLoader().getResource("/"+packageUrl.replaceAll(".", "/")).getFile();
        File scanfile = new File(fileUrl);
        String[] fileList = scanfile.list();
        for (String fileName: fileList) {
            File file = new File(fileUrl+fileName);
            if (file.isDirectory()) {
                scanPackages(packageUrl + "." + fileName);;
            } else {
                clzList.add(packageUrl + "." + fileName.replace(".class", ""));
            }
        }
    }

接著是對(duì)象實(shí)例化:

private void doInstance() throws Exception{
        if (clzList.size()>0) {
            for (String clzName : clzList) {
                Class clzClass = Class.forName(clzName);
                if (clzClass.isAnnotationPresent(Controller.class)) {
                    //for controller
                    RequestMapping rm = clzClass.getAnnotation(RequestMapping.class);
                    beansMap.put(rm.value(), clzClass.newInstance());
                } else if (clzClass.isAnnotationPresent(Service.class)) {
                    Service service = clzClass.getAnnotation(Service.class);
                    beansMap.put(service.value(), clzClass.newInstance());
                }
            }
        }
    }

接著是依賴注入,其實(shí)是反射:

private void ioc() throws Exception{
        if (beansMap.size()>0) {
            for (Map.Entry entry : beansMap.entrySet()) {
                Field[] fields = entry.getValue().getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(Autowired.class)) {
                        Qualifier anno = field.getAnnotation(Qualifier.class);
                        field.set(entry.getValue(), beansMap.get(anno.value()));
                    }
                }
            }
        }
    }

最后是建立請(qǐng)求url與controller的mapping關(guān)系,如下:

private void doMapping() {
        if (beansMap.size()>0) {
            for (Map.Entry entry: beansMap.entrySet()) {
                Class obj = entry.getValue().getClass();
                if (obj.isAnnotationPresent(Controller.class)){
                    RequestMapping rm = obj.getAnnotation(RequestMapping.class);
                    Method[] methods = obj.getMethods();
                    for (Method method: methods) {
                        if (method.isAnnotationPresent(RequestMapping.class)) {
                            RequestMapping anno = method.getAnnotation(RequestMapping.class);
                            urlMapping.put(rm.value() + anno.value(), method);
                        }
                    }
                }
            }
        }
    }

還要把注解創(chuàng)建下:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
    String value() default "";
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Qualifier {
    String value() default "";
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
    String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
    String value() default "";
}

此時(shí)就可以啟動(dòng)服務(wù)完成初始化工作了
下面我們要?jiǎng)?chuàng)建一個(gè)sevice方法來(lái)接收url請(qǐng)求

@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI(); 
        String contextPath = req.getContextPath(); 
        //得到請(qǐng)求地址
        String path = requestURI.replace(contextPath, "");
        Method method = (Method)urlMapping.get(path);
        if (method != null) {
            try {
                Object obj = method.invoke(beansMap.get("/"+path.split("/")[1]));
                resp.getOutputStream().write(obj.toString().getBytes());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

上面是得到請(qǐng)求url,然后從urlMapping得到要調(diào)用的method,再通過(guò)反射調(diào)用,最后通過(guò)outputStream輸出到瀏覽器上。

下面編寫一個(gè)controller和service測(cè)試下
controller代碼如下:

@Controller
@RequestMapping("/hello")
public class HelloController {
    @Autowired
    @Qualifier("helloservice")
    Helloservice helloservice;

    @RequestMapping("/sayHello")
    public String sayHello() {
        //System.out.println(helloservice.hello());
        return "controller";
    }
}

service代碼如下:

@Service("helloservice")
public class Helloservice {
    public String hello() {
        return "hello";
    }
}

請(qǐng)求url:http://localhost:8080/hello/sayHello
學(xué)習(xí)交流,歡迎加群:64691032

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

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

相關(guān)文章

  • 我對(duì) SpringMVC 的一些誤解

    摘要:引言剛考完期末,再也不用考試?yán)沧罱鼘W(xué)習(xí)了慕課網(wǎng)的實(shí)戰(zhàn)課手寫,劍指開(kāi)源框架靈魂。最近將本課程和看透結(jié)合起來(lái)學(xué)習(xí),感覺(jué)受益匪淺,同時(shí),糾正了我之前對(duì)的一些誤解。誤解洪荒時(shí)代的當(dāng)年,開(kāi)發(fā)都需要手動(dòng)去實(shí)現(xiàn)。為了解決太多的問(wèn)題,引入了,進(jìn)行統(tǒng)一調(diào)度。 引言 剛考完期末,再也不用考試?yán)玻。。?最近學(xué)習(xí)了慕課網(wǎng)的實(shí)戰(zhàn)課《手寫SpringMVC,劍指開(kāi)源框架靈魂》。 showImg(https://s...

    seanlook 評(píng)論0 收藏0
  • SpringMVC入門就這么簡(jiǎn)單

    摘要:也就是說(shuō)映射器就是用于處理什么樣的請(qǐng)求提交給處理。這和是一樣的提交參數(shù)的用戶名編號(hào)提交配置處理請(qǐng)求注冊(cè)映射器包框架接收參數(shù)設(shè)置無(wú)參構(gòu)造器,里邊調(diào)用方法,傳入要封裝的對(duì)象這里的對(duì)象就表示已經(jīng)封裝好的了對(duì)象了。 什么是SpringMVC? SpringMVC是Spring家族的一員,Spring是將現(xiàn)在開(kāi)發(fā)中流行的組件進(jìn)行組合而成的一個(gè)框架!它用在基于MVC的表現(xiàn)層開(kāi)發(fā),類似于struts...

    SKYZACK 評(píng)論0 收藏0
  • SpringMVC【校驗(yàn)器、統(tǒng)一處理異常、RESTful、攔截器】

    摘要:只要有一個(gè)攔截器不放行,不能執(zhí)行完成號(hào)不放行和號(hào)不放行測(cè)試結(jié)果總結(jié)只有前邊的攔截器方法放行,下邊的攔截器的才執(zhí)行。至于他們的攔截器鏈的調(diào)用順序,和的是沒(méi)有差別的。 前言 本博文主要講解的知識(shí)點(diǎn)如下: 校驗(yàn)器 統(tǒng)一處理異常 RESTful 攔截器 Validation 在我們的Struts2中,我們是繼承ActionSupport來(lái)實(shí)現(xiàn)校驗(yàn)的...它有兩種方式來(lái)實(shí)現(xiàn)校驗(yàn)的功能 手寫...

    marser 評(píng)論0 收藏0
  • Spring+SpringMVC+Maven+Mybatis+MySQL+Jetty項(xiàng)目搭建(1)

    摘要:接口聲明并實(shí)現(xiàn)接口聲明一個(gè)接口新建一個(gè)類,并實(shí)現(xiàn)接口單元測(cè)試單元測(cè)試是為了驗(yàn)證第步中接口的方法。中新增類使用實(shí)現(xiàn)單元測(cè)試指定注入的配置文件使用標(biāo)準(zhǔn)的注釋來(lái)告訴使用在中新增類文件運(yùn)行單元測(cè)試右鍵運(yùn)行結(jié)果到此,我們已經(jīng)搭建了一個(gè)基于的項(xiàng)目環(huán)境。 本文詳細(xì)講述如何搭建一個(gè)Spring+SpringMVC+Maven+Mybatis+MySQL項(xiàng)目環(huán)境。eclipse、maven 及 mysq...

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

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

0條評(píng)論

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