springboot HandlerIntercepter Interceptor's Operation to Modify request body Data
- 2021-10-13 07:32:30
- OfStack
Learning technology in practical work is the fastest and most profound. Of course, it is necessary to have a sense of continuous learning
Technology stack version:
spring boot 2.0.2
Something happened
Recently, doing business needs, front-end classmate fe will
userId
And
userName
Put
request header
Won.
If you want to use the back-end api interface,
userId
And
userName
Each interface is derived from the
header
Gets from the.
Imagine 1. If you have 10 interfaces, you have to write each interface once.
Object.setUserId(request.getHeader("userId"))
As in the following code snippet
@RestController
@Validated
@RequestMapping("/template")
public class TemplateController {
// 1 A feign client
@Autowired
TemplateClient templateClient
@PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE)
public ResultVO create(@RequestBody @Valid TemplateParam param, HttpServletRequest request) {
// Every interface must write 1 Pass setXXX() Method
param.setUserId(request.getHeader("userId"));
param.setUserName(request.getHeader("userName"));
return templateClient.createTemplate(param).toResultVO();
}
}
@Data
public class TemplateParam{
private Long templateId;
private Long userId;
private String userName;
}
Solution
Two sharp weapons that everyone knows,
tomcat
Adj.
Filter
And
spring
Adj.
Intercepter
(Specifically,
userName
0
)
Implementation principle
The specific method is to define 1
Filter
Implementation class and 1
userName
0
Gets or sets the implementation class of. Define another 1
userName
3
Implementation classes, whose functions are
Filter Implementation Class: UserInfoFilter
Create an entry and define an opportunity in this entry: put our custom
userName
4
Substitute
userName
3
As the request passes on,
HttpServletRequest Implementation Class: customHttpServletRequestWrapper
Because
userName
3
Object's
userName
7
Data can only
userName
8
, can't
userName
9
That is, you cannot assign a value again.
And what we need is to give
userName
3
Assignment, so you need to define 1
userName
3
Implementation class:
request header
2
This implementation class can be assigned to meet our needs.
Implementation Class for HandlerIntercepter: CustomInterceptor
Intercept requests and obtain information about interface methods (method names, parameters, return values, etc.). Thereby realizing the giving of unification 1
request header
3
Dynamic assignment
As mentioned above, the specific implementation code is as follows
Code implementation
Declaration basis
request header
4
:
request header
5
request header
5
: Defines the contents of the
userId
,
userName
Entity bean, if you want to inject user information into it, you need to enter the parameter object
request header
9
Inheritance
request header
5
In the interceptor, only processing
userId
1
Is implemented in
request header
5
Class
request header
4
.
As above
controller
Medium
create
Input parameters of method:
TemplateParam
, inheritance
request header
5
@Data
public class TemplateParam extends UserInfoParam{
private Long templateId;
// private Long userId;
// private String userName;
}
@Data
public class UserInfoParam {
// Users id
private Long userId;
// User name
private String userName;
}
Define the Filter implementation class:
UserInfoFilter
@Slf4j
public class UserInfoFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
CustomHttpServletRequestWrapper customHttpServletRequestWrapper = null;
try {
HttpServletRequest req = (HttpServletRequest)request;
customHttpServletRequestWrapper = new CustomHttpServletRequestWrapper(req);
}catch (Exception e){
log.warn("customHttpServletRequestWrapper Error:", e);
}
chain.doFilter((Objects.isNull(customHttpServletRequestWrapper) ? request : customHttpServletRequestWrapper), response);
}
}
userName
3
Implementation class:
userName
4
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
// Save request body Data of
private String body;
// Analyse request Adj. inputStream( I.e. body) Data, turned into a string
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
// Assign a value to body Field
public void setBody(String body) {
this.body = body;
}
}
userName
0
The implementation class of:
CustomInterceptor
@Slf4j
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod)handler;
pushUserInfo2Body(request, handlerMethod);
return true;
}
private void pushUserInfo2Body(HttpServletRequest request, HandlerMethod handlerMethod) {
try{
String userId = request.getHeader("userId");
String userName = request.getHeader("userName");
MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
if(ArrayUtils.isEmpty(methodParameters)) {
return;
}
for (MethodParameter methodParameter : methodParameters) {
Class clazz = methodParameter.getParameterType();
if(ClassUtils.isAssignable(UserInfoParam.class, clazz)){
if(request instanceof CustomHttpServletRequestWrapper){
CustomHttpServletRequestWrapper requestWrapper = (CustomHttpServletRequestWrapper)request;
String body = requestWrapper.getBody();
JSONObject param = JSONObject.parseObject(body);
param.put("userId", userId);
param.put("userName", Objects.isNull(userName) ? null : URLDecoder.decode(userName, "UTF-8"));
requestWrapper.setBody(JSON.toJSONString(param));
}
}
}
}catch (Exception e){
log.warn("fill userInfo to request body Error ", e);
}
}
Definition
Configuration class
Increase the configuration of interceptors and filters
WebMvcConfigurer
Subclass:
CustomWebMvcConfigurer
@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
CustomInterceptor customInterceptor= new CustomInterceptor();
registry.addInterceptor(customInterceptor);
}
@Bean
public FilterRegistrationBean servletRegistrationBean() {
UserInfoFilter userInfoFilter = new UserInfoFilter();
FilterRegistrationBean<UserInfoFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(userInfoFilter);
bean.setName("userInfoFilter");
bean.addUrlPatterns("/*");
bean.setOrder(Ordered.LOWEST_PRECEDENCE);
return bean;
}
}
At this point, the code for realizing the function is finished. Start
spring boot App
, you can
curl
Visit
restful
Interface
http Access
curl -X POST \
http://localhost:8080/template/create
-H 'Content-Type: application/json'
-H 'username: tiankong Sky '
-H 'userId: 11'
-d '{
"templateId": 1000}
Effect
You can see
TemplateController.create(…)
The typed message,
userId
And
header
1
The value of is exactly
header
Value passed in
toDo