自定义@ResponseBody以及SpringMVC总结

文章目录

1.需求分析

2.目录

3.自定义ResponseBody注解

java 复制代码
package com.sunxiansheng.springmvc.annotation;

import java.lang.annotation.*;

/**
 * Description: 自定义ResponseBody注解
 * @Author sun
 * @Create 2024/8/6 16:09
 * @Version 1.0
 */
@Retention(value = RetentionPolicy.RUNTIME) // 运行时生效
@Target(value = ElementType.METHOD) // 作用在方法上
@Documented // 生成文档
public @interface ResponseBody {}

4.MonsterController.java

java 复制代码
    /**
     * 返回JSON数据的格式
     */
    @ResponseBody // 返回JSON数据
    @RequestMapping(url = "/json/monster")
    public List<Monster> jsonMonster(HttpServletResponse response) {
        // 设置响应类型
            // 获取怪物列表
            List<Monster> monsters = monsterService.listMonster();
            // 日志打印monsters
            log.info("monsters: {}", monsters);
            // 响应JSON数据
            return monsters;
    }

5.Monster.java 实现序列化接口

6.引入jackson

xml 复制代码
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.4</version> 
        </dependency>

7.Adapter.java 如果有@ResponseBody注解就返回json

java 复制代码
package com.sunxiansheng.springmvc.adaptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sunxiansheng.springmvc.annotation.ResponseBody;
import com.sunxiansheng.springmvc.handler.HandlerMapping;
import com.sunxiansheng.springmvc.handler.SunHandler;
import com.sunxiansheng.springmvc.viewparser.ViewParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Description: 适配器
 *
 * @Author sun
 * @Create 2024/8/8 14:13
 * @Version 1.0
 */
public class Adapter {

    private static final Logger log = LoggerFactory.getLogger(Adapter.class);

    /**
     * 3.适配器请求分发
     *
     * @param request
     * @param response
     */
    public static void executeDispatch(HttpServletRequest request, HttpServletResponse response) {
        // 4.调用映射器获取映射关系
        HandlerMapping handlerMapping = SunHandler.getHandlerMapping(request);

        // 如果没有找到映射器,就返回404
        if (handlerMapping == null) {
            try {
                response.getWriter().write("404 NOT FOUND");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return;
        }

        // 匹配成功,调用目标方法
        Object controller = handlerMapping.getController();
        Method method = handlerMapping.getMethod();
        // 5.调用参数解析器,解析参数
        Object[] args = ResolveArguments.resolveMethodArguments(request, response, method);
        // 日志,打印实参列表数组
        List<Class<?>> argsList = new ArrayList<>();
        for (Object arg : args) {
            argsList.add(arg.getClass());
        }
        log.info("实参列表:{}", argsList);
        try {
            // 反射调用方法
            Object invoke = method.invoke(controller, args);
            // 先判断有没有@ResponseBody注解,如果有则返回JSON
            if (method.isAnnotationPresent(ResponseBody.class)) {
                // 使用 Jackson 进行 JSON 序列化
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonResponse = objectMapper.writeValueAsString(invoke);
                // 设置响应内容类型和编码
                response.setContentType("application/json;charset=utf-8");
                response.setCharacterEncoding("UTF-8");
                // 将 JSON 响应数据写入到响应输出流
                response.getOutputStream().write(jsonResponse.getBytes());
            } else {
                // 6.调用视图解析器,进行视图解析
                if (invoke instanceof String) {
                    ViewParser.parse(invoke.toString(), request, response);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

}

8.测试

9.SpringMVC执行流程

  • 中央控制器 是一个Servlet,配置了,在Tomcat启动时调用init方法
  • init方法完成初始化Spring容器,初始化映射器的操作
  • 浏览器发送请求,交给适配器 完成请求分发
  • 适配器 首先从映射器 中获取映射关系 ,其中映射关系包括url、目标对象、Method对象
  • 适配器 调用参数解析器 根据形参列表的类型来填充实参列表 ,然后反射调用方法
  • 适配器 检测方法是否有**@ResponseBody注解,如果有则返回Json数据,如果没有则将结果交给视图解析器**处理
  • 视图解析器 根据冒号进行分割,请求转发或者重定向到指定的视图
相关推荐
jingde5283 天前
SpringMVC中使用REST风格
springmvc
垚森12 天前
SpringBoot兼容SpringMVC带有.do后缀的请求
springmvc·.do后缀
_leyilea12 天前
Java内存马系列 | SpringMVC内存马 - 上 | SpringMVC代码分析
java·开发语言·springmvc·内存马
沿途欣赏i15 天前
关于SpringMVC的理解
springmvc
m0_7194145617 天前
【SpringMVC】
java·springmvc
王小二(海阔天空)22 天前
浅谈SpringMvc的核心流程与组件
springmvc·核心流程·核心组件
S-X-S24 天前
SpringMVC核心机制环境搭建
springmvc
空谷忧人1 个月前
【SpringMVC】SpringMVC中单元方法获取请求数据的方式
java·后端·mvc·springmvc
醉颜凉1 个月前
SpringMVC 运行流程
java·面试·mvc·springmvc·model·controller·view