IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> SpringMVC框架 -> 正文阅读

[PHP知识库]SpringMVC框架

思路:

  1. 在项目部署的时候,就马上启动扫描的工作了。

    a. 把扫描的工作提前放到servlet的init方法去做: init --- service - destroy

    b. 让这个init方法调用的时机再提前一些,提前到项目发布的时候就执行。

    c. 设置 <load-on-startup> 1</load-on-startup>

  2. DispatcherServlet注册的时候,不要使用注解来注册了,而是使用xml来注册, 在xml里面注册的时候,就可以配置servlet的初始化参数,用户指定扫描具体那个包。 <init-param>

  3. 扫描得到包下的所有类了之后,不是每一个类我们都要查看它的所有方法有没有requestMapping这个注解

    1. 只看类上有没有一个注解@Controller , 这个注解是自定义的注解。

    2. 谁身上有这个注解,我们就解析这个类里面的所有方法。

  4. 在init方法里面完成扫描的工作之后,需要使用一个Map集合来进行映射关系,也就是完成扫描工作之后,使用一个map集合来包装 映射的地址和controller的对象。 map集合里面就包装了请求地址和调用方法的一个关系。 KEY : 请求地址 , value : 包装的javaBean。

    class MethodBean{

    private Method method; //具体的方法对象

    private Object obj; //调用这个方法要用的实例对象

    }

    Map<String , MethodBean> map ;

    MethodBean mb = new MethodBean(方法对象 , 类的实例对象);

    map.put("/user/register" , mb);

  5. 在请求来的时候,在service里面获取请求的地址

  6. 截获请求的地址了之后,就可以直接问map要方法来调用。

    MethodBean mb = map.get("/user/register");

    Method m = mb.getMethod();

    m.invoke(mb.getObj() , req , resp);

  7. 在用户请求到来之前执行扫描包的操作

//工具类

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * @Description:扫描包下的类
 * @Author: yp
 */
public class ClassScannerUtils {

    /**
     * 获得包下面的所有的class
     * @param
     * @return List包含所有class的实例
     */
    public static List<Class<?>> getClasssFromPackage(String packageName) {
        List clazzs = new ArrayList<>();
        // 是否循环搜索子包
        boolean recursive = true;
        // 包名对应的路径名称
        String packageDirName = packageName.replace('.', '/');
        Enumeration<URL> dirs;

        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            while (dirs.hasMoreElements()) {

                URL url = dirs.nextElement();
                String protocol = url.getProtocol();
                if ("file".equals(protocol)) {
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    findClassInPackageByFile(packageName, filePath, recursive, clazzs);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return clazzs;
    }

    /**
     * 在package对应的路径下找到所有的class
     */
    public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive,
                                                List<Class<?>> clazzs) {
        File dir = new File(filePath);
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 在给定的目录下找到所有的文件,并且进行条件过滤
        File[] dirFiles = dir.listFiles(new FileFilter() {

            public boolean accept(File file) {
                boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
                boolean acceptClass = file.getName().endsWith("class");// 接受class文件
                return acceptDir || acceptClass;
            }
        });

        for (File file : dirFiles) {
            if (file.isDirectory()) {
                findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
            } else {
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
//servlet包


import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DispatcherServlet extends HttpServlet {
    Map<String, MethodBean> map = new HashMap<>();

    @Override
    public void init(ServletConfig config) throws ServletException {
        try {
            //在用户请求到来之前便执行初始化扫描包的操作
            //获取需要初始化的包名
            String packageName = config.getInitParameter("packageName");

            //扫描得到的包下面的所以字节码
            //得到有个list集合,也就是包下所有类的集合
            List<Class<?>> classList = ClassScannerUtils.getClasssFromPackage(packageName);

            //遍历得到的集合
            for (Class<?> clazz : classList) {
                //判断这个集合里面的类是否有注解Controller
                if (clazz.isAnnotationPresent(Controller.class)) {
                    //有这个注解,那就获取这个注解下面的类中的所有方法得到一个方法数组
                    Method[] methods = clazz.getMethods();

                    //变量得到的方法数组,每遍历一次,获取方法上面的注解ResqustMapping
                    for (Method method : methods) {
                        ResqustMapping annotation = method.getAnnotation(ResqustMapping.class);

                        //判断这些方法上面的注解ResqustMapping是否为空
                        //不为空的话就获取注解中的值
                        if (annotation != null) {
                            String value = annotation.value();

                            //得到值后存储封装在map集合中
                            MethodBean methodBean = new MethodBean(method ,clazz.newInstance() );
                            map.put(value, methodBean);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        try {
            //获取地址
            String uir = req.getRequestURI();

            //截取地址
            String path = uir.substring(0, uir.lastIndexOf("."));

            //用截取到的地址去map集合中找对象
            //那就得创建map集合对象
            MethodBean methodBean = map.get(path);

            //判断有没有执行到方法
            if (methodBean != null) {
                //不为空,执行到了,便获取参数
                Method method = methodBean.getMethod();
                Object object = methodBean.getObject();

                //调用方法
                method.invoke(object , req , resp);
            }else {
                System.out.println("没有找到方法......"+path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
//controller  需要扫描的包

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
public class UserController {

    @ResqustMapping("/user/register")
    public void register(HttpServletRequest  req, HttpServletResponse resp){
        System.out.println("调用了UserControllor的用户注册......register");
    }


    @ResqustMapping("/user/login")
    public void login(HttpServletRequest  req, HttpServletResponse resp){
        System.out.println("调用了UserControllor的用户登录......login");
    }
}
//bean 包

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.lang.reflect.Method;

@Data
@AllArgsConstructor//有参
@NoArgsConstructor//无参
@ToString
public class MethodBean {
    private Method method;
    private Object object;
}
//定义注解的包annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)//表示在方法上面打注解
@Retention(RetentionPolicy.RUNTIME)//表示这个注解的生命周期
//这个注解是给类下面的方法做标记
public @interface ResqustMapping {
    String value();

}
//定义注解的包annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)//这个注解是作用在类上面的
@Retention(RetentionPolicy.RUNTIME)//这个注解的生命周期直到运行阶段都还存在
//定义一个注解作为类的标记,这个注解为空的
public @interface Controller {

}
<!--相关依赖  pom.xml-->

<dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.16</version>
    </dependency>
  </dependencies>
  <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>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <!-- 指定端口 -->
          <port>82</port>
          <!-- 请求路径 -->
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
<!--web.xml文件中定义需要扫描包的操作,初始化-->

	<!--注册DispatcherServlet-->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>servlet/DispatcherServlet</servlet-class>

		<!--告诉DispatcherServlet要扫描的包是哪个-->
		<init-param>
			<param-name>packageName</param-name>
			<param-value>controller</param-value>
		</init-param>


		<!--让DispatcherServlet在项目发布的时候,就进行初始化,执行init方法-->
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-20 15:33:56  更:2021-09-20 15:35:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 4:21:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计