配置自定义视图解析器

自定义视图解析器类

/*
	Order接口的作用是在springmvc内部遍历时,使自定义视图解析器第一个解析。
*/
@Component
public class MyViewResolver implements ViewResolver, Ordered {
    private int order=1;

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (viewName.startsWith("keyi:")){
            return new MyView();
        }else{
            return null;
        }
    }

    @Override
    public int getOrder() {
        return order;
    }
}

自定义视图类

public class MyView implements View {
    @Override
    public String getContentType() {
        return "text/html";
    }
    
    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, 
                       HttpServletResponse response) throws Exception {
        if (model!=null){
            Set<? extends Map.Entry<String, ?>> entries = model.entrySet();
            for (Map.Entry<String, ?> s:entries){
                String key = s.getKey();
                Object value = s.getValue();
                request.setAttribute(key,value);
            }
        }
        request.getRequestDispatcher("/success.html").forward(request,response);
    }
}

注册自定义视图解析器

@Component
public class MyConfig {

    /*配置WebMvcConfigurer,定制化SpringMVC的功能*/
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            /*配置自定义视图解析器*/
            @Override
            public void configureViewResolvers(ViewResolverRegistry registry) {
                registry.viewResolver(new MyViewResolver());
            }
        };
    }
}

目标方法

@GetMapping("/test2")
public String test2(){
    /*
        自定义视图解析器原理
    */
    System.out.println("测试");
    return "keyi:success";
}

流程

请求以http://localhost:8080/test2,get请求,目标返回"keyi:success"
底层遍历容器中所有的视图解析器,找到自定义视图解析器,根据返回值字符串,创建自定义的视图对象
调用视图对象的render方法渲染数据跳转视图。

视图解析器原理

SpringBoot和SpringMVC不同在于,它有一个内容协商的功能,
在SpringMVC中,你配置了自定义视图解析器,底层直接给你遍历,找到并使用自定义解析器来创建视图对象
但在SpringBoot中,它配置了一个ContentNegotiatingViewResoulver,在这个解析器的resolveViewName方法
中,再次遍历容器中其余的视图解析器,并且,在该方法中,最后是根据视图对象的getContentType()方法来匹配
合适的媒体类型进行解析,所以,如果你的自定义视图对象没有重写该方法,则你的视图对象并不能被返回,而是返回
thymeleafView或者InternalView,这样就会导致你的自定义视图解析没有效果,终于通过debug找出来了,舒服。