zoukankan      html  css  js  c++  java
  • 简单实现springmvc中的请求处理

    自定义MVC框架中的一些元素

    一些注解

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

    处理对象封装

    public class Handler {
    
        private Object controller;//Controller对应的类
        private Method method;//执行业务的方法
        private Pattern pattern;//uri
        private Map<String,Integer> paramIndexMapping;//参数和位置的映射
    
        public Handler(Object controller, Method method, Pattern pattern) {
            this.controller = controller;
            this.method = method;
            this.pattern = pattern;
            this.paramIndexMapping = new HashMap<>();
        }
    
        public Object getController() {
            return controller;
        }
    
        public void setController(Object controller) {
            this.controller = controller;
        }
    
        public Method getMethod() {
            return method;
        }
    
        public void setMethod(Method method) {
            this.method = method;
        }
    
        public Pattern getPattern() {
            return pattern;
        }
    
        public void setPattern(Pattern pattern) {
            this.pattern = pattern;
        }
    
        public Map<String, Integer> getParamIndexMapping() {
            return paramIndexMapping;
        }
    
        public void setParamIndexMapping(Map<String, Integer> paramIndexMapping) {
            this.paramIndexMapping = paramIndexMapping;
        }
    }
    

    自定义DisptchServelet处理代码

    public class DispatchServelet extends HttpServlet {
        private Properties properties = new Properties();
        private List<String> classNames = new ArrayList<>();
        private Map<String,Object> ioc =new HashMap<>();
        private List<Handler> handlerMapping = new ArrayList<>();
        @Override
        public void init(ServletConfig config) throws ServletException {
            //加载配置文件
            String contextConfigLocation = config.getInitParameter("contextConfigLocation");
            doLoadConfig(contextConfigLocation);
            //扫描相关的类,扫描注解
            doScan(properties.getProperty("scanPackage"));
            //初始化bean,基于注解
            doInstance();
            //实现依赖注入
            doAutoWired();
            //实现处理器映射器,将url和method进行关联
            initHandlerMapping();
            System.out.println("mvc 初始化完成");
            
        }
        //执行的是方法和url方法映射
        private void initHandlerMapping() {
            if (ioc.isEmpty()){
                return;
            }
            for (Map.Entry<String,Object> entry :ioc.entrySet()){
                Class<?> aClass = entry.getValue().getClass();
                if (!aClass.isAnnotationPresent(Controller.class)){
                    continue;
                }
                String baseUrl = "";
                if (aClass.isAnnotationPresent(RequestMapping.class)){
                    RequestMapping requestMapping = aClass.getAnnotation(RequestMapping.class);
                    baseUrl=requestMapping.value();
                }
                Method[] methods= aClass.getMethods();
                for (int i=0;i<methods.length;i++){
                    Method method = methods[i];
                    if (!method.isAnnotationPresent(RequestMapping.class)){
                        continue;
                    }
                    RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                    String methodUrl = requestMapping.value();
                    String url = baseUrl+methodUrl;
                    Handler handler = new Handler(entry.getValue(),method, Pattern.compile(url));
                    Parameter[] parameters = method.getParameters();
                    for (int j=0;j<parameters.length;j++){
                        Parameter parameter = parameters[j];
                        if (parameter.getType().equals(HttpServletRequest.class)||parameter.getType().equals(HttpServletResponse.class)){
                            handler.getParamIndexMapping().put(parameter.getType().getSimpleName(),j);
                        }else {
                            handler.getParamIndexMapping().put(parameter.getName(),j);
                        }
                    }
                    //完成方法和url的映射关系
                    handlerMapping.add(handler);
                }
            }
        }
        //执行注入部分,同样是做的ioc的部分功能
        private void doAutoWired() {
            if (ioc.isEmpty()){
                return;
            }
            for (Map.Entry<String,Object> entry :ioc.entrySet()){
                Field[] declareFields = entry.getValue().getClass().getDeclaredFields();
                for (int i=0;i<declareFields.length;i++){
                    Field declareField = declareFields[i];
                    if (!declareField.isAnnotationPresent(Autowired.class)){
                        continue;
                    }
                    Autowired autowired = declareField.getAnnotation(Autowired.class);
                    String beanName = autowired.value();
                    if ("".equals(beanName.trim())){
                        beanName=declareField.getType().getName();
                    }
                    declareField.setAccessible(true);
                    try {
                        //直接将这个字段的值设置为ioc中已经示例化的类,
                        // 即是完成了ioc中的实例化交给容器来管理的情况
                        declareField.set(entry.getValue(),ioc.get(beanName));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
    
            }
        }
    
        //执行的是符合要求的类的初始化,实际上是实现的一部分ioc的功能
        private void doInstance()  {
            if (classNames.size()==0){
                return;
            }
            try {
                for (int i=0;i<classNames.size();i++){
                    String className = classNames.get(i);
                    Class<?> clazz = Class.forName(className);
                    if (clazz.isAnnotationPresent(Controller.class)){
                        String simpleName = clazz.getSimpleName();
                        String lowerFirst = lowerFirst(simpleName);
                        Object o = clazz.newInstance();
                        //因为controller无别名,所以简单设置成首字母小写就行
                        ioc.put(lowerFirst,o);
                    }else if (clazz.isAnnotationPresent(Service.class)){
                        Service service = clazz.getAnnotation(Service.class);
                        String beanName =service.value();
                        if (!"".equals(beanName.trim())){
                            ioc.put(beanName,clazz.newInstance());
                        }else {
                            beanName = lowerFirst(clazz.getSimpleName());
                            ioc.put(beanName,clazz.newInstance());
                        }
    
                        Class<?>[] interfaces = clazz.getInterfaces();
                        for (int j=0;j<interfaces.length;j++){
                            Class<?> ainterface = interfaces[j];
                            System.out.println(ainterface.getName());
                            //将实现类和接口进行绑定
                            ioc.put(ainterface.getName(),clazz.newInstance());
                        }
                    }else {
                        continue;
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    
    
        private  String lowerFirst(String className){
           char[] chars = className.toCharArray();
           if ('A'<chars[0]&&chars[0]<'Z'){
               chars[0]+=32;
           }
           return new String(chars);
        }
        private void doScan(String basePackage) {
            //获取到指定包下的所有类的类名
            String scanPackagePath= Thread.currentThread().getContextClassLoader().getResource("").getPath()+basePackage.replaceAll("\.","/");
            File pack = new File(scanPackagePath);
            File [] files = pack.listFiles();
            for (File file:files){
                if (file.isDirectory()){
                    doScan(basePackage+"."+file.getName());
                }else if (file.getName().endsWith(".class")){
                    String className = basePackage+"."+file.getName().replaceAll(".class","");
                    classNames.add(className);
                }
            }
        }
        //实现加载web.xml中配置的文件的路径
        private void doLoadConfig(String contextConfigLocation) {
            InputStream inputStream =this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
            try {
                properties.load(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req,resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Handler handler = getHander(req);
            if (handler==null){
                resp.getWriter().write("404 not found");
                return;
            }
            Class<?> [] parameterTypes = handler.getMethod().getParameterTypes();
            Object[] paraValues = new Object[parameterTypes.length];
    
            Map<String,String[]> parameterMap = req.getParameterMap();
            for (Map.Entry<String,String[]> param:parameterMap.entrySet()){
                String value = StringUtils.join(param.getValue(),",");
                if (!handler.getParamIndexMapping().containsKey(param.getKey())){
                    continue;
                }
                //对应实际参数的位置
                Integer index = handler.getParamIndexMapping().get(param.getKey());
                paraValues[index]=value;
    
            }
            //对应上req,和resp参数的位置
            int reqIndex = handler.getParamIndexMapping().get(HttpServletRequest.class.getSimpleName());
            paraValues[reqIndex]=req;
            int respIndex = handler.getParamIndexMapping().get(HttpServletResponse.class.getSimpleName());
            paraValues[respIndex]=resp;
    
            try {
                //实际执行的是controller中的方法
                handler.getMethod().invoke(handler.getController(),paraValues);
                System.out.println("执行controller方法成功");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    
        }
    
        private Handler getHander(HttpServletRequest req) {
            if (handlerMapping.isEmpty()){
                return null;
            }
            String url =req.getRequestURI();
            for (Handler handler:handlerMapping){
                Matcher matcher = handler.getPattern().matcher(url);
                if (!matcher.matches()){
                    continue;
                }
                return handler;
            }
            return null;
        }
    
    }
    

    测试代码

    public interface DemoService {
    
        String getName(String name);
    }
    
    
    
    @Service("demoService")
    public class DemoServiceImpl implements DemoService {
        @Override
        public String getName(String name) {
            return name;
        }
    }
    
    @Controller
    @RequestMapping("/demo")
    public class DemoController {
        @Autowired
        private DemoService demoService;
        @RequestMapping("/query")
        public String query(HttpServletRequest req, HttpServletResponse resp,String name){
            return demoService.getName(name);
        }
    }
    

    web.xml配置

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>com.zhao.mvcframework.servelet.DispatchServelet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>mvc.properties</param-value>
        </init-param>
      </servlet>
      <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/*</url-pattern>
      </servlet-mapping>
    </web-app>
    

    mvc.properties的配置

    scanPackage=com.zhao.mvcdemo
    

    pom文件的配置

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.zhao</groupId>
      <artifactId>mvc</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>mvc Maven Webapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
          <version>3.10</version>
        </dependency>
      </dependencies>
    
      <build>
          <plugins>
            <plugin>
              <groupId>org.apache.tomcat.maven</groupId>
              <artifactId>tomcat7-maven-plugin</artifactId>
              <version>2.2</version>
              <configuration>
                <port>8080</port>
                <path>/</path>
              </configuration>
    
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                  <source>1.8</source>
                  <target>1.8</target>
                  <encoding>utf-8</encoding>
                  <compilerArgs>-parameters</compilerArgs>
                </configuration>
            </plugin>
          </plugins>
      </build>
    </project>
    

    测试时访问具体的http://localhost:8080/demo/query?name=zhaozhen 无问题
    file
    代码地址为https://github.com/zhendiao/deme-code/tree/main/mvc

  • 相关阅读:
    165. Compare Version Numbers
    164. Maximum Gap
    3、桶排序
    162. Find Peak Element
    160. Intersection of Two Linked Lists
    155. Min Stack
    154. Find Minimum in Rotated Sorted Array II
    153. Find Minimum in Rotated Sorted Array
    Linux/Unix系统编程手册 第二章:基本概念
    Linux/Unix系统编程手册 第一章:历史和标准
  • 原文地址:https://www.cnblogs.com/zhendiao/p/14897803.html
Copyright © 2011-2022 走看看