04-返回值处理器

准备对象

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

准备FreeMarker视图解析器

java 复制代码
@Configuration
public class WebConfig {

    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
        freeMarkerConfigurer.setDefaultEncoding("UTF-8");
        freeMarkerConfigurer.setTemplateLoaderPath("classpath:templates");
        return freeMarkerConfigurer;
    }

    @Bean
    public FreeMarkerViewResolver freeMarkerViewResolver(FreeMarkerConfigurer freeMarkerConfigurer) {
        // Spring初始化FreeMarkerView时,会要求Web环境  这里去掉此制约
        FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver() {
            public AbstractUrlBasedView instantiateView() {
                FreeMarkerView freeMarkerView = new FreeMarkerView() {
                    @Override
                    protected boolean isContextRequired() {
                        return false;
                    }
                };
                freeMarkerView.setConfiguration(freeMarkerConfigurer.getConfiguration());
                return freeMarkerView;
            }
        };
        freeMarkerViewResolver.setContentType("text/html;charset=utf-8");
        freeMarkerViewResolver.setPrefix("/");
        freeMarkerViewResolver.setSuffix(".ftl");
        freeMarkerViewResolver.setExposeSpringMacroHelpers(false);
        return freeMarkerViewResolver;
    }

}

准备控制器

java 复制代码
@Slf4j
static class Controller {

    public ModelAndView test1() {
        log.warn("test1()");
        // 添加视图名
        ModelAndView modelAndView = new ModelAndView("view1");
        // 添加模型名
        modelAndView.addObject("name", "张三");
        return modelAndView;
    }

    public String test2() {
        log.warn("test2()");
        // 返回视图名   只有视图 没有模型数据
        return "view2";
    }

    @ModelAttribute
    // 没有视图 默认将请求路径当作视图名
    //@RequestMapping("/test3")
    public User test3() {
        log.warn("test3()");
        // 只有模型数据  没有视图
        return new User("李四", 20);
    }
    
    public User test4() {
        log.warn("test4()");
        // 只有模型数据  没有视图
        return new User("王五", 30);
    }
    
    public HttpEntity<User> test5() {
        log.warn("test5()");
        return new HttpEntity<>(new User("赵六", 40));
    }

    public HttpHeaders test6() {
        log.warn("test6()");
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "text/html");
        return httpHeaders;
    }

    @ResponseBody
    public User test7() {
        log.warn("test7()");
        return new User("钱七", 50);
    }

}

准备返回值处理器组合

java 复制代码
private static HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite() {
    MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
    HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = new HandlerMethodReturnValueHandlerComposite();
    returnValueHandlerComposite.addHandlers(CollUtil.newArrayList(
            // 返回值:ModelAndView    test1
            new ModelAndViewMethodReturnValueHandler(),
            // 返回值字符串:视图名    test2
            new ViewNameMethodReturnValueHandler(),
            // 返回模型数据  带@ModelAttribute注解   test3
            new ServletModelAttributeMethodProcessor(false),
            // 返回值:HttpEntity    test5
            new HttpEntityMethodProcessor(CollUtil.newArrayList(jackson2HttpMessageConverter)),
            // 返回值:HttpHeaders   test6
            new HttpHeadersReturnValueHandler(),
            // 返回值json: 带@ResponseBody注解   test7
            new RequestResponseBodyMethodProcessor(CollUtil.newArrayList(jackson2HttpMessageConverter)),
            // 返回模型数据  不带@ModelAttribute注解   test4
            new ServletModelAttributeMethodProcessor(true)
    ));
    return returnValueHandlerComposite;
}

处理返回值(打印要渲染的视图)

