У меня есть контроллер Spring MVC с несколькими API, я хочу получить URI API, который был поражен из внешнего интерфейса.
У меня есть фильтр, расширяющий OncePerRequestFilter, который перехватывает каждый вызов API, у фильтра есть метод, который принимает HttpServletRequest, HttpServletResponse и filterChain.
Я могу получить uri, используя request.getRequestURI(), но в случае, если uri имеет переменные пути шаблона, скажем uri = "q/v1/ruleset/{rulesetId}"
я получаю окончательный uri, например, API был атакован для rulesetid=23, uri, который я получаю от request.getRequestURI(),
"q/v1/ruleset/23" но я хочу uri = "q/v1/ruleset/{rulesetId}",
есть ли какой-либо способ получить ожидаемый результат, я знаю, я всегда могу получить желаемый результат с помощью некоторых манипуляций, но я хочу сделать вещи универсальными, пожалуйста, помогите
У меня есть контроллер, содержащий API
@RequestMapping(value = "/ruleset/{rulesetid}", method =
RequestMethod.GET)
public RuleSet getRuleSet(@PathVariable(value = "rulesetid")
final Long ruleSetId) {
return storeMixin.getRuleSet(ruleSetId);
}
Фильтр
@Component
@Order(1)
public class CatalogFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,FilterChain filterChain) throws
IOException, ServletException {
long startTime = System.currentTimeMillis();
filterChain.doFilter(request, response);
long elapsed = System.currentTimeMillis() - startTime;
String name = request.getRequestURI();
String requestType = request.getMethod();
Integer httpCode = response.getStatus();
}
}
Здравствуйте, Адитья. Вам нужны статистика/метрика или какая-либо другая операция, которую вы хотите выполнить?
@PatelRomil, да, в фильтре я записываю время выполнения API и количество API, затем отправляю статистику с помощью StatsD, основная проблема заключается в том, что с каждым значением переменной пути {rulesetid} создается новая метрика, в которой нет необходимости, вот почему я хочу шаблонный uri
@AdityaKrishnaNamdeo Возможно, вы уже получили ответ, но для подсчета и статистики времени вы можете использовать администратор весенней загрузки, если хотите, дайте мне знать
@PatelRomil, когда я использовал пружинный привод для сбора метрик, привод предоставляет http-метрики по умолчанию для измерения времени и количества, но в случае statsD я не могу найти эту функцию, если эта функция существует, как вы говорите, пожалуйста, дайте мне знать
@AdityaKrishnaNamdeo да, пружинный привод может собирать время, посчитайте с администратором весенней загрузки, вы можете легко увидеть это в форме графического интерфейса. Я отвечу на это в ближайшее время
Привет @AdityaKrishnaNamdeo, посмотри на ответ. Вы можете сосредоточиться на Spring Boot Admin




Я сомневаюсь, что вы можете получить его в фильтре через существующий API. Однако вы можете предварительно отсканировать все аннотации @RequestMapping, сохранить их, а затем в фильтре сопоставить шаблон, чтобы получить желаемый результат.
Вы не сможете сделать это в фильтре, так как фильтр выполняется до обработчика.
Вы можете реализовать HandlerInterceptor и получить сопоставление путей, как показано ниже.
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
String path = (String)request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
System.out.println("path : " + path);
return true;
}
}
Другой способ — использовать Администратор весенней загрузки. Для этого нам нужно настроить клиент-сервер. Чтобы избежать ошибки, убедитесь, что версия для клиент-серверной зависимости одинакова. Мы можем добавить необходимую метрику из раскрывающегося списка, как показано на изображениях.
Вы можете COUNT, TOTAL_TIME для uri:/user/getEmployee/{employeeId} как 3, 0,2264027
пом.xml
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.1.4</version>
</dependency>
приложение.свойства
spring.boot.admin.api-path=/instances
spring.boot.admin.client.url=http://localhost:6699
management.endpoints.web.exposure.include=*
приложение.свойства
server.port = 6699
spring.boot.admin.server.url=http://localhost:8889
пом.xml
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.1.4</version>
</dependency>
Добавьте @EnableAdminServer
import de.codecentric.boot.admin.server.config.EnableAdminServer;
@SpringBootApplication
@EnableAdminServer
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
графический интерфейсhttp://локальный:6699/#/приложения
Если вы хотите добиться этого Если вы хотите добиться этого программно. Я даю подсказку здесь вы можете найти Все подробности здесь
@RequestMapping(path = "/admin/count",method=RequestMethod.POST)
public JSONObject count(@RequestParam(name = "url") final String url)//@PathVariable(name = "url") final String url
{
String finalURL = "http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:" + url + "";
return sendRequestToURL(finalURL);
}
Мы можем использовать Spring Boot /actuator/metrics/http.server.requests, чтобы получить все конечные точки, которые выполняются, с их количеством, исключением, результатом, статусом, общим временем и т. д., как показано ниже.
Если вы хотите увидеть подробности для конкретной конечной точки, вы можете сделать это, вызвав запрос следующим образом.
localhost:8889/actuator/metrics/http.server.requests?tag=uri:<endPoint>
localhost:8889/actuator/metrics/http.server.requests?tag=uri:/user/asset/getAllAssets
localhost:8889/actuator/metrics/http.server.requests?tag=uri:/user/asset/getAllAssets&tag=status:200
COUNT, сколько раз конкретная конечная точка была
называетсяCOUNT столько раз, сколько раз была конкретная конечная точкаTOTAL_TIME/COUNT как для конкретной конечной точки, так и для всего
заявлениелокальный: 8889/actuator/metrics/http.server.requests
{
"name": "http.server.requests",
"description": null,
"baseUnit": "seconds",
"measurements": [
{
"statistic": "COUNT",
"value": 3
},
{
"statistic": "TOTAL_TIME",
"value": 0.21817219999999998
},
{
"statistic": "MAX",
"value": 0.1379249
}
],
"availableTags": [
{
"tag": "exception",
"values": [
"MethodArgumentTypeMismatchException",
"None"
]
},
{
"tag": "method",
"values": [
"GET"
]
},
{
"tag": "uri",
"values": [
"/{id}.*",
"/user/asset/getAsset/{assetId}",
"/user/asset/getAllAssets"
]
},
{
"tag": "outcome",
"values": [
"CLIENT_ERROR",
"SUCCESS"
]
},
{
"tag": "status",
"values": [
"400",
"404",
"200"
]
}
]
}
Сделай это
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} finally {
String patternMatch = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
}
}
Вам нужно сначала выполнить filterChain.doFilter, прежде чем пытаться выполнить вызов request.getAttribute, поскольку этот атрибут устанавливается только позже в жизненном цикле запроса.
Вы можете попробовать это:
String path = (String)request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
Я сомневаюсь, что вы можете получить его в фильтре через API. Вы можете предварительно отсканировать все аннотации @RequestMapping, сохранить их, а затем в фильтре сопоставить шаблон.