Как обрабатывать запросы, которые включают в себя косые черты (/)?
Мне нужно обрабатывать запросы следующим образом:
www.example.com/show/abcd/efg?name=alex&family=moore (does not work)
www.example.com/show/abcdefg?name=alex&family=moore (works)
www.example.com/show/abcd-efg?name=alex&family=moore (works)
Он должен принимать любой символ из значения, которое находится между www.example.com/show/
и ?
. Обратите внимание, что значение, которое будет расположено там, будет иметь одно значение, а не имя действия.
Например: /show/abcd/efg
и /show/lkikf?name=Jack
, в котором первый запрос должен перенаправить пользователя на страницу abcd/efg
(потому что это имя), а второй должен перенаправить пользователя на страницу lkikf
вместе со значением имя параметра.
У меня есть следующий контроллер для его обработки, но проблема в том, что у меня есть/в адресе, который контроллер не может обработать.
@RequestMapping(value = "/{mystring:.*}", method = RequestMethod.GET)
public String handleReqShow(
@PathVariable String mystring,
@RequestParam(required = false) String name,
@RequestParam(required = false) String family, Model model) {
Я использовал следующее регулярное выражение, которое не сработало.
/^[ [email protected]/#&+-]*$/
Ответы
Ответ 1
Вам нужно создать два метода, а затем иметь @RequestMapping(value = { "/{string:.+}" })
аннотацию, а другую - @RequestMapping(value = { "/{string:.+}", "/{string:.+}/{mystring:.+}" })
, а затем действовать соответственно в каждом, потому что вы не можете иметь необязательные переменные пути .
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/show")
public class HelloController {
@RequestMapping(value = { "/{string:.+}" })
public String handleReqShow(@PathVariable String string,
@RequestParam(required = false) String name,
@RequestParam(required = false) String family, Model model) {
System.out.println(string);
model.addAttribute("message", "I am called!");
return "hello";
}
@RequestMapping(value = { "/{string:.+}", "/{string:.+}/{mystring:.+}" })
public String whatever(@PathVariable String string,
@PathVariable String mystring,
@RequestParam(required = false) String name,
@RequestParam(required = false) String family, Model model) {
System.out.println(string);
System.out.println(mystring);
model.addAttribute("message", "I am called!");
return "hello";
}
}
Ответ 2
Другой способ:
@RequestMapping(value = "test_handler/**", method = RequestMethod.GET)
... и ваш тестовый обработчик может быть "/test_hanlder/a/b/c", и вы получите всю ценность, используя следующий механизм.
requestedUri = (String)
request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
Ответ 3
Первый не работает, потому что вы пытаетесь обработать совершенно новый URL-адрес, который на самом деле не отображен вашим контроллером.
www.example.com/show/abcd/efg?name=alex&family=moore (does not work)
Правильное сопоставление для вышеуказанного URL-адреса может быть похоже на приведенный ниже код.
@RequestMapping(value = {"/{mystring:.*}" , "/{mystring:.*}/{mystring2:.*}"}, method = RequestMethod.GET)
public String handleReqShow(
@PathVariable String mystring,
@PathVariable String mystring2,
@RequestParam(required = false) String name,
@RequestParam(required = false) String family, Model model) {
Я пробовал аналогичную концепцию, когда мой один контроллер используется для обработки нескольких типов запросов.
Ответ 4
Вы можете определить правила, чтобы избежать этого.
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
rules.xml добавьте это на свой WEB-INF
<urlrewrite>
<rule>
<from>^/(10\..*)$</from> <!-- tweak this rule to meet your needs -->
<to>/Show?temp=$1</to>
</rule>
</urlrewrite>
Ответ 5
Попробуйте избежать косой черты.
Regex: /^[ A-Za-z0[email protected]\/#&+-]*$/
Ответ 6
По умолчанию Spring MVC pathperper использует /
как разделитель для переменных пути, независимо от того, что.
Правильный способ обработки этого запроса состоял бы в том, чтобы написать собственный сопоставитель маршрутов, который изменил бы эту логику для конкретного метода обработчика и делегировал значение по умолчанию для других методов обработчика.
Однако, если вы знаете максимально возможное количество косых черт в своем значении, вы можете написать обработчик, который принимает необязательные переменные пути, а не в самом методе, собрать значение из частей переменной пути, вот пример который будет работать для максимальной косой черты, вы можете легко расширить его до трех или четырех
@RequestMapping(value = {"/{part1}", "/{part1}/{part2}"}, method = RequestMethod.GET)
public String handleReqShow(
@PathVariable Map<String, String> pathVariables,
@RequestParam(required = false) String name,
@RequestParam(required = false) String family, Model model) {
String yourValue = "";
if (pathVariables.containsKey("part1")) {
String part = pathVariables.get("part1");
yourValue += " " + part;
}
if (pathVariables.containsKey("part2")) {
String part = pathVariables.get("part2");
yourValue += " /" + part;
}
// do your stuff
}
Вы можете поймать все переменные пути внутри карты, карту @PathVariable Map<String, String> pathVariables
, но недостатком является то, что статическая часть отображения должна перечислить все возможные варианты
Ответ 7
Вы можете кодировать косые черты в пользовательском интерфейсе с помощью% 2f: http://www.example.com/show/abcd%2fefg?name=alex&family=moore
.
Теперь вы должны настроить Spring для обработки косой черты. Пример простой конфигурации:
@RestController
public class TestController {
@GetMapping("{testId:.+}")
public String test(@PathVariable String testId) {
return testId;
}
@GetMapping("{testId:.+}/test/{messageId}")
public String test2(@PathVariable String testId, @PathVariable String messageId) {
return testId + " " + messageId;
}
//Only if using Spring Security
@Configuration
public static class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
DefaultHttpFirewall firewall = new DefaultHttpFirewall();
firewall.setAllowUrlEncodedSlash(true);
return firewall;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
}
}
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public static class SpringMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
urlPathHelper.setUrlDecode(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
}