일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Vue configureWebpack
- Visual Studio 강제 삭제
- 리버스 프록시 예제
- Visual Studio 패키지에 실패했습니다.
- Vue.config
- Vue3 configureWebpack
- vue.js
- SQLP
- 디자인 패턴 사례
- 프록시 예제
- .NET Core
- Visual Studio 2015 삭제
- 웹 크롤링
- javascript
- Visual Studio 2015 강제 삭제
- tomcat
- vue
- 웹 자동화
- Selenium 설치
- Visual Studio 2015 설치
- spring
- MSSQL 동적 쿼리
- 업무 자동화
- Nginx Reverse Proxy
- Tomcat Error
- vue3
- Visual Studio 재설치
- Selenium 환경
- .NET Core Proxy
- MSSQL 문자열
- Today
- Total
금백조의 개발 블로그
[Spring]Spring에서 PUT, DELETE Method 사용하기 본문
서론
진행하고 있던 Spring 사이드 프로젝트에서 RESTful 하고 싶은 HTTP API를 만들기 위해 put, delete HTTP Method를 사용하려 했습니다. 단순히 form 태그 안 method 속성을 "put", "delete"로 바꾸고 요청을 시도해보았지만 Controller에 Method 별로 제대로 매핑이 되지 않았습니다. 오늘은 이를 해결한 과정에 대해서 자세히 포스팅하려 합니다.
[개발환경]
Spring 4.3.12
openJDK 1.8
본론
HTML form 태그에서는 GET/POST Method만 지원을 합니다. 왜 그런지에 대해서는 아래의 [REST - HTML Form에서 GET/POST만 지원하는 이유] 글에 자세히 나와있기에 링크로 대체하겠습니다.
[REST - HTML Form에서 GET/POST만 지원하는 이유]
http://haah.kr/2017/05/23/rest-http-method-in-html-form/
따라서 디스패처 서블릿(dispatcher Servlet)이 PUT, DELETE Method를 인식할 수 있도록 Spring Framework의 org.springframework.web.filter 패키지 안에 구현된 HiddenHttpMethodFilter를 사용해야 합니다.
[해결책]
1. web.xml 에 아래의 코드를 추가하여 HiddenHttpMethodFilter를 활성화합니다.
[web.xml]
<!-- HTTP Method Filter -->
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.form 태그에서 method 속성을 post 로 하고 form 태그 안 input을 type="hidden" name = "_method"으로 한 후 value 속성에 요청할 HTTP Method를 명시합니다.
[example.jsp]
<form id="delete" action="/bulletinboards/newbulletinboard/${bulletinId}" method="post">
<input type="hidden" name = "_method" value = "delete"/>
</form>
3.Controller에 요청한 HTTP Method가 제대로 매핑되는지 확인합니다.
[ExampleController.java]
@PutMapping(value = "/newbulletinboard/{bulletinId}")
public void updateBulletinboard(Model model, HttpServletRequest req, @PathVariable("bulletinId") String strbulletinId) throws Exception {
//생략
}
@DeleteMapping(value = "/newbulletinboard/{bulletinId}")
public void updateBulletinboard(Model model, HttpServletRequest req, @PathVariable("bulletinId") String strbulletinId) throws Exception {
//생략
}
form 태그안의 input 태그를 히든으로 하고 name을 _method로 하는 이유?
→ HiddenHttpMethodFilter.class 내부를 디버깅을 해보면 input 태그를 type="hidden" name = "_method" value = "delete"로 한 후 요청하면 doFilterInternal메서드 안에 있는 paramValue에 "delete"가 들어가게 됩니다. 그리고 HttpMethodRequestWrapper 객체를 생성하여 method를 delete로 변경하여 DELETE 요청이 온 것으로 바뀌게 됩니다. 따라서 히든으로 설정한 name이 _"method"인 input 태그의 value 값에 따라 디스패처 서블릿(dispatcher Servlet)에 요청하는 HTTP Method가 결정됩니다.
[HiddenHttpMethodFilter.class]
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
/** Default method parameter: {@code _method} */
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
/**
* Set the parameter name to look for HTTP methods.
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
requestToUse = new HttpMethodRequestWrapper(request, paramValue);
}
}
filterChain.doFilter(requestToUse, response);
}
/**
* Simple {@link HttpServletRequest} wrapper that returns the supplied method for
* {@link HttpServletRequest#getMethod()}.
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method.toUpperCase(Locale.ENGLISH);
}
@Override
public String getMethod() {
return this.method;
}
}
}
결론
Spring 환경에서 GET, POST Method 이외에 HTTP Method 사용법을 알게 된 좋은 경험이었습니다. 구현된 자세한 소스는 아래 링크에서 확인하실 수 있습니다.
https://github.com/GoldSwan/PictureRepository