1、要被拦截的Controller接口
我们需要一个更新用户信息接口,请求方式为POST,参数类型为对象类型(UserInfo),代码如下:
privateUserServiceuserService; /*** 更新用户信息** @param request* @param userInfo* @return*/value="/updateUserInfo", produces="application/json;charset=UTF-8", (method=RequestMethod.POST) publicJSONObjectupdateUserInfo(HttpServletRequestrequest, UserInfouserInfo) { ... userService.updateUserInfo(userInfo); ... }
2、拦截器
我们要在拦截器中拦截该接口,并获取其请求参数UserInfo对象。
如果只是获取普通的请求对象(eg:用户ID -> userId),我们可以直接在拦截器中,通过如下代码即可获取request请求体中的参数数据:
publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecto) { ...... // user ID为string类型,所以可以直接拿到数据,// 但是如果参数是对象类型/JSON类型数据,则无法通过这种方式获取!StringuserId=request.getParameter("userId"); ..... }
3、HttpServletRequestWrapper解决这一问题
在拦截器中写一个内部类 RequestWrapper ,让其继承 HttpServletRequestWrapper:
classRequestWrapperextendsHttpServletRequestWrapper {
RequestWrapper 重写父类方法,最终完整的拦截器代码如下:
/*** 拦截器: ** @author csp* @date 2022-01-06 15:36:41*/publicclassUserInterceptorimplementsHandlerInterceptor { privatefinalstaticLoggerlogger=LoggerFactory.getLogger(UserInterceptor.class); privateUserServiceuserService; /*** 前置拦截** @param request* @param response* @param o* @return* @throws Exception*/publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecto) throwsException { // 从request请求体中拿到body中的JSON对象参数RequestWrapperrequestWrapper=newRequestWrapper(request); StringjsonBody=requestWrapper.getBody(); UserInfouserInfo=JSONObject.toJavaObject(JSONObject.parseObject(jsonBody), UserInfo.class); // 根据userInfo校验是否具备权限BooleanisAuth=userService.getAuthByUserInfo(userInfo); if (!isAuth) { // response响应给浏览器无权限,代码略 ... returnfalse; } returntrue; } publicvoidpostHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecto, ModelAndViewmodelAndView) throwsException {} publicvoidafterCompletion(HttpServletRequestrequest, HttpServletResponseresponse, Objecto, Exceptione) throwsException {} // RequestWrapper 内部类classRequestWrapperextendsHttpServletRequestWrapper { privatefinalStringbody; publicRequestWrapper(HttpServletRequestrequest) { super(request); StringBuilderstringBuilder=newStringBuilder(); BufferedReaderbufferedReader=null; InputStreaminputStream=null; try { inputStream=request.getInputStream(); if (inputStream!=null) { bufferedReader=newBufferedReader(newInputStreamReader(inputStream)); char[] charBuffer=newchar[128]; intbytesRead=-1; while ((bytesRead=bufferedReader.read(charBuffer)) >0) { stringBuilder.append(charBuffer, 0, bytesRead); } } else { stringBuilder.append(""); } } catch (IOExceptionex) { } finally { if (inputStream!=null) { try { inputStream.close(); } catch (IOExceptione) { e.printStackTrace(); } } if (bufferedReader!=null) { try { bufferedReader.close(); } catch (IOExceptione) { e.printStackTrace(); } } } body=stringBuilder.toString(); } publicServletInputStreamgetInputStream() throwsIOException { finalByteArrayInputStreambyteArrayInputStream=newByteArrayInputStream(body.getBytes()); ServletInputStreamservletInputStream=newServletInputStream() { publicbooleanisFinished() { returnfalse; } publicbooleanisReady() { returnfalse; } publicvoidsetReadListener(ReadListenerreadListener) { } publicintread() throwsIOException { returnbyteArrayInputStream.read(); } }; returnservletInputStream; } publicBufferedReadergetReader() throwsIOException { returnnewBufferedReader(newInputStreamReader(this.getInputStream())); } publicStringgetBody() { returnthis.body; } } }
这样,就可以在拦截器中,拦截request请求,并获取request请求体中的json/对象类型的参数啦!