zoukankan      html  css  js  c++  java
  • springMvc框架实现

    一 springMvc核心功能

    springMvc是基于分层MVC设计模式的spring实现,他的核心功能是:

    1 url跳转

    2 ioc

    3 aop(本次暂不实现)

    二springMvc工作流程图

    三 接下来,让我们写代码实现springMvc框架

    通过注解方式实现了跳转和ioc两个核心功能,工程结构如下:

    分别创建注解@Controller

    package com.hongsen.annotation;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Controller {
        String value();
    }
    

     创建@RequestMapping注解

    package com.hongsen.annotation;
    
    @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RequestMapping {
        String value();
    }
    

     创建@resource注解

    package com.hongsen.annotation;
    
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Resource {
        String value();
    }
    

     创建@Service注解

    package com.hongsen.annotation;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Service {
        String value();
    }
    

    创建servlet,代码如下:

    package com.hongsen.servlet;
    
    /**
     * springMvc 作用
     * <p>
     * 1 跳转
     * 2 ioc
     * 3 aop
     *
     * @author wanghongsen 2018.07.27
     */
    
    public class DispatcherServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
        private List<String> classList = new ArrayList<>();
        private Map<String, Object> beanInstanceMap = new HashMap<>();
        private Map<String, Method> urlHandlerMap = new HashMap<>();
    
        /**
         * servlet初始化方法
         * 1 scan扫描包路径
         * 2 构造所有类集合 (list<String>)
         * 3 构造所有bean实例集合 (beanName-> bean)
         * 4 构造所有请求handler跳转(uri -> method)
         */
        public void init() throws ServletException {
            System.out.println("init() start");
            String scanBasePath = "com.hongsen";
            scan(scanBasePath);
            initBeanInstance();
            ioc();
            initUrlHandlerMap();
        }
    
        private void scan(String scanBasePath) {
            URL url = this.getClass().getResource("/" + scanBasePath.replace(".", "/"));
            String baseFilePath = url.getFile();
            File baseFile = new File(baseFilePath);
            String[] subFilePaths = baseFile.list();
            for (String subFilePath : subFilePaths != null ? subFilePaths : new String[0]) {
                File subFile = new File(baseFilePath + subFilePath);
                if (subFile.isDirectory()) {
                    scan(scanBasePath + "." + subFilePath);
                } else {
                    classList.add(scanBasePath + "." + subFilePath);
                }
            }
        }
    private void initBeanInstance() { for (String beanName : classList) { try { beanName = beanName.replace(".class", ""); Class beanClass = Class.forName(beanName); try { if (beanClass.isAnnotationPresent(Controller.class)) { Controller controller = (Controller) beanClass.getAnnotation(Controller.class); beanInstanceMap.put(controller.value(), beanClass.newInstance()); } else if (beanClass.isAnnotationPresent(Service.class)) { Service service = (Service) beanClass.getAnnotation(Service.class); beanInstanceMap.put(service.value(), beanClass.newInstance()); } } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } private void ioc() { for (String beanName : classList) { try { beanName = beanName.replace(".class", ""); Class beanClass = Class.forName(beanName); Field[] fields = beanClass.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Resource.class)) { Resource resource = field.getAnnotation(Resource.class); String val = resource.value(); try { field.setAccessible(true); Service service = (Service) beanClass.getAnnotation(Service.class); if (service != null) { field.set(beanInstanceMap.get(service.value()), beanInstanceMap.get(val)); } else { Controller controller = (Controller) beanClass.getAnnotation(Controller.class); if (controller != null) { field.set(beanInstanceMap.get(controller.value()), beanInstanceMap.get(val)); } } } catch (IllegalAccessException e) { e.printStackTrace(); } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } private void initUrlHandlerMap() { for (String beanName : classList) { try { beanName = beanName.replace(".class", ""); Class beanClass = Class.forName(beanName); if (beanClass.isAnnotationPresent(RequestMapping.class)) { RequestMapping baseReqMap = (RequestMapping) beanClass.getAnnotation(RequestMapping.class); if (baseReqMap != null) { String requestBaseUrl = baseReqMap.value(); Method[] methods = beanClass.getMethods(); for (Method method : methods) { RequestMapping reqMap = method.getAnnotation(RequestMapping.class); if (reqMap != null) { urlHandlerMap.put(requestBaseUrl + reqMap.value(), method); } } } } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws javax.servlet.ServletException, IOException { String uri = request.getRequestURI(); String contextPath = request.getContextPath(); String requestUrl = uri.replace(contextPath, ""); Method method = urlHandlerMap.get(requestUrl); if (method == null) { return; } Class beanClass = method.getDeclaringClass(); Controller controller = (Controller) beanClass.getAnnotation(Controller.class); Object bean = beanInstanceMap.get(controller.value()); try { Map<String, String[]> requestParameterMap = request.getParameterMap(); Object[] args = new Object[requestParameterMap.entrySet().size()]; int index = 0; for (Map.Entry entry : requestParameterMap.entrySet()) { args[index] = entry.getValue(); index++; } method.invoke(bean, args); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } }

    创建完servlet后web.xml自动生成相应代码

    <load-on-startup>加这个标签,tomcat启动时会自动加载指定的servlet  大于等于0时启动tomcat会加载 servlet的init()方法 数字越小代表加载的优先级越高

    <url-pattern>/这个标签是tomcat请求扫描路径,扫到后会调用servlet相应的doGet或doPost方法

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        <servlet>
            <servlet-name>DispatcherServlet</servlet-name>
            <servlet-class>com.hongsen.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    创建Controller类

    package com.hongsen.controller;
    
    @Controller("testController")
    @RequestMapping("/test")
    public class TestController {
    
        @Resource("testAddService")
        private TestAddServiceImpl testAddService;
    
        @Resource("testDelService")
        private TestDelServiceImpl testDelService;
    
        @RequestMapping("/add.json")
        public void testAdd() {
            testAddService.add();
        }
        @RequestMapping("/del.json")
        public void testDel(Object num1, Object num2) {
            testDelService.del(num1.toString(), num2.toString());
        }
    }
    

     创建service接口和实现类

    package com.hongsen.service;
    
    public interface TestAddService {
        void add(String num);
    }
    
    package com.hongsen.service;
    
    @Service("testAddService")
    public class TestAddServiceImpl implements TestAddService{
        @Override
        public void add(String num) {
            System.out.println("add方法执行!");
        }
    }
    

    部署tomcat启动成功后:

    访问:http://localhost:8080/test/add.json

  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/wanghongsen/p/9377651.html
Copyright © 2011-2022 走看看