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

  • 相关阅读:
    Redhat7.x静默安装19C客户端
    利用增量备份修复DG备库中的gap>>>>>>>>>>>有新增数据文件
    利用增量备份修复DG备库中的gap>>>>>>>>>>>无新增数据文件
    ORA-01665 control file is not a standby control file
    ORA-01110 ORA-01122 ORA-01110 ORA-01200解决办法
    Zabbix5.0+Grafana可视化部署教程
    RedHat 7.5配置bonding双网卡绑定(转)
    11.2.0.1 RAC环境部分磁盘组无法自动挂载,导致数据库实例无法启动(转)
    11.2.0.1 RAC环境经典bug CRS-4124: Oracle High Availability Services startup failed.
    Git配置SSH及常用命令
  • 原文地址:https://www.cnblogs.com/zhendiao/p/14897803.html
Copyright © 2011-2022 走看看