SpringMVC学习

 1.SringMVC的实现原理

  springMVC的实现其实就是socket的上下文

SpringMVC学习_第1张图片

其中一个Server中包含多个connector,一个connector包含多个container。

2.Client和Socket一般有两种链接方式,一种是每个socket占用一个独立的线程,另一种是建立一个Selector容器,用Handle来遍历有请求的socket

SpringMVC学习_第2张图片

两者相比较后者更加快捷,而且阻塞时间更短,占据资源更少,实现了高并发访问。

3.参照源码,对SpringMVC进行仿写

  1.创建maven项目,添加依赖

<build>
      <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <configuration>
                    <source>8source>
                    <target>8target>
                configuration>
            plugin>
        plugins>
    build>
    <dependencies>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.2.1.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.2.1.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.10version>
        dependency>
    dependencies>
project>

直接创建maven项目可以为以后添加依赖提供方便

  2.为bean类添加注解

@Data //get 和setter方法
@NoArgsConstructor //无参构造方法
@AllArgsConstructor//有参构造方法
@ToString//toString方法

 3.仿照RestController和RequestMapping来写出自己的注解--MyRestController和MyRequestMapping

  

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 MyRestController {
    String value() default "";
}


import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRequestMapping {
    String value() default "";
}

4.创建ServerTest2类

// IOC 容器
    public static Map beanMap = new HashMap<>();
    // URL映射,RequestMapping
    public static Map methodMap = new HashMap<>();

    public static void main(String[] args) throws IOException {


        //调用扫描包的方法
        refreshBeanFactory("ydp.day01.Test");

        //建立服务器端socket
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(80));
        //是否为阻塞
        serverSocketChannel.configureBlocking(false);
        //创建存放socket的容器
        Selector selector = Selector.open();
        //将服务器端socket注册到selector中
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {

            if (selector.select(3000) <= 0) {
                continue;
            }
            //对selector容器中每一个注册的socket进行迭代,迭代完之后并remove
            Iterator keyIterator = selector.selectedKeys().iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                handle(key);
                //迭代完之后移除
                keyIterator.remove();
            }
        }
private static void requestHandle(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
//byte字节Buffer流 -> 字节流
ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
//clear:设置为写模式
byteBuffer.clear();

//从socket中读取内容到byteBuffer
if (socketChannel.read(byteBuffer) == -1) {
socketChannel.close();
return;
}
// 调用url所映射的方法
private static String methodInvoke(String url, List urlParams) throws InvocationTargetException, IllegalAccessException {
MethodInfo methodInfo = methodMap.get(url);
// 如果url中参数个数与方法中参数个数不一致,则返回404
if (methodInfo == null) {
return "404";
}
String className = methodInfo.getClassName();
Method method = methodInfo.getMethod();
Object beanObj = beanMap.get(className);
Object[] params = new Object[urlParams.size()];
Parameter[] parameters = method.getParameters();
// 如果url中参数个数与方法中参数个数不一致,则返回404
if (params.length != parameters.length) {
return "参数个数不匹配";
}
// 按照方法中参数的属性,来进行参数转换和填充
int i = 0;
for (Parameter p : parameters) {
String type = p.getType().getSimpleName();
String pName = p.getName();
boolean flag = false;
for (String p2 : urlParams) {
String pp[] = p2.split("=");
if (pName.equals(pp[0])) {
// 根据类型进行参数转换
Object pValue = paramTranslate(type, pp[1]);
params[i++] = pValue;
flag = true;
continue;
}
}
if (!flag)
return "参数名称不匹配";
}
return (String) method.invoke(beanObj, params);
}
}

这样就能完成对基本类型的参数,包"ydp/day01/Test/UserController"下所有有MyRequestMapping的方法进行调用了。

 这里只贴出了部分代码详细代码见GitHub链接:https://github.com/yao-cz/repository/tree/master

你可能感兴趣的:(SpringMVC学习)