" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring手寫簡化版MVC流程詳解

 更新時間:2022年11月11日 10:00:45   作者:lin000_0  
Spring MVC是Spring Framework的一部分,是基于Java實現(xiàn)MVC的輕量級Web框架。本文將通過簡單示例帶大家掌握SpringMVC簡化版手寫方法,感興趣的可以了解一下

spring是一個非常流行的技術框架,其中spring mvc組件在其中非常重要的地位,主要面要客戶端提供服務,我們今天來手寫一個簡化版的mvc,且包括ioc部分,主要利用servlet機制來實現(xiàn),類的關系如下:

準備注解類,類于spring的@Autowired、@Service、@Controller、@RequestMapping、@RequestParam

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CSAutowired {
    String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CSController {
    String value() default "";
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CSRequestMapping {
    String value() default "";
}
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CSRequestParam {
    String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CSService {
    String value() default "";
}

準備service interface

public interface IDemoService {
    public String get(String name);
}

準備service實現(xiàn)類,利用@CSService

@CSService
public class DemoService implements IDemoService {
    @Override
    public String get(String name) {
        return "My name is "+name;
    }
}

準備對外服務的類,主要利用@CSController注解

@CSController
@CSRequestMapping("/demo")
public class DemoAction {
    @CSAutowired
    private IDemoService demoService;
    @CSRequestMapping("/query")
    public void query(HttpServletRequest req, HttpServletResponse resp, @CSRequestParam("name") String name){
        String result=demoService.get(name);
        try {
            resp.getWriter().write(result);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
    @CSRequestMapping("/add")
    public void add(HttpServletRequest req, HttpServletResponse resp, @CSRequestParam("aa") Integer a,@CSRequestParam("b") Integer b){
        try {
            resp.getWriter().write(a+"+"+b+"="+(a+b));
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
    @CSRequestMapping("/remove")
    public void remove(HttpServletRequest req, HttpServletResponse resp, @CSRequestParam("id") Integer id){
        try {
            resp.getWriter().write("id="+id);
        } catch (IOException exception) {
            exception.printStackTrace();
        }
    }
}

準備servlet

主要實現(xiàn)了以下功能:

1).根據(jù)@CSController對外服務的url如何mapping到具體方法 doHandlerMap

2).service和controller bean的管理 iocBeans

3).如何實列化bean doInstance

4).如何獲取url中參數(shù)值 doDispatch中

5).找到需要加載的class doScanner

6).如何自動autowired doAutoWried

public class CSDispatchServlet extends HttpServlet {
    public static String urlPattern="/custom";
    private void doDispatch(HttpServletRequest request,HttpServletResponse response) throws Exception{
        String url=request.getRequestURI();
        String contextPath=request.getContextPath();
        url=url.replace(urlPattern,"");
        if(!handlerMap.containsKey(url)){
            response.getWriter().write("404 not found!");
            return;
        }
        Method method=handlerMap.get(url);
        Annotation[][] methodParameterAnnotations= method.getParameterAnnotations();
        Parameter[]  methodParameters= method.getParameters();
        Annotation[][] paramerterAnnotations=method.getParameterAnnotations();
        ArrayList<Object> methodParameterValues=new  ArrayList<Object>();
        Map<String,String[]> requestParams= request.getParameterMap();
        int parmeterCnt=0;
        for(Parameter parameter:methodParameters){
            if(parameter.getType()==HttpServletRequest.class ){
                methodParameterValues.add(request);
            }else if(parameter.getType()==HttpServletResponse.class){
                methodParameterValues.add(response);
            }else {
               String methodParamName="";
               if(paramerterAnnotations[parmeterCnt].length>0) {
                       Annotation annotation= paramerterAnnotations[parmeterCnt][0];
                       if(annotation instanceof CSRequestParam) {
                           methodParamName = ((CSRequestParam) annotation).value();
                       }
               }
               if("".equals(methodParamName.trim())){
                   methodParamName=parameter.getName();
               }
                String value="";
               //String value=Arrays.toString(requestParams.get(methodParamName));
                if(requestParams.get(methodParamName).length>1)
                    value=Arrays.toString(requestParams.get(methodParamName));
                else if(requestParams.get(methodParamName).length==1)
                     value= requestParams.get(methodParamName)[0];
                else
                    value="999999";
               if(parameter.getType()==String.class)
                   methodParameterValues.add(value);
               else if(parameter.getType()==Integer.class) {
                   try {
                       methodParameterValues.add(Integer.parseInt(value));
                   } catch (Exception e){
                       methodParameterValues.add(99999999);
                   }
               }else {
                    //可以擴展復雜類型轉換
               }
            }
            parmeterCnt++;
        }
        String beanName=this.genBeanName(method.getDeclaringClass().getSimpleName());
        method.invoke(this.iocBeans.get(beanName), methodParameterValues.toArray());
    }
    private String genBeanName(String beanName){
        if(beanName.length()>1)
            beanName=beanName.substring(0,0).toLowerCase()+beanName.substring(1);
        else
            beanName=beanName.toLowerCase();
        return beanName;
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            this.doDispatch(req,resp);
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
    private ArrayList<String> classs=new ArrayList<String>();
    private ConcurrentHashMap<String,Object> iocBeans=new ConcurrentHashMap<String,Object>();
    private ConcurrentHashMap<String,Method> handlerMap=new ConcurrentHashMap<String,Method>();
    private void doInstance() {
        try {
            for (String className : classs) {
                if (!className.contains(".")) continue;
                Class<?> clazz = Class.forName(className);
                String beanName="";
                if (clazz.isAnnotationPresent(CSController.class)) {
                    CSController controller = clazz.getAnnotation(CSController.class);
                    beanName=controller.value();
                }else if(clazz.isAnnotationPresent(CSService.class)){
                    CSService service=clazz.getAnnotation(CSService.class);
                    beanName=service.value();
                }else {
                    continue;
                }
                Object instance=clazz.newInstance();
                if("".equals(beanName.trim()))
                    beanName=clazz.getSimpleName();            
                beanName=genBeanName(beanName);
                iocBeans.put(beanName,instance);
                if(clazz.isAnnotationPresent(CSService.class)){
                    for(Class  c:  clazz.getInterfaces()){
                        if(iocBeans.containsKey(c.getName())) continue;
                        iocBeans.put(c.getName(),instance);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private void doAutoWried(){
        for(Object o:iocBeans.values()){
            if(o==null) continue;
            Class clazz=o.getClass();
            if(clazz.isAnnotationPresent(CSService.class) || clazz.isAnnotationPresent(CSController.class)){
                Field[] fields=clazz.getDeclaredFields();
                for(Field f:fields){
                    if(!f.isAnnotationPresent(CSAutowired.class)) continue;
                    CSAutowired autowired=f.getAnnotation(CSAutowired.class);
                    String beanName=autowired.value();
                    if("".equals(beanName)) beanName=f.getType().getName();
                    f.setAccessible(true);
                    try{
                        Object o1=iocBeans.get(beanName);
                        f.set(o,iocBeans.get(beanName));
                    }catch (IllegalAccessException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    private void doHandlerMap(ServletConfig config){ 
        for(Object o:iocBeans.values()){
            if(!o.getClass().isAnnotationPresent(CSController.class)) continue;
            String baseUrl="";
            if(o.getClass().isAnnotationPresent(CSRequestMapping.class)){
                CSRequestMapping requestMapping=o.getClass().getAnnotation(CSRequestMapping.class);
                baseUrl=requestMapping.value();
            }
            for(Method method: o.getClass().getMethods()){
                if(method.isAnnotationPresent(CSRequestMapping.class)) {
                    CSRequestMapping requestMapping=method.getAnnotation(CSRequestMapping.class);
                    String url=baseUrl+requestMapping.value().replaceAll("/+","/");
                    String contextPath=config.getServletContext().getContextPath();
                    this.handlerMap.put(url,method);
                }
            }
        }
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        InputStream is=null;
        try{
            System.out.println("custom servlet init........");
            /*
            Properties configContext=new Properties();
            is=this.getClass().getClassLoader().getResourceAsStream(config.getInitParameter("contextConfigLocation"));
            configContext.load(is);
            String scanPackage=configContext.getProperty("scanPackage");
            */
            Enumeration<String> enumerations= config.getInitParameterNames();
            while (enumerations.hasMoreElements()){
                System.out.println(enumerations.nextElement());
            }
            doScanner("com.mesui.spring.custom");
            doInstance();
            doAutoWried();
            doHandlerMap( config);
        }catch (Exception exception){
            exception.printStackTrace();
        }finally {
        }
    }
    private void doScanner(String scanPackage){
        URL url= this.getClass().getClassLoader().getResource("") ;
        String filePath="";
        try {
              filePath= URLDecoder.decode( url.getPath(),"UTF-8")+"/"+scanPackage.replaceAll("\\.","/");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        File classDir=new File(filePath);
        for(File file:classDir.listFiles()){
            if(file.isDirectory()){
                doScanner(scanPackage+"."+file.getName());
            }else if(!file.getName().endsWith(".class")) {
                continue;
            }
            if(!file.isDirectory()) {
                String clzzName = (scanPackage + "." + file.getName().replace(".class", ""));
                //map.put(clzzName,null);
                classs.add(clzzName);
            }
        }
    }
}

在利用spring的configuration類初始化servlet

這邊為了方便進行偷懶,這樣/custom/下的服務按照自已邏輯對對外服務,不按照spring mvc的進行,另外自已可以tomcat的web.xml中標記servlet完全脫離spring

    @Configuration
public class MybatisPlusConfig {
    @Bean
    public ServletRegistrationBean CustomServlet(){
        return new ServletRegistrationBean(new CSDispatchServlet(),CSDispatchServlet.urlPattern+"/*");
    }
}

測試

結論

從上面的例子中我們可以看到自已寫一個mvc也很方便,不是什么難事,但是這個只是用于學習,畢竟spring是一個體系,我們自已不可能將所有內容重新寫一遍,但是自已寫著玩有助于對spring mvc和IOC的理解。

到此這篇關于Spring手寫簡化版mvc流程詳解的文章就介紹到這了,更多相關Spring mvc內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java下Struts框架中的ActionForm類詳解

    Java下Struts框架中的ActionForm類詳解

    這篇文章主要介紹了Java下Struts框架中的ActionForm類詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • java基于jdbc連接mysql數(shù)據(jù)庫功能實例詳解

    java基于jdbc連接mysql數(shù)據(jù)庫功能實例詳解

    這篇文章主要介紹了java基于jdbc連接mysql數(shù)據(jù)庫功能,結合實例形式詳細分析了jdbc連接mysql數(shù)據(jù)庫的原理、步驟、實現(xiàn)方法及相關操作技巧,需要的朋友可以參考下
    2017-10-10
  • SpringBoot服務端數(shù)據(jù)校驗過程詳解

    SpringBoot服務端數(shù)據(jù)校驗過程詳解

    這篇文章主要介紹了SpringBoot服務端數(shù)據(jù)校驗過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-02-02
  • 解決@PathVariable參數(shù)接收不完整的問題

    解決@PathVariable參數(shù)接收不完整的問題

    這篇文章主要介紹了解決@PathVariable參數(shù)接收不完整的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中Shiro安全框架的權限管理

    Java中Shiro安全框架的權限管理

    這篇文章主要介紹了Java中Shiro安全框架的權限管理,Apache?Shiro是Java的一個安全框架,Shiro可以非常容易的開發(fā)出足夠好的應用,其不僅可以用在JavaSE環(huán)境,也可以用在JavaEE環(huán)境,需要的朋友可以參考下
    2023-08-08
  • Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導入數(shù)據(jù)庫

    Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導入數(shù)據(jù)庫

    在開發(fā)中,我們經(jīng)常會遇到這樣的需求,將Excel的數(shù)據(jù)導入數(shù)據(jù)庫中,這篇文章主要來和大家講講Java如何使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導入數(shù)據(jù)庫,感興趣的可以了解下
    2024-01-01
  • 詳解Java中HashSet和TreeSet的區(qū)別

    詳解Java中HashSet和TreeSet的區(qū)別

    這篇文章主要介紹了詳解Java中HashSet和TreeSet的區(qū)別的相關資料,需要的朋友可以參考下
    2017-06-06
  • springboot項目啟動自動跳轉到瀏覽器的操作代碼

    springboot項目啟動自動跳轉到瀏覽器的操作代碼

    這篇文章主要介紹了springboot項目啟動自動跳轉到瀏覽器的操作代碼,本文圖文實例代碼相結合給大家介紹的非常詳細,需要的朋友可以參考下
    2024-03-03
  • java開發(fā)分布式服務框架Dubbo調用過程

    java開發(fā)分布式服務框架Dubbo調用過程

    這篇文章主要為大家介紹了java開發(fā)分布式服務框架Dubbo調用過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2021-11-11
  • Eclipse配置maven環(huán)境的圖文教程

    Eclipse配置maven環(huán)境的圖文教程

    下面小編就為大家?guī)硪黄狤clipse配置maven環(huán)境的圖文教程。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11

最新評論