如何在spring boot中添加名为“MultiViewResover”的新viewResover

时间:2016-12-05 02:22:57

标签: java spring spring-mvc spring-boot

在spring boot中,在spring boot中添加一个名为'MultiViewResover'的viewResover。 在控制器中如果我返回' ftl:/ freemarker / test'然后MultiViewResover将使用FreeMarkerViewResolver并找到/freemarker/test.ftl

如果我返回':/ thymeleaf / test'然后MultiViewResover将使用ThymeleafViewResolverand找到/freemarker/test.html

这是我的代码

Application.java

public class Application extends WebMvcConfigurerAdapter{

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        app.addInitializers();
        app.run(args);
    }

    @Autowired
    MultiViewResover resover;

    @Bean(name = "viewResover")
    public MultiViewResover getViewResolver() {
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        internalResourceViewResolver.setViewClass(JstlView.class);
        internalResourceViewResolver.setPrefix("/");
        internalResourceViewResolver.setSuffix(".jsp");

        ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
        thymeleafViewResolver.setViewClass(ThymeleafView.class);

        FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver();
        freeMarkerViewResolver.setPrefix("");
        freeMarkerViewResolver.setSuffix(".ftl");

        Map<String, ViewResolver> resolvers = new HashedMap();
        resolvers.put("jsp",internalResourceViewResolver);
        resolvers.put("th",thymeleafViewResolver);
        resolvers.put("ftl",freeMarkerViewResolver);

        resover.setResolvers(resolvers);
        return resover;
    }

    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

MultiViewResover.java

@Component   
public class MultiViewResover implements ViewResolver {

    private static Map<String, ViewResolver> resolvers ;

    /**
     * 默认视图类型为jsp视图
     */
    private static final String DEFAULT_VIEW_TYPE = "jsp";

    @Override
    public View resolveViewName(String viewName, Locale locale) throws Exception {
        int n = viewName.lastIndexOf(":"); // 获取
        String suffix = MultiViewResover.DEFAULT_VIEW_TYPE;
        // 默认使用jsp视图
        if (n != -1) {
            // 有的话截取:前面的字符串 这里一般是jsp,ftl,vm,th与Map resolvers中的key匹配
            suffix = viewName.substring(0, n);
            // 取:后面的部分 那时真正的资源名.比如我们要使用hello.jsp 那viewName就应该是jsp:hello
            viewName = viewName.substring(n+1);
        }
        // 根据:前面的字符串去获取托管的视图解析类对象
        ViewResolver resolver = resolvers.get(suffix);

        if (resolver != null)
            return resolver.resolveViewName(viewName, locale);
        return null;
    }

    public Map<String, ViewResolver> getResolvers() {
        return resolvers;
    }

    public void setResolvers(Map<String, ViewResolver> resolvers) {
        this.resolvers = resolvers;
    }

}

MyController.java

@RequestMapping(value = "/test1",name = "test return th view",method = RequestMethod.GET)
    public ModelAndView test1(){
        return thView("login");
    }
public ModelAndView thView(String viewPath){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("th:"+viewPath);
        return modelAndView;
    }

但是当我运行这个应用程序时会抛出异常

Caused by: java.lang.IllegalStateException: ApplicationObjectSupport instance [org.springframework.web.servlet.view.InternalResourceViewResolver@40e94dde] does not run in an ApplicationContext
    at org.springframework.context.support.ApplicationObjectSupport.getApplicationContext(ApplicationObjectSupport.java:141)
    at org.springframework.web.servlet.view.UrlBasedViewResolver.applyLifecycleMethods(UrlBasedViewResolver.java:513)
    at org.springframework.web.servlet.view.UrlBasedViewResolver.loadView(UrlBasedViewResolver.java:508)
    at org.springframework.web.servlet.view.AbstractCachingViewResolver.createView(AbstractCachingViewResolver.java:244)
    at org.springframework.web.servlet.view.UrlBasedViewResolver.createView(UrlBasedViewResolver.java:472)
    at org.springframework.web.servlet.view.AbstractCachingViewResolver.resolveViewName(AbstractCachingViewResolver.java:156)
    at me.luger.core.mvc.controller.MultiViewResover.resolveViewName(MultiViewResover.java:51)
    at me.luger.core.mvc.controller.MultiViewResover$$FastClassBySpringCGLIB$$8118b2de.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
    at me.luger.core.log.aspect.ControllerLogAspect.doAround(ControllerLogAspect.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
    at me.luger.core.mvc.controller.MultiViewResover$$EnhancerBySpringCGLIB$$c7c3b2b9.resolveViewName(<generated>)
    at org.springframework.web.servlet.view.ContentNegotiatingViewResolver.getCandidateViews(ContentNegotiatingViewResolver.java:299)
    at org.springframework.web.servlet.view.ContentNegotiatingViewResolver.resolveViewName(ContentNegotiatingViewResolver.java:220)
    at org.springframework.web.servlet.DispatcherServlet.resolveViewName(DispatcherServlet.java:1296)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1234)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    ... 25 common frames omitted

谢谢!

1 个答案:

答案 0 :(得分:0)

InternalResourceViewResolver需要应用程序上下文,因为它扩展了WebApplicationObjectSupport。因此,您需要将其创建为Bean,以便将其注入。

请注意,我没有看到这个MultiViewResolver的重点,因为您正在尝试实现Spring已经支持的功能。您可以添加多个视图解析器并对其进行排序,同时保持它们独立。您的实现将所有模板引擎绑定在一起,并忽略了一些视图解析器(如InternalResourceViewResolver)如果无法解析视图并且不会为视图提供另一个机会来解析该视图的事实另一个解析器。