SSM基础篇(六)--手写springmvc

手写springmvc

本次手写框架是为了更好的理解springmvc底层是如何运作的,参考springboot的思路,通过注解和反射来完成,这里需要导入三个jar包是为了json格式字符串的转换。
image

整体结构设计

包结构

SSM基础篇(六)--手写springmvc_第1张图片

执行流程图

SSM基础篇(六)--手写springmvc_第2张图片

第一步将请求和响应封装成类

HttpServletRequest封装了url属性

package javax.http;
public class HttpServletRequest {
    //  /register,/login
    String url;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
}

HttpServletResponse封装了执行结果

package javax.http;
public class HttpServletResponse {
    // controller执行的结果
    String responseBody;
    public String getResponseBody() {
        return responseBody;
    }
    public void setResponseBody(String responseBody) {
        this.responseBody = responseBody;
    }
}

第二步定义注解用于扫描类和方法

Controller注解

package org.springmvc.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 {
}

RestController注解

package org.springmvc.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//controller返回的是对象
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RestController {
}

RequestMapping的value属性是为了获取注解参数

package org.springmvc.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 RequestMapping {
    String value();
}

第三步定义一个响应数据的实体类和两个处理器

OrderEntity类

定义一个实体类用来封装要相应的参数

package com.tedu.mall.controller;
public class OrderEntity {
    String id;
    int price;
    public OrderEntity(String id, int price) {
        super();
        this.id = id;
        this.price = price;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
}

UserController类

加注解Controller和RequestMapping,用于通过访问返回结果封装在HttpServletResponse的对象中

package com.tedu.mall.controller;
import javax.http.HttpServletResponse;
import org.springmvc.annotation.Controller;
import org.springmvc.annotation.RequestMapping;
@Controller
public class UserController {
    @RequestMapping("/register")
    public HttpServletResponse register() {
        HttpServletResponse response=new HttpServletResponse();
        response.setResponseBody("register success");
        return response;
    }
    @RequestMapping("/login")
    public HttpServletResponse login() {
        HttpServletResponse response=new HttpServletResponse();
        response.setResponseBody("login success");
        return response;
    }
}

OrderController类

加注解RestController和RequestMapping,用于通过访问返回结果封装在OrderEntity对象中返回给客户端

package com.tedu.mall.controller;
import org.springmvc.annotation.RequestMapping;
import org.springmvc.annotation.RestController;
@RestController
public class OrderController {
    @RequestMapping("/getOrder")
    public OrderEntity getOrder() {
        OrderEntity orderEntity = new OrderEntity("202008120001", 9000);
        return orderEntity;
    }
}

第四步编写一个ControllerDefinition实体类用于封装每一个controller中的方法。

package org.springmvc;

//封装controller
public class ControllerDefinition {
    String url;// /register /login
    String controllerName;// UserController
    String methodName;// register,login
    Boolean isJson;
    public ControllerDefinition(String url, String controllerName, String methodName, Boolean isJson) {
        super();
        this.url = url;
        this.controllerName = controllerName;
        this.methodName = methodName;
        this.isJson = isJson;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getControllerName() {
        return controllerName;
    }
    public void setControllerName(String controllerName) {
        this.controllerName = controllerName;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
    public Boolean getIsJson() {
        return isJson;
    }
    public void setIsJson(Boolean isJson) {
        this.isJson = isJson;
    }
    
}

第五步编写一个WebApplictionContext类用于扫描所有的controller并封装在map中

package org.springmvc;

import java.lang.reflect.Method;
import java.util.HashMap;

import org.springmvc.annotation.RequestMapping;
import org.springmvc.annotation.RestController;

public class WebApplictionContext {
    // /register,{/register,UserController,register,false}
    // /login,{/login,UserController,login,false}
    public static HashMap UrlMapping = new HashMap<>();

    public void init() throws Throwable {
        // 扫描所有的controller
        String[] controllerNames = { "com.tedu.mall.controller.UserController" ,
                "com.tedu.mall.controller.OrderController"};
        for (String controllerName : controllerNames) {
            Class clazz = Class.forName(controllerName);
            // 得到所有方法
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                // 判断方法有没有加requestMapping注解
                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                if (requestMapping != null) {
                    // 得到url
                    String url = requestMapping.value();
                    // 创建ControllerDefinition
                    String methodName = method.getName();
                    boolean isJson = false;
                    //判断这个类有没有加@restController
                    RestController restController=(RestController) clazz.getAnnotation(RestController.class);
                    if (restController!=null) {
                        isJson=true;
                    }
                    ControllerDefinition controllerDefinition = new ControllerDefinition(url, controllerName,
                            methodName, isJson);
                    // 把controllerDefinition放到UrlMapping
                    UrlMapping.put(url, controllerDefinition);
                }
            }
        }
    }
}

第六步编写一个DispatcherServlet前端处理器

package org.springmvc;

import java.lang.reflect.Method;

import javax.http.HttpServletRequest;
import javax.http.HttpServletResponse;

import com.fasterxml.jackson.databind.ObjectMapper;

public class DispatcherServlet {
    WebApplictionContext context = new WebApplictionContext();

