项目实战:中央控制器实现(4)-实现RequestBody注解的功能-获取请求体参数

1、DispatcherServlet

java 复制代码
package com.csdn.mymvc.core;
import com.csdn.fruit.dto.Result;
import com.csdn.fruit.util.RequestUtil;
import com.csdn.fruit.util.ResponseUtil;
import com.csdn.mymvc.annotation.RequestBody;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.Map;
@WebServlet("/*")
public class DispatcherServlet extends HttpServlet {

    private final String BEAN_FACTORY = "beanFactory";
    private final String CONTROLLER_BEAN_MAP = "controllerBeanMap";

    @Test
    public void uri() {
        String uri = "/fruit/index";
        String[] arr = uri.split("/");
        System.out.println(Arrays.toString(arr));//[, fruit, index]
    }
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String[] staticResourceSuffixes = {".html", ".jsp", ".jpg", ".png", ".gif", ".css", ".js", ".ico"};
        String uri = req.getRequestURI();
        if (Arrays.stream(staticResourceSuffixes).anyMatch(uri::endsWith)) {
            RequestDispatcher defaultDispatcher = req.getServletContext().getNamedDispatcher("default");
            defaultDispatcher.forward(req, resp);
        } else {
            String[] arr = uri.split("/");
            if (arr == null || arr.length != 3) {
                throw new RuntimeException(uri + "非法!");
            }
            //[, fruit, index]
            String requestMapping = "/" + arr[1];
            String methodMapping = "/" + arr[2];

            ServletContext application = getServletContext();
            ControllerDefinition controllerDefinition = ((Map<String, ControllerDefinition>) application.getAttribute(CONTROLLER_BEAN_MAP))
                    .get(requestMapping);

            if (controllerDefinition == null) {
                throw new RuntimeException(requestMapping + "对应的controller组件不存在!");
            }
            //获取请求方式,例如:get或者post
            String requestMethodStr = req.getMethod().toLowerCase();
            //get_/index
            Method method = controllerDefinition.getMethodMappingMap().get(requestMethodStr + "_" + methodMapping);
            Object controllerBean = controllerDefinition.getControllerBean();

            try {
                //第 1 步:参数处理
                //获取method方法上的参数
                Parameter[] parameters = method.getParameters();
                Object[] parameterValues = new Object[parameters.length];
                for (int i = 0; i < parameters.length; i++) {
                    Parameter parameter = parameters[i];

                    RequestBody requestBodyAnnotation = parameter.getDeclaredAnnotation(RequestBody.class);
                    Object parameterValue = null;
                    if (requestBodyAnnotation != null) {
                        parameterValue = RequestUtil.readObject(req, parameter.getType());
                    } else {
                        //获取参数名称
                        //JDK8之前,通过反射获取到参数对象(Parameter对象)
                        //然后通过parameter.getName()方法是得不到形参的名称的,返回的是arg0,arg1,arg2....
                        //JDK8开始,反射技术得到的Class中可以包含方法形参的名称,不过需要做一个额外的设置:
                        //java compiler中添加一个参数:-parameters
                        String paramName = parameter.getName();
                        String paramValueStr = req.getParameter(paramName);
                        if (paramValueStr != null) {
                            //获取参数的类型
                            String parameterTypeName = parameter.getType().getName();
                            parameterValue = switch (parameterTypeName) {
                                case "java.lang.String"-> paramValueStr;
                                case "java.lang.Integer"-> Integer.parseInt(paramValueStr);
                                default -> null;
                            };
                        }
                    }
                    parameterValues[i] = parameterValue;
                }
                //第 2 步:方法调用
                //调用controllerBean对象中的method方法
                method.setAccessible(true);
                Object returnObj = method.invoke(controllerBean, parameterValues);
                if (returnObj != null && returnObj instanceof Result) {
                    Result result= (Result) returnObj;
                    ResponseUtil.print(resp,result);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }

        }
    }
}

2、FruitController

java 复制代码
package com.csdn.fruit.controller;
import com.csdn.fruit.dto.PageInfo;
import com.csdn.fruit.dto.PageQueryParam;
import com.csdn.fruit.dto.Result;
import com.csdn.fruit.pojo.Fruit;
import com.csdn.fruit.service.FruitService;
import com.csdn.mymvc.annotation.*;
@Controller
@RequestMapping("/fruit")
public class FruitController {
    @Autowire
    private FruitService fruitService;

    @GetMapping("/index")
    public Result index(Integer pageNo,String keyword) {
        if (pageNo == null) {
            pageNo = 1;
        }
        if (keyword == null) {
            keyword = "";
        }
        PageQueryParam pageQueryParam = new PageQueryParam(pageNo, 5, keyword);
        PageInfo<Fruit> pageInfo = fruitService.getFruitPageInfo(pageQueryParam);

       return Result.OK(pageInfo);

    }

    @PostMapping("/add")
    public Result add(@RequestBody Fruit fruit)  {
        fruitService.addFruit(fruit);
        return Result.OK();
    }

    @GetMapping("/del")
    public Result del(Integer fid){
        fruitService.delFruit(fid);
        return Result.OK();
    }

    @GetMapping("/edit")
    public Result edit(Integer fid){
        Fruit fruit = fruitService.getFruitById(fid);
        return Result.OK(fruit);
    }

    @GetMapping("/getFname")
    public Result getFname(String fname){ //fname是请求参数
        Fruit fruit = fruitService.getFruitByFname(fname);
         return fruit == null ? Result.OK() : Result.Fail();
    }

    @PostMapping("/update")
    public Result update(@RequestBody Fruit fruit){ //fruit是请求体参数
        fruitService.updateFruit(fruit);
        return Result.OK();
    }
}
相关推荐
长亭外的少年3 分钟前
ClickHouse 介绍:深度解析高性能列式数据库的核心优势
java·数据库·clickhouse
tokengo5 分钟前
从Java开发者到.NET Core初级工程师学习路线:C#语言基础
java·csharp·新人入门
java6666688885 分钟前
深入理解Spring Boot中的配置加载顺序
java·spring boot·后端
空青72634 分钟前
ChatGPT在Java后端开发中的应用与影响
java·开发语言·人工智能·后端·神经网络·机器学习·chatgpt
莫得等待35 分钟前
MySQL的慢sql
java
威哥爱编程1 小时前
Nginx性能调优5招35式不可不知的策略实战
java·nginx·性能调优
五月阳光暖洋洋1 小时前
SpringBoot2.2.6使用spring-boot-validation读取不到自定义配置文件中的属性
java·开发语言·spring boot
刘钢筋universe1 小时前
leetcode hot100
java·算法·leetcode
java6666688881 小时前
深入理解Spring Boot中的容器与依赖注入
java·spring boot·后端
u0104058361 小时前
Spring Boot中的依赖注入和控制反转
java·spring boot·后端