При разработке и развитии REST API с использованием Java EE в некоторых случаях вы хотели бы «взглянуть» на входящий HTTP-запрос, в частности на параметры заголовка , более детально (для каждого случая), чем фильтр сервлетов или более конкретные ContainerRequestFilters .
Один из возможных способов, который я нахожу в некоторых случаях очень удобным, — это добавление перехватчиков CDI в мою реализацию JAXRS Resource , которые в конечном итоге получают доступ к входящему HTTP-запросу и выполняют некоторую «пользовательскую» логику. Как разработчик, я могу полностью контролировать — где (в каких путях) перехватывать запрос, просто добавляя или удаляя пользовательскую аннотацию. С введением Java EE 7 легче смешивать «проблемы», поэтому вы можете легко внедрить HTTP-запрос к обычным перехватчикам CDI .
Ниже я просто документирую очень простой пример, в котором я использую пользовательский перехватчик для «перехвата» HTTP-запросов в бизнес-REST API, чтобы выполнить очень специфическую пользовательскую логику аутентификации. Я проверяю, находится ли «пользователь», инициирующий запрос в моем REST API, в какой-то определенной пользовательской роли, которую определяет моя система. Конечно, общий пример — всего лишь пример, но вы поняли идею.
Чтобы внедрить такой компонент, вам нужно 2 вещи:
- ввести пользовательскую аннотацию, которая будет использоваться для активации перехватчика, когда он определен
- реализовать перехватчик CDI.
- применить аннотацию, на пути / ресурсы вашего отдыха API
Интерфейс аннотации
Здесь нет ничего необычного, только пользовательская аннотация во время выполнения, поэтому мы можем использовать ее для «маркировки» определенных методов нашего JAXRS API.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
package gr.javapapo.sample.cdi;/** * Created by <a href="mailto:javapapo@mac.com">javapapo</a> on 24/09/15. */import javax.enterprise.util.Nonbinding;import javax.interceptor.InterceptorBinding;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@InterceptorBinding@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD})public @interface CheckRequest { @Nonbinding String role() default "ADMIN";} |
Реализация перехватчика
Интересные моменты:
- перехватчик «помечен» нашей пользовательской аннотацией — просто
- мы @ Внедрим HttpServletReqest
- Мы применяем некоторую пользовательскую логику, основанную на деталях аннотации (я читаю любые параметры определения)
- Из запроса я прочитал заголовок и на основе параметров аннотации — я делаю некоторые основные логики
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package gr.javapapo.sample.cdi;import javax.inject.Inject;import javax.interceptor.AroundInvoke;import javax.interceptor.Interceptor;import javax.interceptor.InvocationContext;import javax.servlet.http.HttpServletRequest;import javax.ws.rs.NotAllowedException;/** * CDI interceptor for the {@linkplain CheckRequest} annotation * Created by <a href="mailto:javapapo@mac.com">javapapo</a> on 24/09/15. */@Interceptor@CheckRequestpublic class CheckRequestInterceptor { @Inject HttpServletRequest request; @AroundInvoke public Object checkAccess(InvocationContext ctx) throws Exception { CheckRequest annotation = ctx.getMethod().getAnnotation(CheckRequest.class); String role = annotation.role(); String roleToken = request.getHeader("roleToken"); if(roleToken==null && !role.equals(roleToken)){ throw new NotAllowedException("Not allowed if your request does not have the roleToken header " + "or your role is not correct "); } return ctx.proceed(); }} |
Применение перехватчика / аннотации
В конце концов, вы можете просто аннотировать свои ресурсы и методы @Path JAXRS, чтобы «вставить» свою собственную логику:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
@Path("/status")public class StatusResource { /** * Returns a simple JSON object, regarding the app status, n * * @return Response <JsonObject> */ @GET @Produces(MediaType.APPLICATION_JSON) @CheckRequest(role="ADMIN") public Response getStatus() { JsonObject object = Json.createObjectBuilder() .add("status", "Status with CDI internceptor check,It Works at " + LocalDateTime.now().toString()) .build(); Response.ResponseBuilder repBuilder = Response.ok().entity(object); return repBuilder.build(); } |
- Вы можете найти все файлы в этом очень простом примере проекта на github .
| Ссылка: | CDI-перехватчик параметров HTTP Request и Header — простой пример от нашего партнера JCG Париса Апостолопулоса из блога журнала Papo . |