    public DispatcherServlet() throws Throwable {
        context.init();
    }

    public HttpServletResponse doDispatch(HttpServletRequest request) throws Throwable {
        // 到webApplicationContext.urlMapping找到controller
        ControllerDefinition controllerDefinition = context.UrlMapping.get(request.getUrl());
        // 调用controller中的方法
        String controllerName = controllerDefinition.getControllerName();
        String methodName = controllerDefinition.getMethodName();

        Class clazz = Class.forName(controllerName);
        Object controllerObject = clazz.newInstance();
        Method method = clazz.getDeclaredMethod(methodName);
        // OrderController.getOrder()返回的是OrderEntity
        // UserController.register()/login()返回的是response
        HttpServletResponse response = null;
        if (controllerDefinition.isJson == false) {
            // userController
            response = (HttpServletResponse) method.invoke(controllerObject);
        } else {
            // orderController
            Object result = method.invoke(controllerObject);

            // 用jackson框架把result转成json字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(result);
            response = new HttpServletResponse();
            response.setResponseBody(jsonString);
        }
        return response;
    }
}

第七步编写一个WebServer服务器

package org.springmvc;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
import javax.http.HttpServletRequest;
import javax.http.HttpServletResponse;
import javax.xml.ws.http.HTTPBinding;
//实现tomcat的核心功能
public class WebServer {
    public static void main(String[] args) throws Throwable{
        //监听端口号
        ServerSocket serverSocket=new ServerSocket(8080);
        System.out.println("webServer运行了");
        while(true) {
            Socket socket=serverSocket.accept();
            HttpRequestThread thread=new HttpRequestThread(socket);
            thread.start();
        }

    }
    static class HttpRequestThread extends Thread{
        Socket socket;
        
        public HttpRequestThread(Socket socket) {
            super();
            this.socket = socket;
        }

        @Override
        public void run() {
            //接收浏览器发过来的请求
            try {
                InputStream inputStream=socket.getInputStream();
                InputStreamReader inputStreamReader=new InputStreamReader(inputStream);
                BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
                String requestLine=bufferedReader.readLine();
                System.out.println(requestLine);
                // get /login
                //分词,
                StringTokenizer stringTokenizer=new StringTokenizer(requestLine);
                String requestMethod=stringTokenizer.nextToken();
                System.out.println("requestMethod="+requestMethod);
                String url=stringTokenizer.nextToken();
                System.out.println("url="+url);
                
                //把浏览器发过来的请求交给dispatcherServlet
                HttpServletRequest request=new HttpServletRequest();
                request.setUrl(url);
                
                DispatcherServlet dispatcherServlet=new DispatcherServlet();
                HttpServletResponse response=dispatcherServlet.doDispatch(request);

                System.out.println("controller执行的结果:"+response.getResponseBody());
            //把controller的结果返回给浏览器
                //响应行
                String responseLine="HTTP/1.1 200 ok \r\n";
                //响应头
                StringBuilder stringBuilder=new StringBuilder();
                stringBuilder.append("Content-Type:text/html\r\n");
                String responseBody=response.getResponseBody();
                stringBuilder.append("Content-Length:"+responseBody.length()+"\r\n");
                stringBuilder.append("\r\n");
                //响应体
                OutputStream outputStream=socket.getOutputStream();
                outputStream.write(responseLine.getBytes());
                outputStream.write(stringBuilder.toString().getBytes());
                outputStream.write(responseBody.getBytes());
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }
}

你可能感兴趣的