欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Velocity 获取Request的请求URL

程序员文章站 2024-02-01 21:29:58
...

项目使用的是Velocity来渲染主体内容,大的框架还是使用JSP.

总体来说就是JSP + Velocity.

请求使用JSP, 异步使用VM

你问什么用Velocity不用freemarker 因为项目比较老.修改比较麻烦.

现在有一个需求,因为项目的生产和UAT使用的图片路径是不一样的.

这样导致在渲染Velocity模板的时候,需要有一个属性去判断使用什么版本的资源.

JSP很好判断,应为能够获取HttpServletRequest, 直接拿取RequestURL方法即可.

但是Velocity里面是无法获取Request的,难道要把URL作为参数传递过去.

那修改的代码量,无法想象.

大部分的Velocity模板都会有一个公共的头,在这个头中存储通用的信息,我们要是能够把

URL传入到这个头,就好了.

查阅资料,网上有一个通过编写指令来获取Request的想法提示了我.

可以通过指令来获取HttpServletRequest,把URL存入到变量中即可. 然后就设计了下面一个类.

package com.itheima.util;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.springframework.web.servlet.support.RequestContext;

/**
 * 路径存在,是一个velocity的指令类.
 * 用来判断url对应的生产环节
 * @author 陈淼
 * @time 2017年7月11日 下午3:25:37 
 */
public class UrlObtain extends Directive {
	// 可以使用反射去突破安全防线,
	private boolean canSecurity = true;
	
	@Override
	public String getName() {
		return "UrlObtain";
	}

	// Block块标示要使用#end结束 Line不需要
	@Override
	public int getType() {
		return LINE;
	}

	@Override
	public boolean render(InternalContextAdapter context,
            Writer writer, Node node )
			throws IOException, ResourceNotFoundException, ParseErrorException,
			MethodInvocationException {
		// 写入一个默认的域
		String requestUrl = "";
		int count = node.jjtGetNumChildren();
		// 给定了 默认的url
		if(count > 0) {
			Node jjtGetChild = node.jjtGetChild(0);
			if(jjtGetChild != null) {
				requestUrl =  (String) jjtGetChild.value(context);
			}
		}
		// 限制了反射
		if(count > 1) {
			Node jjtGetChild = node.jjtGetChild(1);
			if(jjtGetChild != null) {
				String securityValue =  (String) jjtGetChild.value(context);
				canSecurity = Boolean.valueOf(securityValue);
			}
		}
		RequestContext requestContext = (RequestContext) context.get("rc");
		if(requestContext == null) {
			throw new ResourceNotFoundException("please open velocity requestContextAttribute set value rc");
		}
		
		// 如果没有提供默认的url,并且 不允许使用反射, 那么报错.
		if(StringUtils.isEmpty(requestUrl) && !canSecurity) {
			throw new IOException("Either set the default URL, or open the reflect");
		}
		HttpServletRequest request = null;
		if(canSecurity) {
			
			try {
				
				Method method = requestContext.getClass().getDeclaredMethod("getRequest", null);
				method.setAccessible(true);
				request = (HttpServletRequest) method.invoke(requestContext, null);
				
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		
		// 获取真实url
		if(request != null) {
			requestUrl = request.getRequestURL().toString();
		}
		
		context.put("RequestURL", requestUrl);
		//requestContext.getModel().put("RequestURL", requestUrl);
		
		return true;
	}
	

}

## UrlObtain 具有两个参数, 默认是url地址和是否使用反射(默认为使用) 结果保存在RequestURL变量中

## 如果不使用反射, 则RequestURL变量时默认url地址,

## 如果没有传递默认url并且 禁止使用反射, 会抛出异常.

## UrlObtain 需要视图解析器开启requestContextAttribute属性 并命名为rc

## 不然会抛出异常.

#UrlObtain("www.baidu.com")


这样子 $RequestURL将可以获取到现在的URL

展开来说,既然反射可以拿到Request,那么Response也可以拿到.

还可以把Request和Response作为变量传递到Velocity模板中去.


需要注意的是.视图解析器的配置

	<bean id="velocityViewResolver"
		class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
		<property name="exposeSessionAttributes" value="true" />
		<property name="allowSessionOverride" value="true" />
		<property name="requestContextAttribute" value="rc" />
		<!-- 把request的属性扩展到模板中去 -->
		<property name="cache" value="true" />
		<property name="prefix" value="" />
		<property name="suffix" value=".vm" />
		<property name="order" value="1" />
		<property name="viewNames">
			<list>
				<value>test</value>
			</list>
		</property>
		<property name="dateToolAttribute" value="dateTool" />
		<property name="numberToolAttribute" value="numberTool" />
		<property name="contentType" value="text/html;charset=UTF-8"></property>
	</bean>


end