java 复制代码
@SneakyThrows
private static void renderValue(ModelAndViewContainer modelAndViewContainer, ServletWebRequest servletWebRequest,
                                AnnotationConfigApplicationContext applicationContext) {

    try {
        log.warn("=========>渲染视图内容");
        HttpServletRequest request = servletWebRequest.getRequest();
        MockHttpServletResponse response = (MockHttpServletResponse) servletWebRequest.getResponse();
        String viewName = modelAndViewContainer.getViewName();
        if (StrUtil.isBlank(viewName)) {
            viewName = ((String) request.getAttribute(UrlPathHelper.PATH_ATTRIBUTE));
            modelAndViewContainer.setViewName(viewName);
            log.warn("没有获取到视图名,获取默认视图:{}", viewName);
        }
        if (!modelAndViewContainer.isRequestHandled()) {
            // 获取 View
            FreeMarkerViewResolver freeMarkerViewResolver = applicationContext.getBean(FreeMarkerViewResolver.class);
            View view = freeMarkerViewResolver.resolveViewName(viewName, RequestContextUtils.getLocale(request));
            view.render(modelAndViewContainer.getModel(), request, response);
        }
        for (String headerName : response.getHeaderNames()) {
            System.out.println(headerName + "=" + response.getHeaders(headerName));
        }
        System.out.println(new String(response.getContentAsByteArray(), StandardCharsets.UTF_8));

        } catch (Exception e) {
            // 处理渲染异常
            e.printStackTrace(); // 这里需要根据实际情况处理异常
        }
}

测试返回值处理器

test1(ModelAndViewMethodReturnValueHandler)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test1");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}

test2(ViewNameMethodReturnValueHandler)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test2");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}

test3(ServletModelAttributeMethodProcessor)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test3");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
// 模拟将路径放入RequestAttribute中  模拟视图名字
request.setRequestURI("test3");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType("text/html;charset=utf-8");
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}

test4(ServletModelAttributeMethodProcessor)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test4");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
// 模拟将路径放入RequestAttribute中  模拟视图名字
request.setRequestURI("test4");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
MockHttpServletResponse response = new MockHttpServletResponse();
response.setContentType("text/html;charset=utf-8");
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}

test5(HttpEntityMethodProcessor)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test5");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}

test6(HttpHeadersReturnValueHandler)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test6");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}

test7(RequestResponseBodyMethodProcessor)

java 复制代码
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(WebConfig.class);
// 只探讨返回值处理器  所有测试方法都不带参数
Method method = Controller.class.getMethod("test7");
Controller controller = new Controller();
// 得到返回值
Object returnValue = method.invoke(controller);
// 拿到返回值类型
HandlerMethod handlerMethod = new HandlerMethod(controller, method);
MethodParameter returnType = handlerMethod.getReturnType();
// 模型视图容器
ModelAndViewContainer modelAndViewContainer = new ModelAndViewContainer();
// 模拟请求
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
// 返回值处理器
HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite = returnValueHandlerComposite();
if (returnValueHandlerComposite.supportsReturnType(returnType)) {
    returnValueHandlerComposite.handleReturnValue(
            returnValue, returnType, modelAndViewContainer, servletWebRequest
    );
    System.out.println(modelAndViewContainer.getModel());
    System.out.println(modelAndViewContainer.getViewName());
    renderValue(modelAndViewContainer, servletWebRequest, annotationConfigApplicationContext);
}
相关推荐
都叫我大帅哥1 分钟前
TOGAF迁移规划阶段全解密:从菜鸟到达人的通关秘籍
java
探索java3 分钟前
深入理解 Spring 中的 XmlBeanFactory 原理及实践
java·spring·xmlbeanfactory
奋进的孤狼6 分钟前
【Spring AI】阿里云DashScope灵积模型
人工智能·spring·阿里云·ai·云计算
hqxstudying2 小时前
Java异常处理
java·开发语言·安全·异常
我命由我123455 小时前
Kotlin 数据容器 - List(List 概述、创建 List、List 核心特性、List 元素访问、List 遍历)
java·开发语言·jvm·windows·java-ee·kotlin·list
武子康7 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
YuTaoShao10 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw10 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨10 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
双力臂40411 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试