• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

如何给HttpServletRequest增加消息头

java 搞代码 4年前 (2022-01-05) 54次浏览 已收录 0个评论
文章目录[隐藏]

这篇文章主要介绍了如何给HttpServletRequest增加消息头的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

HttpServletRequest增加header

由于在请求中请求域的属性在请求转发,路由等过程中,请求域的值会丢失,在项目项目中使用请求头来传递信息,但是HttpRequest并没有实现增加请求头的方法,所以找到他的子类来实现

 class MutableHttpServletRequest extends HttpServletRequestWrapper { // holds custom header and value mapping private final Map customHeaders; public MutableHttpServletRequest(HttpServletRequest request){ super(request); this.customHeaders = new HashMap(); } public void putHeader(String name, String value){ this.customHeaders.put(name, value); } public String getHeader(String name) { // check the custom headers first String headerValue = customHeaders.get(name); if (headerValue != null){ return headerValue; } // else return from into the original wrapped object return ((HttpServletRequest) getRequest()).getHeader(name); } public Enumeration getHeaderNames() { // create a set of the custom header names Set set = new HashSet(customHeaders.keySet()); // now add the headers from the wrapped request object @SuppressWarnings("unchecked") Enumeration e = ((HttpServletRequest) getRequest()).getHeaderNames(); while (e.hasMoreElements()) { // add the names of the request headers into the list String n = e.nextElement(); set.add(n); } // create an enumeration from the set and return return Collections.enumeration(set); } } 

使用:

 public class SecurityFilter implements javax.servlet.Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); ... mutableRequest.putHeader("x-custom-header", "custom value"); chain.doFilter(mutableRequest, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { } }

