서블릿 매핑 URL 패턴에서 /와 / *의 차이점


175

익숙한 코드 :

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>main</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

내 이해는에 /*매핑됩니다 http://host:port/context/*.

어때요 /? http://host:port/context루트에만 매핑되지는 않습니다 . 실제로는을 수락 http://host:port/context/hello하지만 거부 http://host:port/context/hello.jsp합니다.

누구나 어떻게 http://host:port/context/hello매핑 되는지 설명 할 수 있습니까 ?

답변:


268

<url-pattern>/*</url-pattern>

/*서블릿에는 기본 서블릿과 JSP 서블릿으로 servletcontainer에서 제공하는 모든 서블릿을 포함하여 다른 모든 서블릿을 재정의합니다. 당신이 요청한 것이 무엇이든, 그것은 그 서블릿에서 끝날 것입니다. 따라서 이는 서블릿에 잘못된 URL 패턴입니다. 일반적 /*으로 한 Filter가지만 사용하고 싶습니다 . 를 호출하여 요청이보다 구체적인 URL 패턴을 수신하는 서블릿을 계속하도록 할 수 FilterChain#doFilter()있습니다.

<url-pattern>/</url-pattern>

/다른 서블릿을 대체하지 않습니다. 등록 된 다른 서블릿과 일치하지 않는 모든 요청에 ​​대해서만 서블릿 컨테이너의 내장 기본 서블릿을 대체합니다. 이는 일반적으로 정적 자원 (CSS / JS / image / etc) 및 디렉토리 목록에서만 호출됩니다. 서블릿 컨테이너의 내장 기본 서블릿은 HTTP 캐시 요청, 미디어 (오디오 / 비디오) 스트리밍 및 파일 다운로드 이력서도 처리 할 수 ​​있습니다. 일반적으로 기본 서블릿을 재정의하고 싶지는 않습니다. 그렇지 않으면 모든 작업을 처리해야합니다. 정확하지는 않습니다 (JSF 유틸리티 라이브러리 OmniFaces 에는 오픈 소스 예제가 있습니다)). 따라서 이는 서블릿의 잘못된 URL 패턴이기도합니다. JSP 페이지가이 서블릿에 도달하지 않는 이유는 서블릿 컨테이너의 내장 JSP 서블릿이 호출되기 때문입니다. 이는 기본적으로보다 구체적인 URL 패턴에 이미 맵핑되어 *.jsp있습니다.

<url-pattern></url-pattern>

그런 다음 빈 문자열 URL 패턴도 있습니다. 컨텍스트 루트가 요청 될 때 호출됩니다. 이는 <welcome-file>하위 폴더가 요청 될 때 호출되지 않는 접근 방식 과 다릅니다 . 이것은 " 홈 페이지 서블릿 " 을 원할 경우 실제로 찾고있는 URL 패턴 일 가능성이 높습니다 . 나는 빈 문자열 URL 패턴 과 슬래시 URL 패턴 /이 다른 방식으로 정확하게 정의 될 것으로 직관적으로 기대한다는 것을 인정해야 하므로 많은 초보자가 이것에 대해 혼란스러워했다는 것을 이해할 수 있습니다. 그러나 그것이 바로 그 것입니다.

전면 컨트롤러

경우 당신이 실제로 프론트 컨트롤러 서블릿을하고자하는, 당신은 최고의 같은보다 구체적인 URL 패턴에 매핑 거라고 *.html, *.do, /pages/*, /app/*, 등 당신은 일반적인 URL 패턴의 전면 컨트롤러 URL 패턴과 커버 정적 자원을 멀리 숨길 수 있습니다 같은 /resources/*, /static/*등 서블릿 필터의 도움으로. / *에 맵핑 된 프론트 컨트롤러 서블릿이 정적 자원을 처리하지 못하게하는 방법을 참조하십시오 . Spring MVC에는 내장 정적 리소스 서블릿이 있으므로 /Spring에서 정적 리소스에 대한 공통 URL 패턴을 구성하면 프론트 컨트롤러를 매핑 할 수 있습니다 . Spring MVC에서 정적 컨텐츠를 처리하는 방법을 참조하십시오 .


9
감사. 약간의 연구 끝에 미묘한 점을 분명히하고 싶습니다. /는 웹 서버가 설치하는 기본 서블릿을 덮어 씁니다. 예를 들어 Tomcat은 정적 리소스를 제공하는 DefaultServlet을 설치합니다. /를 사용하면 기본 서블릿이 (가장 바람직하지 않은) 부작용으로 제거됩니다.
Candy Chiu

글쎄, 나는 그것을 "덮어 쓰기"라고 부르지 않고 "바꾸기"라고 부릅니다. 이와 같은 기본 서블릿을 바꾸는 것이 유용 할 수 있습니다.
BalusC

1
<url-pattern> </ url-pattern> 오류 발생 : 서블릿 매핑에서 유효하지 않은 <url-pattern>
슬림

오류 메시지는 내 IDE가 아닌 바람둥이에서 나왔습니다. 그러나 Tomcat 6을 사용하고 있으므로 아마도 문제 일 것입니다.)
slim

2
@BalusC, /**패턴이 무엇을 나타내는 지 알려주시겠습니까?
Sajib Acharya

45

BalusC의 답변을 매핑 규칙과 예제로 보완하고 싶습니다.

Servlet 2.5 스펙의 맵핑 규칙 :

  1. 정확한 URL지도
  2. 와일드 카드 경로 매핑
  3. 지도 확장
  4. 기본 서블릿에 매핑

이 예에는 세 개의 서블릿이 있습니다. /는 우리가 설치 한 기본 서블릿입니다. Tomcat은 jsp 및 jspx를 제공하기 위해 두 개의 서블릿을 설치합니다. 지도로http://host:port/context/hello

  1. 다음에 정확한 URL 서블릿이 설치되지 않았습니다.
  2. 다음에 와일드 카드 경로 서블릿이 설치되지 않았습니다.
  3. 다음 확장 프로그램과 일치하지 않습니다.
  4. 기본 서블릿에 맵핑하고 리턴하십시오.

지도로 http://host:port/context/hello.jsp

  1. 다음에 정확한 URL 서블릿이 설치되지 않았습니다.
  2. 다음에 와일드 카드 경로 서블릿이 설치되지 않았습니다.
  3. 확장 서블릿을 찾았습니다.

25

아마도 404몇 시간 동안 고통 을 겪었으므로 URL이 어떻게 매핑되는지 알아야합니다 . 요청을 처리하는 핸들러에는 두 가지 종류가 있습니다. BeanNameUrlHandlerMapping그리고 SimpleUrlHandlerMapping. 를 정의 할 때을 servlet-mapping사용 SimpleUrlHandlerMapping합니다. 우리가 알아야 할 한 가지는이 두 핸들러 alwaysUseFullPath가 기본값 인 이라는 공통 속성을 공유 한다는 것 false입니다.

false여기서 Spring은 전체 경로를 사용하여 URL을 컨트롤러에 매핑하지 않습니다. 무슨 뜻인가요? 다음을 정의 할 때를 의미합니다 servlet-mapping.

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

핸들러는 실제로 *부품을 사용 하여 컨트롤러를 찾습니다. 예를 들어 다음 컨트롤러를 404사용하여 요청하면 오류가 발생합니다./perfix/api/feature/doSomething

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

완벽하게 맞아? 그러나 왜 404. 앞에서 언급했듯이 기본값 인 alwaysUseFullPathfalse는 요청에서 /api/feature/doSomething해당 컨트롤러를 찾는 데만 사용되지만 해당 경로에 대해서는 신경 쓰지 않습니다. URL을 MyController base 로 변경 /perfix/perfix/api/feature/doSomething하거나 제거 해야합니다 .perfix@RequestingMapping


8

나는 Candy의 대답이 대부분 맞다고 생각합니다. 내가 생각하는 작은 부분이 하나 있습니다.

host : port / context / hello.jsp를 맵핑하려면

  1. 다음에 정확한 URL 서블릿이 설치되지 않았습니다.
  2. 와일드 카드 경로 서블릿을 찾았습니다 .

"/ *"가 host : port / context / hello와 일치하지 않는 이유는 "/ hello"를 파일 대신 경로로 취급하기 때문입니다 (확장자가 없기 때문에).


2

사이의 본질적인 차이 /*/매핑 서블릿이다 /*확장 매핑 (같은 어떠한 서블릿 전에 선택 될 *.html맵핑 서블릿을하면서) /확장 매핑이 고려된다 (그리고 어떤 아무튼 '모든 요청에 사용될 후에 만 선택 될 다른 어떤 것과도 일치하지 않습니다. ""기본 서블릿 "입니다.

특히, /*매핑은 항상 /매핑 전에 선택 됩니다. 두 가지 중 하나라도 있으면 요청이 컨테이너의 기본 서블릿에 도달하지 못하게됩니다.

어느에만 정확히 일치하는 (등이있다 서블릿 매핑 후 선택됩니다 /foo/bar)와 이상 경로 매핑되는 그 /*(같은 /foo/*). 빈 문자열 매핑은 컨텍스트 루트 ( http://host:port/context/) 와 정확히 일치합니다 .

http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html의 버전 3.1에서 사용 가능한 Java Servlet Specification의 12 장을 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.