• 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

  • 相关阅读:
    HDU1196 ZOJ2417 Lowest Bit
    HDU1008 ZOJ2108 Elevator
    HDU2614 Beat
    HDU2057 A + B Again
    POJ3984 迷宫问题
    HDU1013 POJ1519 Digital Roots
    HDU2051 Bitset
    HDU2037 今年暑假不AC
    ACM入门练习与递推小结
    HDU2046 骨牌铺方格【递推】
  • 原文地址:https://www.cnblogs.com/wanghongsen/p/9377651.html
Copyright © 2020-2023  润新知