@PathVariable в SpringBoot с косой чертой в URL

Мне нужно получить параметры из URL-адреса, используя @PathValiable в приложении SpringBoot. Эти параметры часто имеют косую черту. У меня нет контроля над тем, что пользователь введет в URL-адрес, поэтому я хотел бы получить то, что он ввел, а затем я могу справиться с этим.

Я уже просмотрел здесь материалы и ответы, не думаю, что для меня будет хорошим решением просить пользователей как-то кодировать входящие параметры.

Код SpringBoot прост:

@RequestMapping("/modules/{moduleName}")
@ResponseBody
public String moduleStrings (@PathVariable("moduleName") String moduleName) throws Exception {

  ...

}

Таким образом, URL-адрес, например, будет следующим:

http://localhost:3000/modules/...

Проблема в том, что параметр moduleName часто имеет косую черту. Например,

metadata-api\cb-metadata-services OR
app-customization-service-impl\\modules\\expand-link-schemes\\common\\app-customization-service-api

Таким образом, пользователь определенно может ввести:

http://localhost:3000/modules/metadata-api\cb-metadata-services

Возможно ли получить все, что пользователь ввел в URL после /modules/?

Если кто-нибудь скажет мне, каковы хорошие способы решения такой проблемы.


person Kirill Ch    schedule 18.04.2017    source источник


Ответы (3)


Этот код получает полный путь:

@RequestMapping(value = "/modules/{moduleBaseName}/**", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(@PathVariable String moduleBaseName, HttpServletRequest request) {
    final String path =
            request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString();
    final String bestMatchingPattern =
            request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString();

    String arguments = new AntPathMatcher().extractPathWithinPattern(bestMatchingPattern, path);

    String moduleName;
    if (null != arguments && !arguments.isEmpty()) {
        moduleName = moduleBaseName + '/' + arguments;
    } else {
        moduleName = moduleBaseName;
    }

    return "module name is: " + moduleName;
}
person P.J.Meisch    schedule 18.04.2017
comment
Я могу вызвать localhost:8080/modules/abc, который возвращает имя модуля: abc и localhost:8080/modules/abc/def, который возвращает имя модуля: abc/def . Вы вводите обратную косую черту в URL? - person P.J.Meisch; 18.04.2017
comment
Это действительно входит в метод. Это хорошо. Однако по какой-то причине он идет по кругу (доходит до оператора return МНОГО РАЗ, и имя модуля меняется каждый раз). - person Kirill Ch; 18.04.2017
comment
Большой! Просто добавьте @ResponseBody. Это действительно работает! - person Kirill Ch; 18.04.2017
comment
ах, вот в чем разница; Мой контроллер был аннотирован @RestController вместо @Controller, поэтому по умолчанию у меня уже был @ResponseBody. - person P.J.Meisch; 18.04.2017
comment
AntPathMatcher должен быть кэширован и, возможно, может быть заменен сопоставителем пути муравья Spring. - person martian; 05.05.2019

Основываясь на ответе PJMeisch, я пришел к простому решению для моего случая. Также он позволяет учитывать несколько косых черт в параметре URL. Это не позволяет работать с обратной косой чертой, как и в предыдущем ответе.

@RequestMapping(value = "/modules/**", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(HttpServletRequest request) {

    String requestURL = request.getRequestURL().toString();

    String moduleName = requestURL.split("/modules/")[1];

    return "module name is: " + moduleName;

}
person Kirill Ch    schedule 18.04.2017
comment
Не уверен, почему этот ответ не предпочтительнее, чем вуду выше - person Aubergine; 31.05.2019
comment
У меня это сработало, используя этот формат: @RequestMapping(value = /{modules:.+}/**, method = RequestMethod.GET) - person aQ123; 05.11.2019

Это школьное задание или что? Почему вы хотите поместить свободный текст в путь? Вместо этого, почему бы не использовать переменную параметра?

Я не уверен, что это хорошая идея, когда пользователь вводит сложные URL-адреса, содержащие произвольный текст. Во-первых, пользователям трудно запомнить сложные URL-адреса, поэтому это не удобно для пользователя. Во-вторых, они могут делать странные вещи.

Вместо этого есть главная страница, на которую они переходят, на которой могут быть ссылки (или что-то в этом роде), чтобы перейти на следующую страницу. Если им нужно ввести произвольный текст, дайте им текстовое поле для добавления данных, кнопку для нажатия, которая сделает что-то вроде ajax-вызова, содержащего данные. В пути будет все, кроме свободного текста. Вы можете сделать это так...

@RequestMapping(value = "/modules/{moduleBaseName}", method = RequestMethod.GET)
@ResponseBody
public String moduleStrings(@PathVariable String moduleBaseName,
                            @RequestParam(value = "moduleName", required = false) String moduleName 
                            HttpServletRequest request) 
{
    return "module name is: " + moduleName;
}

Затем на стороне клиента вам просто нужно установить атрибут данных в вашем ajax-вызове на json, который содержит атрибут «moduleName». Что-то вроде этого.

var params = {};
params.moduleName = userEnteredText;
jQuery.ajax({
    type: "GET",
    url: 'http://localhost:3000/modules'.json'),
    dataType: "json",
    data: params,
    async: true,
    success: function(data) { callback(data); },
    error: function() { alert("Error!!!"); }
});
person ajpieri    schedule 05.06.2020