JAX-RS의 필수 @QueryParam (및 부재시 수행 할 작업)
RESTEasy JAX-RS 구현을 사용하여 웹 서비스 구성 요소를 JBoss Application Server 7에 배포합니다 .
JAX-RS 에서 필수 필수 @QueryParam 매개 변수 를 선언하는 데 사용할 수있는 어노테이션이 있습니까? 그렇지 않다면 그러한 매개 변수가 누락 된 상황을 처리하는 '표준'방법은 무엇입니까?
내 웹 서비스 (리소스) 메서드는 모든 필수 인수와 함께 올바르게 호출 될 때 JSON 문자열 결과를 반환하지만 필수 매개 변수가 누락되었음을 호출자에게 나타내는 가장 좋은 방법이 무엇인지 모르겠습니다.
좋은 질문. 불행히도 (또는 다행히도) JAX-RS에는 매개 변수를 필수로 만드는 메커니즘이 없습니다. 매개 변수가 제공되지 않으면 값이되며 NULL
리소스가 그에 따라 처리해야합니다. 다음을 사용 WebApplicationException
하여 사용자에게 알리는 것이 좋습니다 .
@GET
@Path("/some-path")
public String read(@QueryParam("name") String name) {
if (name == null) {
throw new WebApplicationException(
Response.status(HttpURLConnection.HTTP_BAD_REQUEST)
.entity("name parameter is mandatory")
.build()
);
}
// continue with a normal flow
}
당신이 사용할 수있는 javax.validation
매개 변수가로 주석을 달아도 필수 있음을 시행 주석을 @javax.validation.constraints.NotNull
. Jersey 예제 와 RESTeasy 예제를 참조하십시오 .
따라서 귀하의 방법은 다음과 같습니다.
@GET
@Path("/some-path")
public String read(@NotNull @QueryParam("name") String name) {
String something =
// implementation
return something;
}
그런 다음 JAX-RS 제공자에 의해 예외가 일부 오류 코드로 변환됩니다. 일반적으로 자체 구현을 등록하여 재정의 할 수 있습니다 javax.ws.rs.ext.ExceptionMapper<javax.validation.ValidationException>
.
이는 필수 매개 변수를 오류 응답으로 변환하는 중앙 집중식 방법을 제공하며 코드 중복이 필요하지 않습니다.
나는 같은 문제에 부딪 쳤고 내 REST 코드에 흩어져있는 수많은 상용구 null 검사를 원하지 않기로 결정했기 때문에 이것이 내가하기로 결정한 것이다.
- 필수 매개 변수가 지정되지 않은 경우 예외가 발생하도록하는 어노테이션을 작성하십시오.
- REST 코드에서 발생한 다른 모든 예외를 처리하는 것과 동일한 방식으로 throw 된 예외를 처리합니다.
내용은 1) , 나는 다음과 같은 주석을 구현 :
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Required
{
// This is just a marker annotation, so nothing in here.
}
... 그리고 ContainerRequestFilter
그것을 적용하기 위해 다음 JAX-RS :
import java.lang.reflect.Parameter;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
@Provider
public class RequiredParameterFilter implements ContainerRequestFilter
{
@Context
private ResourceInfo resourceInfo;
@Override
public void filter(ContainerRequestContext requestContext)
{
// Loop through each parameter
for (Parameter parameter : resourceInfo.getResourceMethod().getParameters())
{
// Check is this parameter is a query parameter
QueryParam queryAnnotation = parameter.getAnnotation(QueryParam.class);
// ... and whether it is a required one
if (queryAnnotation != null && parameter.isAnnotationPresent(Required.class))
{
// ... and whether it was not specified
if (!requestContext.getUriInfo().getQueryParameters().containsKey(queryAnnotation.value()))
{
// We pass the query variable name to the constructor so that the exception can generate a meaningful error message
throw new YourCustomRuntimeException(queryAnnotation.value());
}
}
}
}
}
당신은 등록해야 ContainerRequestFilter
당신이 당신의 다른 등록하는 것과 같은 방법으로 @Provider
당신의 JAX-RS 라이브러리 클래스를. RESTEasy가 자동으로 수행 할 수 있습니다.
들어 2) , I는 일반적인 JAX-RS를 사용하여 모든 런타임 예외를 처리 ExceptionMapper
:
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class MyExceptionMapper implements ExceptionMapper<RuntimeException>
{
@Override
public Response toResponse(RuntimeException ex)
{
// In this example, we just return the .toString() of the exception.
// You might want to wrap this in a JSON structure if this is a JSON API, for example.
return Response
.status(Response.Status.BAD_REQUEST)
.entity(ex.toString())
.build();
}
}
As before, remember to register the class with your JAX-RS library.
Probably the easiest way is to use @Nonnull
from javax.annotation
to achieve this. It's super simple to use as all you have to do is add it before @QueryParam
as shown below.
However, keep in mind that this will throw an IllegalArgumentException
when the parameter is null so the response you send back will be whatever you do for an exception. If you don't intercept it it's going to be a 500 Server Error
even though the correct thing to send back would be a 400 Bad Request
. You can intercept IllegalArgumentException
and process it to return a proper response.
Example:
import javax.annotation.Nonnull;
...
@GET
@Path("/your-path")
public Response get(@Nonnull @QueryParam("paramName") String paramName) {
...
}
The default error message returned to the caller looks like this:
{"timestamp":1536152114437,"status":500,"error":"Internal Server Error","exception":"java.lang.IllegalArgumentException","message":"Argument for @Nonnull parameter 'paramName' of com/example/YourClass.get must not be null","path":"/path/to/your-path"}
'code' 카테고리의 다른 글
반사를 통해 개체의 필드를 가져 오는 방법은 무엇입니까? (0) | 2020.11.17 |
---|---|
android의 webview에서 onclick 이벤트를 어떻게 얻을 수 있습니까? (0) | 2020.11.17 |
동일한 스크립트로 제출시 HTML 양식에서 PHP로 이메일 보내기 (0) | 2020.11.17 |
Map [string] int를 값으로 정렬하는 방법은 무엇입니까? (0) | 2020.11.17 |
독일어 키보드의 줄 주석 단축키 (0) | 2020.11.17 |