Spring MVC中使用自定义ViewResolver对自定义View进行处理

Spring MVC为编程人员默认提供了很多的ViewResolver,ViewResolver的主要作用就是讲Controller层返回的View进行处理渲染并最终写入到Response中对请求进行返回。当默认的ViewResolver无法满足要求时我们可以通过自定义ViewResolver的形式来增加独特的功能。

先定义一个对象ViewName,由于这个对象是我们自定义的,所以当返回这个对象的时候没有相应的ViewResolver可以对它进行处理,这个时候就需要使用自定义的ViewResolver来处理这种情况。

package hello.test;

public class ViewName {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

接着是定义一个Controller,这个Controller的第一个方法返回刚刚自定义的ViewName对象

package hello.test;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.concurrent.Callable;

/**
 * @Auther: wangzhen25
 * @Date: 2018/11/22 14:07
 * @Description:
 */
@Controller
public class TestController {

    @GetMapping("/test")
    public ViewName test4(ModelMap modelMap) {
        modelMap.put("key", "value");
        ViewName viewName = new ViewName();
        viewName.setName("test");
        return viewName;
    }
}

接着定义一个自定义的View,自定义的View需要继承View接口的同时要重写render方法,render方法的作用就是使用传入的Model对象对视图进行渲染并最终写入到Response中。

package hello.test;

import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

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 {
        for(Map.Entry<String, ?> entry : model.entrySet()) {
            response.getWriter().write(entry.getKey() + " " + entry.getValue());
        }
    }
}

然后定义一个自定义的ViewResolver,这个ViewResovler用于对Controller层返回的ViewName进行判断,如果发现返回的viewName是test的话就返回刚刚自定义的View,否则返回null

package hello.test;

import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

import java.util.Locale;

public class MyViewResolver implements ViewResolver {

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

最后再定义一个自定义的HandlerMethodReturnValueHandler用来对一开始返回的ViewName对象进行解析判断,首先是在supportReturnType中判断是否能够处理这个类型,在这里将它的类型和ViewName这个类进行判断,如果发现是ViewName类就返回true,否则返回false,只有返回true才能最终进入handleReturnValue这个方法,在这个方法中主要的作用就是从ViewName这个对象中解析出了一个字符串View同时向ModelAndView容器中添加,在这一步也可以进行其他的复杂操作,但是最终都需要对mavContainer进行view属性的设置,这样才能进入MyViewResolver类中对请求想要获取的具体View进行判断。

package hello.test;

import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

public class MyHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        boolean result = returnType.getParameterType().isAssignableFrom(ViewName.class);
        return result;
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        ViewName viewName = (ViewName) returnValue;
        mavContainer.setViewName(viewName.getName());
    }
}

最终将以上的视图处理器和视图解析器都配置到Spring中即可使用。

@Configuration
public class TestConfiguration implements WebMvcConfigurer {

    @Bean("/controller")
    public MyController myController() {
        return new MyController();
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.viewResolver(new MyViewResolver());
        registry.viewResolver(new MySecondViewResolver());
    }

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
        handlers.add(new MyHandlerMethodReturnValueHandler());
    }
}

整个流程可总结如下:首先是Controller层中返回了一个对象,接着框架会进行遍历判断找出能够处理这个类型的HandlerMethodReturnValueHandler,找到相应的Handler后就会对使用返回的对象进行操作,同时会生成一个带有ViewName的ModelAndView对象,接着框架会对这个ModelAndView对象进行处理,这时候框架就会使用所有ViewResolver对这个ViewName进行遍历判断找到能够处理这个ViewName的ViewResolver,最终在ViewResolver中生成视图并返回。

猜你喜欢

转载自blog.csdn.net/turbo_zone/article/details/84571503