springboot使用velocity以及访问j静态资源

本文介绍了在SpringBoot中如何使用Velocity模板引擎以及处理静态资源的问题。在SpringBoot 1.5以后版本, Velocity不再支持,但通过特定配置仍可使用。文章详细记录了配置过程,包括maven依赖、velocityConfig.xml的设置、静态资源加载、异常处理以及在升级SpringBoot版本后遇到的问题和解决方法,如类版本冲突、模板文件位置等。最后,建议对于小项目考虑使用官方推荐的Thymeleaf代替Velocity。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

访问静态资源
参考文章:https://www.jianshu.com/p/d127c4f78bb8
参考文章已经写得很详细了,这里就不再赘述

使用velocity
参考文章:https://zhuanlan.zhihu.com/p/28251412

我遇到的问题和参考文章一样,springboot版本是高于1.5的,但是1.5以后由不支持vm,改成freemarker或者其他要重新学语法,比较麻烦。根据参考文章可以使用vm,我自己测试下来中间有点不一样,记录如下:

1、maven引用,不引用和主springboot一样的版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-velocity</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

2、/src/resources路径下创建一个velocityConfig.xml,配置如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="mvcVelocityEngine" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath" value="/static/" /><!-- 模板存放的路径 -->
        <!--原文有个加载配置文件的配置,我自己测下来没用-->
        <property name="velocityProperties"><!--这个不加,加载出来的页面是乱码-->
            <props>
                <prop key="input.encoding">utf-8</prop>
                <prop key="output.encoding">utf-8</prop>
            </props>
        </property>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        <property name="cache" value="false" />
        <property name="prefix" value="/static/" /><!-- 视图文件的前缀,即存放的路径 -->
        <property name="suffix" value=".vm" /><!-- 视图文件的后缀名 -->
        <property name="dateToolAttribute" value="date" /><!--日期函数名称-->
        <property name="numberToolAttribute" value="number" /><!--数字函数名称-->
        <property name="contentType" value="text/html;charset=UTF-8" />
        <property name="exposeSpringMacroHelpers" value="true" /><!--是否使用spring对宏定义的支持-->
        <property name="exposeRequestAttributes" value="true" /><!--是否开放request属性-->
        <property name="requestContextAttribute" value="rc"/><!--request属性引用名称-->
        <!--<property name="toolboxConfigLocation" value="/WEB-INF/toolbox.xml"/>--><!--这个没用到,vm页面内自定义的函数也可以使用-->
    </bean>
</beans>

在启动文件Application.java中引用xml

@ImportResource({"classpath:velocityConfig.xml"})

3、静态资源加载
我用的是继承WebMvcConfigurerAdapter,所以重写addResourceHandlers方法

registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("classpath:/resources/");

vm文件放在/src/resources/static路径下

4、异常问题查询。
问题描述:访问localhost:9070,拦截器中有拦截,如果访问路径是/,会跳转首页。但是拦截器拦截到的始终是访问/error,返回的视图一直是errorHtml。日志也没有任何报错。

异常处理过程。
1)刚开始想着,既然报错了,那就搞个modelAndView,返回error界面好了。

@RequestMapping(value = { "/error"})
    public ModelAndView error() {
	    return new ModelAndView("error");
    }

结果报错了,说urlmapping的时候有冲突,重复定义了,出现了一个没见过的controller。BasicErrorController。看了下,这个应该是spring boot自带的异常处理的controller,以下写的是我自己的异常查找和处理过程,有兴趣的可以看下参考链接https://blog.youkuaiyun.com/lh87270202/article/details/79925951

2)源码异常跟踪
debug跟踪到以下地方,我没有配置无路径的mapping,本来是想在拦截器中,如果拦截到地址是/ 的,做登录首页跳转的,但是因为没有配置,spring boot表示404,找不到啊。所以在BasicErrorController中走到了errorHtml方法里。

@RequestMapping(value = { "/"})
    public ModelAndView index() {
        return new ModelAndView("index");
    }
@RequestMapping(produces = "text/html")
	public ModelAndView errorHtml(HttpServletRequest request,
			HttpServletResponse response) {
		HttpStatus status = getStatus(request);
		Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
				request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
		response.setStatus(status.value());
		ModelAndView modelAndView = resolveErrorView(request, response, status, model);
		return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
	}

debug可以发现status 是404,根据404去查找错误视图,但是我没有找到怎么配置this.errorViewResolvers,也可能是我没仔细找,后续找到了再补充。总之走了默认的错误视图查找。AbstractErrorController中代码如下

protected ModelAndView resolveErrorView(HttpServletRequest request,
			HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
		for (ErrorViewResolver resolver : this.errorViewResolvers) {
			ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
			if (modelAndView != null) {
				return modelAndView;
			}
		}
		return null;
	}

在默认错误视图查找,先拼接了页面的相对路径 error/404.html。然后在资源路径中查找视图,视图定死是html界面,所以我原先的vm界面要改成html界面。
DefaultErrorViewResolver中代码如下

private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
		for (String location : this.resourceProperties.getStaticLocations()) {
			try {
				Resource resource = this.applicationContext.getResource(location);
				resource = resource.createRelative(viewName + ".html");
				if (resource.exists()) {
					return new ModelAndView(new HtmlResourceView(resource), model);
				}
			}
			catch (Exception ex) {
			}
		}
		return null;
	}

其中this.resourceProperties.getStaticLocations()并不是我们在上文中配置的

registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("classpath:/resources/");

而是默认的资源路径,所以只要将error界面放在某一个路径下就好了。

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
			"classpath:/META-INF/resources/", "classpath:/resources/",
			"classpath:/static/", "classpath:/public/" }

5、升级jdk,升级springboot2.0.3(20180717更新)
升级jdk没什么问题,升级springboot就有问题了,1.5至少在
org.springframework:spring-webmvc:jar:4.3.14.RELEASE包里面还是有velocity的相关类,当时2.0之后,至少在2.0.3里面,org.springframework:spring-webmvc:jar:5.0.7.RELEASE,连velocity的相关类都没有了,所以前面的velocityConfig.xml文件是会报错的

最终解决方案是去4.3.14版本里面,把velocity的相关类copy出来到自己的项目中(org.springframework.web.servlet.view.velocity),然后修改xml文件。
但是呢,在启动的时候,会自动加载一个spring.vm,默认值是找不到的
private static final String SPRING_MACRO_LIBRARY = "org/springframework/web/servlet/view/velocity/spring.vm";
这个时候要修改VelocityConfigurer类,改成类路径private static final String SPRING_MACRO_LIBRARY = "static/spring.vm";
然后把spring.vm文件放到resources/static/路径下就完美了

本地启动ok,然后服务器启动又又又出错了,类版本冲突了

Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/exc/InvalidDefinitionException

又把org.springframework.ui.velocity这包下的类copy出来,然后修改VelocityConfigurer的继承关系

然后启动又又又又报错了,ByteArrayFeeder是jackson-core 2.9以后出现的,所以要把jackson-core升级一下

Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/async/ByteArrayFeeder

另外使用springboot2,jdk要1.8以上,tomcat相关的包要升级到8.5以上,我的是8.5.31

项目不大呢最好还是vm给替换了吧,官方推荐是Thymeleaf

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值