但是项目来源gao@!dai!ma.com搞$$代^@码!网中我使用的SpringCloud ZUUL中使用这样 的方式失败:

 @Component public class AccessFilter extends ZuulFilter { private  Logger log = LoggerFactory.getLogger(AccessFilter.class); @Autowired private VerificationHelper helper; private  BufferedReader reader=null; @Autowired private KeyAndFrequencyService service; @Autowired private ZuulTest zuulTest; @Autowired private PermissionHandler permissionHandler; @Override public String filterType() { //前置过滤器 return "pre"; } @Override public int filterOrder() { //优先级,数字越大,优先级越低 return 0; } @Override public boolean shouldFilter() { //是否执行该过滤器,true代表需要过滤 return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); try { permissionHandler.setTokenExpireTime(200000000); String type = request.getHeader("type"); zuulTest.say(); System.out.println("......................................................"); if (type == null) { System.out.println("......................................................验证1"); Object object = helper.AccessZuul(request, ctx); return object; } else { System.out.println("......................................................验证2"); PermissionResult result=permissionHandler.check(request); System.out.println(result); if(result.isState()){ MutableHttpServletRequest  mutRequest=new MutableHttpServletRequest (request); //增加头部信息 DasAccountInfo accountInfo= permissionHandler.GetDasAccountInfoById(Integer.parseInt(result.getUserId())); mutRequest.putHeader("dasAccountInfo", JSON.toJSONString(disablePropertyName()))                   ;RequestContext.getCurrentContext().setRequest(mutRequest); ctx.setSendZuulResponse(true);// 对该请求进行路由 ctx.setResponseStatusCode(200); ctx.set("isSuccess", true); }else{ ctx.setSendZuulResponse(false);// 过滤该请求,不对其进行路由 ctx.setResponseStatusCode(401);// 返回错误码 ctx.setResponseBody("{\"code\":0,\"result\":\"网关验证失败!验证方式为2\"}");// 返回错误内容 ctx.set("isSuccess", false); } } }catch (Exception e){ e.printStackTrace(); log.error("网关报错!!!",e.fillInStackTrace()); } return null; } 

使用zuul网关的自带的设置请求头的方法,在网关中设置的请求头可以被路由下面的服务获取到:

 ctx.getZuulRequestHeaders().put("dasAccountInfo", JSON.toJSONString(disablePropertyName()));

修改HttpServletRequest中header的信息

废话一堆:由于业务有统一的鉴权系统,页面请求时在header中带过来gsid,正常业务没有问题,但是当需要下载文件时,前端统一用json解析响应,当响应文件时,对于前端来说不好处理,就决定使用简单的get请求下载文件,将gsid通过url带过来,这样的话后端鉴权就需要处理,当header中没有gsid时,从参数中取,为了尽可能少的改变公用的业务代码(指sso),就在当前项目中自定义权限拦截器。

总结一句,我就是想想header中加东西!!往下看具体实现方式:

新建拦截器类,继承原有的拦截器,重写其preHandle方法

 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception { String gsid = request.getHeader("GSID"); if(StringUtils.isBlank(gsid)){ String gsid= request.getParameter("GSID"); //使用反射,将gsid设置到request中的的header中去 reflectSetparam(request,"GSID",gsid); log.info("请求连接中的gsid={}",request.getHeader("GSID")); } return super.preHandle(request, response, o); } 

说明:可以看到在方法中,

1、先进行header信息判断,如果header中没有GSID,就去请求参数中拿

 gsid= request.getParameter("GSID");

2、通过反射将参数中的GSID键值对儿:“GSID”:“376645354562335”加入到header中去

话不多少,先上代码,再解释:

解释:

 /** * 修改header信息,key-value键值对儿加入到header中 * @param request * @param key * @param value */ private void reflectSetparam(HttpServletRequest request,String key,String value){ Class requestClass = request.getClass(); System.out.println("request实现类="+requestClass.getName()); 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); System.out.println("coyoteRequest实现类="+o1.getClass().getName()); Field headers = o1.getClass().getDeclaredField("headers"); headers.setAccessible(true); MimeHeaders o2 = (MimeHeaders)headers.get(o1); o2.addValue(key).setString(value); } catch (Exception e) { e.printStackTrace(); } } 

执行打印信息如下:

request实现类=org.apache.catalina.connector.RequestFacade

coyoteRequest实现类=org.apache.coyote.Request

看HttpServletRequest的源码,是个接口,并且我们获取header信息的方法是getHeader()方法,按常理其对象中应该有header字段,那么我们就去实现类中找这个字段,具体过程如下

步骤一:先找到具体的Request对象是哪个类,根据打印信息看源码

进入其中找到getHeader()方法,如下

 public String getHeader(String name) { if (this.request == null) { throw new IllegalStateException(sm.getString("requestFacade.nullRequest")); } else { return this.request.getHeader(name); } } 

然后我们找this.request

这个request,我们找到它的类型,点击去

这个类的全路径是:org.apache.catalina.connector.Request

这个类中找getHeader方法

 public String getHeader(String name) { return this.coyoteRequest.getHeader(name); }

找到这个类中的coyoteRequest

 protected org.apache.coyote.Request coyoteRequest;

是这样的

再找到getHeader()

 public String getHeader(String name) { return this.headers.getHeader(name); }

好了,终于见到属性了

 private final MimeHeaders headers = new MimeHeaders();

找到MineHeaders中的getHeader方法,

 public String getHeader(String name) { MessageBytes mh = this.getValue(name); return mh != null ? mh.toString() : null; }

看到最终header是一个MessageBytes对象,好找到这个对象进去,发现只能setValue,那就在MineHeaders中找在哪里实例化MessageBytes对象的

找了半天找到在createHeader()方法中实例化MimeHeaderField对象,然后这个对象实例化时会实例化MessageBytes对象

这里有name,value,靠谱

然后再在MimeHeader中找在addValue方法中有调用,就用这个试一下吧,然后就是最上面的我自定义的方法,在heade中加入了一个键值对儿。

测试请求:

http://127.0.0.1:32100/v1/CustomerRefundRest/exportRefund?gsid=abc114f1bd0d484084e5df3fe1c419b8&refundLongStartDate=1520611199000&refundLongEndDate=1522943999000

测试打印结果:

OVER!以上为个人经验,希望能给大家一个参考,也希望大家多多支持gaodaima搞代码网

以上就是如何给HttpServletRequest增加消息头的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:如何给HttpServletRequest增加消息头

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址