由于业务需要,在网上找了很久得到了这两种方式。本文代码偏少,主要讲解一下怎么传,如何接收,也记录一下,以便之后查看。
下面是我拦截器中的代码,preHandle中设置变量,然后在controller中得到
1,变量放在request请求域中,request.setAttribute(“getAttribute”, “getAttribute”);
2,变量放在全局Servlet Context中,request.getServletContext().setAttribute(“getServletContext”, “getServletContext”);
3,变量放在request的请求头中,在controller中在到请求头header中得到数据
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws RRException {
//把变量放在request请求域中,仅可以被这次请求,即同一个requerst使用
request.setAttribute("getAttribute", "getAttribute");
//放在全局的ServletContext中,每一个web应用拥有一个ServletContext,是全局对象,具体请百度
//把变量放在这里面,在之后什么地方都可以访问
request.getServletContext().setAttribute("getServletContext", "getServletContext");
//把自己的变量放在头部
reflectSetHeader(request, "header", "header");
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器之后输出ServletContext中保存的数据:"+request.getServletContext().getAttribute("getServletContext"));
}
//把自己想要的信息设置到header头部,就相当于是在request的请求头部添加一个键值对,保存自己的数据
private void reflectSetHeader(HttpServletRequest request, String key, String value){
Class extends HttpServletRequest> requestClass = request.getClass();
try {
Field request1 = requestClass.getDeclaredField("request");
request1.setAccessible(true);
Object o = request1.get(request);
Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
coyoteRequest.setAccessible(true);
Object o1 = coyoteRequest.get(o);
Field headers = o1.getClass().getDeclaredField("headers");
headers.setAccessible(true);
MimeHeaders o2 = (MimeHeaders)headers.get(o1);
o2.removeHeader(key);
o2.addValue(key).setString(value);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
下面是我controller中的代码
@GetMapping("/hello")
public Result hello( String hello){
System.out.println(hello);
//得到头部保存的信息
System.out.println(getHeadToken((ServletRequestAttributes) RequestContextHolder.getRequestAttributes(), "header"));
//得到servlet中的request
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
System.out.println("request.getAttribute得到数据:"+request.getAttribute("getAttribute"));
System.out.println("request.getServletContext().getAttribute得到全局数据:"+request.getServletContext().getAttribute("getServletContext"));
return null;
}
public static String getHeadToken(ServletRequestAttributes attributes, String key) {
/**
*
* 功能描述: 得到头部保存的信息,通过key得到value
*
* @param: [attributes, key] attribute 固定(ServletRequestAttributes) RequestContextHolder.getRequestAttributes() key:为头部保存信息的键子key
* @return: java.lang.String
*/
HttpServletRequest request = attributes.getRequest();
Map map = new HashMap();
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key1 = (String) headerNames.nextElement();
String value = request.getHeader(key1);
map.put(key1, value);
}
return map.get(key);
}
看控制台输出,第一个 null,因为controller方法上没有参数传过来
后面的都是从拦截器那边传过来的数据。于是,最后需求实现。
切面中的环绕方法,实现切面传递参数到目标方法。
Object o[] = proceedingJoinPoint.getArgs();这句代码就是得到从前端(保存在request中的变量的值)传递到controller中的值。
比如request请求,get方式, http://www.qinjie.xyz/hello?a=1&b=2&c=3;
我controller目标方法接收a,b,c,d,e,f这6个变量值,则上面方法得到的o[]={1,2,3,null,null,null}。有兴趣可以自己测试一下试试。然后我在环绕方法执行目标方法之前替换d = 4,这在controller中就可以接收到a=1,b=2,c=3,d=4,e=null,f=null。
同理,我也可以替换掉a=11,b=22,在controller中就是a=11,b=22 了。
我把关键性代码贴出来。
@Around(value = "InterceptController()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
//得到传递给目标方法的参数值
Object o[] = proceedingJoinPoint.getArgs();
//得到目标方法的参数名,得到controller(目标方法)的变量的名字
String[] paramNames = ((CodeSignature) proceedingJoinPoint
.getSignature()).getParameterNames();
}
return proceedingJoinPoint.proceed(o);//返回执行目标方法,并且把转换修改后的参数值传递到controller(目标方法)
}