英文:
Edit values of object with Interceptor before the controller
问题
有没有选项在请求传递到控制器之前使用拦截器编辑值?
我尝试包装HttpServletRequest并设置新的body。
在控制器中有一个如下所示的Post请求:
@PostMapping("/edit-via-interceptor")
public MyObject getNewObjectFromInterceptor(@RequestBody MyObject myObject){
return myObject;
}
对象看起来像这样:
@Data
public class MyObject implements Serializable {
private List<String> ids;
}
RequestBody中有一个ids列表,我想在拦截器中向当前列表添加2个默认的id。
拦截器看起来像这样:
@Component
public class Interceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpServletRequest httpRequest = request;
CustomHttpServletRequestWrapper wrapper = new CustomHttpServletRequestWrapper(httpRequest);
ObjectMapper objectMapper = new ObjectMapper();
MyObject newMyObject = objectMapper.readValue(wrapper.getInputStream(), MyObject.class);
List<String> newIdsList = newMyObject.getIds();
newIdsList.add("123");
newIdsList.add("1234");
newMyObject.setIds(newIdsList);
byte[] data = SerializationUtils.serialize(newMyObject);
wrapper.setBody(data);
return super.preHandle(wrapper, response, handler);
}
}
CustomHttpServletRequestWrapper看起来像这样:
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
try {
body = IOUtils.toByteArray(request.getInputStream());
} catch (IOException ex) {
body = new byte[0];
}
}
public void setBody(byte[] body){
this.body = body;
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream() {
ByteArrayInputStream bais = new ByteArrayInputStream(body);
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
}
}
拦截器模式的配置:
@Configuration
public class AuthConfig implements WebMvcConfigurer {
@Autowired
private Interceptor controllerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// The registration of /api/** must be in the end
registry.addInterceptor(controllerInterceptor).addPathPatterns("/**");
}
}
在所有这些之后,当到达控制器时,MyObject为null。
英文:
there any option to edit values with Interceptor before the request goes to the controller?
I tried to wrap the HttpServletRequest and set the new body.
I have Post request in controller that looks like this :
@PostMapping("/edit-via-interceptor")
public MyObject getNewObjectFromInterceptor(@RequestBody MyObject myObject){
return myObject;}
The Object looks like this:
@Data
public class MyObject implements Serializable {
private List<String> ids;
}
The RequestBody has List of ids, and I want to add inside the interceptor 2 default id's to the current list.
The Interceptor looks like this:
@Component
public class Interceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpServletRequest httpRequest = request;
CustomHttpServletRequestWrapper wrapper = new CustomHttpServletRequestWrapper(httpRequest);
ObjectMapper objectMapper = new ObjectMapper();
MyObject newMyObject = objectMapper.readValue(wrapper.getInputStream(), MyObject.class);
List<String> newIdsList = newMyObject.getIds();
newIdsList.add("123");
newIdsList.add("1234");
newMyObject.setIds(newIdsList);
byte[] data = SerializationUtils.serialize(newMyObject);
wrapper.setBody(data);
return super.preHandle(wrapper, response, handler);
}
}
CustomHttpServletRequestWrapper looks like this:
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
try {
body = IOUtils.toByteArray(request.getInputStream());
} catch (IOException ex) {
body = new byte[0];
}
}
public void setBody(byte[] body){
this.body = body;
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream() {
ByteArrayInputStream bais = new ByteArrayInputStream(body);
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
}
}
The configuration on Interceptor pattern :
@Configuration
public class AuthConfig implements WebMvcConfigurer {
@Autowired
private Interceptor controllerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// The registration of /api/** must be in the end
registry.addInterceptor(controllerInterceptor).addPathPatterns("/**");
}
After all that, When its comes to the Controller - MyObject is null.
答案1
得分: 3
我使用@Around
注解进行了相同的操作。这是文档6.2.4.5. Around advice(在访问链接后需要搜索 @around)。您可以修改请求和响应。
还有@Before
和@After
建议,如果需要的话,您也可以使用。如果您只需要在控制器调用之前访问对象,@Before
应该足够了。
@Aspect
@Component
public class RequestModifierAspect {
@Around("execution(* com.example.YourController.methodName(..))")
public Object modifyRequest(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
// 在这里修改请求对象
// 例如,更改参数值
request.setParameter("yourParam", "newValue");
// 使用修改后的请求继续
Object result = joinPoint.proceed();
// 如果需要,您还可以修改控制器方法返回的结果
return result;
}
}
英文:
I did the same using @Arround
annotation. Here is the doc 6.2.4.5. Around advice (You need to search @around after going to the link). You can modify both the request and response.
There is also @Before
and @After
advice you can use if required. If you only need to access the object BEFORE controller is invoked, @Before
should be enough.
@Aspect
@Component
public class RequestModifierAspect {
@Around("execution(* com.example.YourController.methodName(..))")
public Object modifyRequest(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
// Modify the request object here
// For example, change a parameter value
request.setParameter("yourParam", "newValue");
// Proceed with the modified request
Object result = joinPoint.proceed();
// You can also modify the result returned by the controller method if needed
return result;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论