5修改request对象变量

您所在的位置:网站首页 java反射的原理是什么 5修改request对象变量

5修改request对象变量

2023-04-03 12:14| 来源: 网络整理| 查看: 265

1、什么是反射?我们在学Java的过程中一定会遇到Java反射,不管是我们常用的框架,还是面试官的问题。多多少少都会牵扯到。那么什么才是反射?很抽象的一个概念!!没有之一,反射的功能很强大,范围很广泛,所以说它不是一句话能概括的了的。我理解反射就是:在程序运行期间,我们通过一系列操作去获取到对象所有信息(如:类、方法、成员变量等等)的操作。(感觉这样定义,把反射说的很狭义)2、反射应用日常业务开发很少会用到反射。但是涉及到通用模块、框架开发等肯定会涉及到反射的应用。如我们配置数据源时通常配置的数据库驱动、Spring配置文件注入Bean时,都是通过反射来实现。3、经典案例:我们通过反射,修改HttpServletRequest的Header值(Tomcat)我们知道在Java中HttpServletRequest是一个接口,具体实现是由服务器去实现对应类。这里选择的是Tomcat,如果更换服务器,这个代码是不适用的。先把全部代码贴出来:

/** * 修改request请求头信息,只适用于Tomcat * @param servletRequest request * @param headerKey 修改HeaderKey * @param headerValue 修改HeaderValue */ private int modifyHeader(HttpServletRequest servletRequest, String headerKey, String headerValue){ try { logger.info("HttpServletRequest implement class is {}", servletRequest.getClass().getName()); //获取org.apache.catalina.connector.RequestFacade类中request字段 Field requestField = servletRequest.getClass().getDeclaredField("request"); //设置字段跳过安全检查 requestField.setAccessible(true); //获取javax.servlet.http.HttpServletRequest实现类中request字段对象:org.apache.catalina.connector.Request Object requestObject = requestField.get(servletRequest); logger.info("RequestFacade class filed request implement class is {}.", requestObject.getClass().getName()); //获取org.apache.catalina.connector.Request类中coyoteRequest字段 Field coyoteRequestField = requestObject.getClass().getDeclaredField("coyoteRequest"); //设置字段跳过安全检查 coyoteRequestField.setAccessible(true); //获取org.apache.catalina.connector.Request实现类中coyoteRequest字段对象:org.apache.catalina.connector.Request.coyoteRequest Object coyoteRequestObject = coyoteRequestField.get(requestObject); logger.info("org.apache.coyote.Request class filed coyoteRequest implement class is {}", coyoteRequestObject.getClass().getName()); //获取org.apache.catalina.connector.Request.coyoteRequest类中headers字段 Field headersField = coyoteRequestObject.getClass().getDeclaredField("headers"); //设置字段跳过安全检查 headersField.setAccessible(true); //获取org.apache.catalina.connector.Request.coyoteRequest实现类中headers字段对象实现:org.apache.tomcat.util.http.MimeHeaders Object headersObject = headersField.get(coyoteRequestObject); //确定字段类型为:org.apache.tomcat.util.http.MimeHeaders if(headersObject instanceof MimeHeaders){ //使用MimeHeaders类方法设置Header值 MimeHeaders headers = (MimeHeaders) headersObject; //addValue只添加,setValue会遍历查找,如果不存在此Header再添加// headers.addValue(headerKey).setString(headerValue); headers.setValue(headerKey).setString(headerValue); logger.info("update request Headers success:{}", servletRequest.getHeader(headerKey)); } }catch (Exception e){ logger.error("Update Request Headers Exception; {}", e.getMessage(), e); return 1; } return 0; }

解析:

我们通过getClass().getName()知道Tomcat对HttpServletRequest的实现类是:org.apache.catalina.connector.RequestFacade。查看RequestFacade类getHeader()方法的实现和调用流程如下:

e8c542734214c58eca89d9edeb60ed5e.pngorg.apache.catalina.connector.RequestFacade#getHeader方法调用的是org.apache.catalina.connector.Request#getHeader方法:

…… /** * The wrapped request. */ protected Request request = null; …… @Override public String getHeader(String name) { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } return request.getHeader(name); } ……

e8c542734214c58eca89d9edeb60ed5e.pngorg.apache.catalina.connector.Request#getHeader方法调用的是org.apache.coyote.Request#getHeader方法:

…… /** * Coyote request. */ protected org.apache.coyote.Request coyoteRequest; @Override public String getHeader(String name) { return coyoteRequest.getHeader(name); } ……

e8c542734214c58eca89d9edeb60ed5e.pngorg.apache.coyote.Request#getHeader方法调用的是org.apache.tomcat.util.http.MimeHeaders#getHeader方法:

…… private final MimeHeaders headers = new MimeHeaders(); public String getHeader(String name) { return headers.getHeader(name); } ……

e8c542734214c58eca89d9edeb60ed5e.png在org.apache.tomcat.util.http.MimeHeaders#getHeader中我们可以看到Header的键值对是从org.apache.tomcat.util.http.MimeHeaderField中遍历获取。

/** * The header fields. */ private MimeHeaderField[] headers = new MimeHeaderField[DEFAULT_HEADER_SIZE]; public String getHeader(String name) { MessageBytes mh = getValue(name); return mh != null ? mh.toString() : null; } public MessageBytes getValue(String name) { for (int i = 0; i

e8c542734214c58eca89d9edeb60ed5e.png且在org.apache.tomcat.util.http.MimeHeaders中,我们看到此类提供了org.apache.tomcat.util.http.MimeHeaders#setValue方法返回org.apache.tomcat.util.buf.MessageBytes类,且在org.apache.tomcat.util.buf.MessageBytes中存在org.apache.tomcat.util.buf.MessageBytes#setString方法。所以我们可以通过反射,获取到org.apache.tomcat.util.http.MimeHeaders对象,然后使用MimeHeaders对象的setValue方法进行设置Header值。

完毕!!!

面试总结题目——Redis部分

面试总结—Mysql-01

面试总结—Mysql02—索引、数据库引擎、乐观锁

面试总结—Java01_Jdk7和Jdk8区别

面试总结—Java02

欢迎点赞:我的博客

354088cb4c52213d254999c2245d20f0.png



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3