私は、Springブートサービスが受け取るすべてのJSON要求ペイロードをデコードするために、Base64
を要求しています。 HTTP POST
メソッドを使用して転記する前に、クライアントでJSONペイロードがBase64
にエンコードされている可能性があります。さらに、私はBase64
を呼び出すクライアントアプリケーションに提示する前にJSON応答をエンコードする必要があります。SpringブートでHttpServletResponseをインターセプトして操作できません
ハンドラインターセプタを使用して定型コードを減らす必要があります。 私はすでにインターセプタを使用して操作の要求/受信レッグを達成しましたが、レスポンスレッグのためにこれをまだ達成していません。 以下にコードスニペットを掲載しました。レスポンスを代行受信してbase64でエンコードするコードは、インターセプタクラスのpostHandleメソッドにあります。
私はここで間違っていますか?
インターセプタクラス:上記で使用
public class Base64ResponseEncodingInterceptor implements HandlerInterceptor {
private static final String DECODED_REQUEST_ATTRIB = "decodedRequest";
private static final String POST = "POST";
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView arg3) throws Exception {
try {
if (POST.equalsIgnoreCase(request.getMethod())) {
CharResponseWrapper res = new CharResponseWrapper(response);
res.getWriter();
byte[] encoded = Base64.encodeBase64(res.toString().getBytes());
byte[] encoded = Base64.encodeBase64(response.getHeader(ENCODED_RESPONSE_ATTRIB).getBytes());
response.getWriter().write(new String(encoded));
}
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
// preHandle and afterCompletion methods
// Omitted
}
CharResponseWrapper
クラス:インターセプタが使用され
@Configuration
@EnableJpaRepositories(repositoryBaseClass = BaseRepositoryBean.class, basePackages = "")
@EntityScan(basePackages = { "com.companyname", "com.companyname.productname"})
public class RestConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Base64ResponseEncodingInterceptor());
}
}
ザ・コントローラクラス、:インターセプタが登録されて
public class CharResponseWrapper extends HttpServletResponseWrapper {
protected CharArrayWriter charWriter;
protected PrintWriter writer;
protected boolean getOutputStreamCalled;
protected boolean getWriterCalled;
public CharResponseWrapper(HttpServletResponse response) {
super(response);
charWriter = new CharArrayWriter();
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (getWriterCalled) {
throw new IllegalStateException("getWriter already called");
}
getOutputStreamCalled = true;
return super.getOutputStream();
}
@Override
public PrintWriter getWriter() throws IOException {
if (writer != null) {
return writer;
}
if (getOutputStreamCalled) {
throw new IllegalStateException("getOutputStream already called");
}
getWriterCalled = true;
writer = new PrintWriter(charWriter);
return writer;
}
@Override
public String toString() {
String s = null;
if (writer != null) {
s = charWriter.toString();
}
return s;
}
}
JavaConfigクラス(ここでは作業要求レッグのみ表示しています):
@Autowired
HttpServletRequest request;
String decodedRequest = null;
@ModelAttribute("decodedRequest")
public void getDecodedParam(){
decodedRequest = (String) request.getAttribute("decodedRequest");
}
postHandle
メソッドのコードは機能しません。それはどちらかHttpServletResponse
がnull
であるか、私は例外メッセージを取得:
のgetOutputStreamすでに
アップデートと呼ばれる:コントローラクラスでResponseBodyAdvice に直接応答を読み込むにソリューション回避策、私は以下を追加しました:
@RestController
@RequestMapping("/api/ipmanager")
public class IPProfileRestController extends AbstractRestController {
@Autowired
HttpServletResponse response;
String encodedResponse = null;
@ModelAttribute("encodedResponse")
public void getEncodedResponse(){
response.setHeader("encodedResponse", StringUtils.EMPTY);
}
@RequestMapping(value = "/time", method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE }, consumes = {
MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody String saveAccessClientTime(@RequestBody String ecodedRequest) {
// Some code here
String controllerResponse = prettyJson(iPProfileResponse);
response.setHeader("encodedResponse", controllerResponse);
return controllerResponse;
}
}
私はResponseBodyAdvice Spring MVC documentation状態として
@ControllerAdvice
public class Base64EncodedResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType,
Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> converterType,
ServerHttpRequest request,
ServerHttpResponse response) {
String body1 = StringUtils.EMPTY;
// Encode the response and return
List<String> listOfHeaderValues = response.getHeaders().get("encodedResponse");
body1=new String(Base64.encodeBase64(listOfHeaderValues.get(0).getBytes()));
return body1;
}
}
ありがとう、アリ。 @ControllerAdviceで注釈を付けると、リクエストレグのインターセプタのようにJavaConfigクラスに登録する必要がありますか?できるだけ早くこれをテストし、結果を元に戻します。ありがとう。 – sage
登録は必要ありません。スキャン可能な限り –
こんにちはアリですが、これを入れてしまえばうまくいきます。郵便配達員にプリントアウトされたStringオブジェクトをレスポンスとして送信することで、期待されるhttpレスポンスを無効にすることができました。私の挑戦は今、文字列として自分のレスポンスペイロードにアクセスする最善の方法です。そのため、クライアントに提示する前にbase64でエンコードすることができます。 response.getBody()は、OutputStreamのみを返します。 ServerHttpResponseからペイロード本文を取得するためのスニペットはありますか? – sage