我是个java小白,在近期的开发中,有这样一个任务,拦截请求,统一对请求进行token的验证,由于特殊原因,工程全部采用post请求。想到的就是拦截器、Filter、aop。
由于要求尽量使用spring组件,所以排除Filter,由于工程的URL没有统一规范,所以aop也排除,最后使用了拦截器,在使用的过程中会出现Required request body is missing错误,经过查找资料发现是request body中获取参数时使用流获取,但是request的流只能使用一次,给出的办法就是在获取流之前对流进行复制。具体实现见下面代码。
1:首先自定义一个类继承HttpServletRequestWrapper,用来备份流
public class BufferedServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] buffer;
public BufferedServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
InputStream is = ();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buff[] = new byte[1024];
int read;
while ((read = (buff)) > 0) {
(buff, 0, read);
}
= ();
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new BufferedServletInputStream();
}
// 对外提供读取流的方法
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}
2:在spring配置文件中自定义拦截器组件
<mvc:interceptors>
<!-- token校验 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="类的全路径">
<property name="excludeMapping">
<list>
<value>/doctorWebLoginAccount/doctorLogin/app</value>
<value>/doctorWebLoginAccount/doctorLogin/web</value>
<value>/ws</value>
<value>/fileUpload/uploadPicture</value>
<value>/fileUpload/uploadSignature</value>
<value>/doctor/registe</value>
<value>/hospitalAndDepartment/findHospital</value>
<value>/hospitalAndDepartment/findDepartment</value>
<value>/hospDoctorTreatment/usageSelect</value>
<value>/chiefComplaint/symptom</value>
<value>/initialDiagnose/list</value>
<value>/doctor/patientInfo</value>
<value>/doctor/updateAccountInfo</value>
<value>/doctor/getMessageCode</value>
<value>/doctor/storeBaseInfo</value>
<value>/doctor/storeBaseGoods/list</value>
<value>/doctor/checkPhoneNum</value>
<value>/storeBaseGoods/pageList</value>
</list>
</property>
</bean>
</mvc:interceptor>
</mvc:interceptors>
3:定义拦截的实现类
public class ValidateTokenInterceptor implements HandlerInterceptor{
//不拦截的请求
private String[] excludeMapping;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//不需要过滤的请求
for(String exclude : excludeMapping){
if(().endsWith(exclude)){
return true;
}
}
BufferedServletRequestWrapper requestWrapper = new BufferedServletRequestWrapper(request);
//在这边替换流,使用工具类GetRequestJsonUtils获取json参数
JSONObject json = (requestWrapper);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
("返回视图之前!");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
("请求结束之后!");
}
public void setExcludeMapping(String[] excludeMapping) {
= excludeMapping;
}
}
4:最后自定义一个Filter(spring请求的链式执行顺序为Filter-->拦截器-->controller)用来备份流
public class TranslateRequestWrapper implements Filter{
/**
* 销毁
*/
@Override
public void destroy() {
}
/**
* 过滤
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ServletRequest requestWrapepr = null;
if(request instanceof HttpServletRequest){
requestWrapepr = new BufferedServletRequestWrapper((HttpServletRequest)request);
}
if(requestWrapepr == null){
(request, response);
}else{
(requestWrapepr, response);
}
}
/**
* 初始化
*/
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
5:附上从流中读取参数的工具类
public class GetRequestJsonUtils {
public static JSONObject getRequestJsonObject(HttpServletRequest request) throws IOException {
String json = getRequestJsonString(request);
return (json);
}
/***
* 获取 request 中 json 字符串的内容
*
* @param request
* @return : <code>byte[]</code>
* @throws IOException
*/
public static String getRequestJsonString(HttpServletRequest request)
throws IOException {
String submitMehtod = ();
// GET
if (("GET")) {
if((())){
return new String(().getBytes("iso-8859-1"),"utf-8").replaceAll("%22", "\"");
}else{
return new String("".getBytes("iso-8859-1"), "utf-8").replaceAll("%22", "\"");
}
// POST
} else {
return getRequestPostStr(request);
}
}
/**
* 描述:获取 post 请求的 byte[] 数组
* <pre>
* 举例:
* </pre>
* @param request
* @return
* @throws IOException
*/
public static byte[] getRequestPostBytes(HttpServletRequest request)
throws IOException {
int contentLength = ();
if(contentLength<0){
return null;
}
byte buffer[] = new byte[contentLength];
for (int i = 0; i < contentLength;) {
int readlen = ().read(buffer, i,
contentLength - i);
if (readlen == -1) {
break;
}
i += readlen;
}
return buffer;
}
/**
* 描述:获取 post 请求内容
* <pre>
* 举例:
* </pre>
* @param request
* @return
* @throws IOException
*/
public static String getRequestPostStr(HttpServletRequest request)
throws IOException {
byte buffer[] = getRequestPostBytes(request);
String charEncoding = ();
if (charEncoding == null) {
charEncoding = "UTF-8";
}
return new String(buffer, charEncoding);
}
}
这样就不会出现request body si missing