📝 @RequestMapping, @Responsebody
@RestController
@RequestMapping("/mapping/users")
public class MappingClassController {
/**
* GET /mapping/users
*/
@GetMapping
public String users() {
return "get users";
}
/**
* POST /mapping/users
*/
@PostMapping
public String addUser() {
return "post user";
}
/**
* GET /mapping/users/{userId}
*/
@GetMapping("/{userId}")
public String findUser(@PathVariable String userId) {
return "get userId=" + userId;
}
/**
* PATCH /mapping/users/{userId}
*/
@PatchMapping("/{userId}")
public String updateUser(@PathVariable String userId) {
return "update userId=" + userId;
}
}
- 일반적으로 공통적인 URL을 클래스 위에 선언해 사용한다
@RequestMapping(value = "/modelAndView.do" method = RequestMethod.GET)
public ModelAndView returnModelAndView(HttpServletResponse response,
HttpServletRequest request) {
ModelAndView modelAndView = new ModelAndView();
// WEB-INF/views/가 기본 경로
modelAndView.setViewName("request"); // request.jsp 페이지 노출 WEB-INF/views/request.jsp
modelAndView.addObject("name","James"); // index.jsp에 name : James 값을 전달
return modelAndView;
}
리턴 종류 - ModelAndView
- 노출시킬 jsp 페이지와 값을 보낼 수 있습니다.
@RequestMapping(value = "/string.do")
public String returnString(HttpServletResponse response,
HttpServletRequest request) {
return "request"; // request.jsp 페이지 노출
}
리턴 종류 - String
- return 값에 해당하는 jsp 페이지를 노출시킵니다.
@RequestMapping("/requset.do")
public void request(HttpServletResponse response,
HttpServletRequest request) throws IOException {
PrintWriter writer = null;
writer=response.getWriter();
writer.print("<html><body><h1>Hello, ResponseBody!</h1></body></html>");
writer.flush();
}
리턴 종류 - void
- HTML 태그를 인식할 수 있습니다. 노출 페이지는 없지만 직접 만들 수 있습니다.
@RequestMapping(value = "/string2.do")
@ResponseBody
public String returnString2(HttpServletResponse response,
HttpServletRequest request) {
return "<html><body><h1>Hello, ResponseBody!</h1></body></html>";
}
// 이미지 base64 인식
// @RequestMapping(value = "/base64", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
// mp4 base64 인식
// @RequestMapping(value = "/base64", method = RequestMethod.GET, produces = "video/mp4")
// pdf base64 인식
// @RequestMapping(value = "/base64", method = RequestMethod.GET, produces = "application/pdf")
// base64 디코딩해 해석해 화면에 노출
@RequestMapping(value = "/base64", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public @ResponseBody byte[] base64(HttpServletRequest request, HttpServletResponse response) throws Exception {
String uri = "http://localhost:8080/getBase64";
String encodeBase64 = callGetMethod(uri);
byte decode[] = Base64.decodeBase64(encodeBase64);
return decode;
}
리턴 종류 - String (responseBody)
- jsp 페이지가 아닌 해당 문자열을 화면에 보여줍니다. (HTML 태그를 인식하고 JSON으로 데이터를 보낼 때 사용)
- [JSON으로 데이터 보낼시 return type은 HashMap 입니다.]
📝 @RequestParam
@RequestMapping(value = "/param.do", method = RequestMethod.GET)
public void param(@RequestParam String name, String age,
HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
// 호출 URI : param.do?name=lee&age=20 // name 필수 입력
System.out.println(">>> " + name); // >>> lee
System.out.println(">>> " + age); // >>> 20
}
RequestParam은 무조건 해당 이름의 키로 받아야 한다는 강제성을 부여한다.
@ResponseBody
@GetMapping(value = "/test")
public String requestParamDefault(
@RequestParam(required = true, defaultValue = "guest") String username,
@RequestParam(required = false, defaultValue = "-1") int age) {
log.info("username={}, age={}", username, age);
return "ok";
}
옵션을 통해 Default값이나 required를 조작할 수 있다
📝 @ModelAttribute
@RequestMapping(value = "/model.do", method = RequestMethod.GET)
public void body4(@ModelAttribute BodyVO bodyVO,
HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
// 호출 URI : model.do?name=lee&age=20
// @ModelAttribute 사용시에는 해당 클래스의 객체를 생성하고 값을 set 해준다.
// (default로 @ModelAttribute 안 적어도 @ModelAttribute 적은 거 처럼 동작)
// 객체를 받는 경우는 무조건 쿼리스트링으로만 동작함 (body 인식 못 함)
System.out.println(">>> " + bodyVO.getName()); // >>> lee
System.out.println(">>> " + bodyVO.getAge()); // >>> 20
}
사용시 해당 클래스의 객체를 생성하고 값을 set 해준다. (default로 @ModelAttribute 안 적어도 @ModelAttribute 적은 거 처럼 동작)
객체를 받는 경우는 무조건 쿼리스트링으로만 동작함 (body 내용은 자동 DI 못 함)
📝 @ResponseBody, @RequestBody
@RequestMapping(value = "/urlencoded.do", method = RequestMethod.POST)
public void urlencoded(String code,String name) {
// 호출 Url : urlencoded.do?name=Lee
// Content-Type : application/x-www-form-urlencoded
// Body : key → code, Value → ABC
System.out.println(">>> " + code); // ABC
System.out.println(">>> " + name); // Lee
// 일반적으로 POST 방식에 쿼리스트링을 붙히지 않지만 붙혀도 인식이 가능함
// x-www-form-urlencoded 의 경우 쿼리스트링처럼 code=ABC 인식을 한다.
}
/** application/x-www-form-urlencoded **/
@RequestMapping(value = "/urlencodedToObject.do", method = RequestMethod.POST)
public void urlencodedToObject(BodyVO bodyVO) {
// 호출 Url : urlencoded.do?name=Lee
// Content-Type : application/x-www-form-urlencoded
// Body : key → code, Value → ABC
System.out.println(">>> " + bodyVO.getName()); // ABC
System.out.println(">>> " + bodyVO.getAge()); // ABC
}
/** application/x-www-form-urlencoded의 GET의 경우 따로 RequestBody가 필요없다. **/
/** text **/
@RequestMapping(value = "/text.do", method = RequestMethod.POST)
public void text(@RequestBody String bodyContents) {
// 호출 Url : text.do
// body : this is text
// Content-Type : text 또는 text/html
System.out.println(">>> " + bodyContents); // this is text
}
/** application/json **/
@RequestMapping(value = "/json.do", method = RequestMethod.POST)
public void json(@RequestBody String bodyContents) {
// 호출 Url : json.do
// body : {"content" : "this is json"}
// Content-Type : application/json
System.out.println(">>> " + bodyContents); // {"content" : "this is json"}
}
/** application/json (Object Injection) **/
@RequestMapping(value = "/jsonToObject.do", method = RequestMethod.POST)
public @ResponseBody HashMap<String, Object> jsonToObject(@RequestBody BodyVO bodyVO) {
/** BodyVO (HashMap도 또한 Object이기 떄문에 동일하게 적용 된다. **/
// String name
// String age → int 형으로 값을 보내면 못 자동 Injection이 안 된다. "age" : 20 (X)
/** 참고로 BodyVO에 default값이 설정되어 있어도 ReuqestBody에 넘어온 값이 없다면(body에 json을 안 보내면) null로 덮어씌워진다. **/
/** 필요사항에서는 데이터를 까서 검증하는 작업을 직접해야할 거 같다. **/
// 호출 Url : jsonToObject.do
// body : {"name" : "lee", "age":"20"}
// Content-Type : application/json
System.out.println(">>> " + bodyVO.getName()); // lee
System.out.println(">>> " + bodyVO.getAge()); // 20
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("bodyVO", bodyVO);
return map;
}
/** responseBody란 처리한 결과를 클라이언트에게 다시 돌려줘서 읽을 수 있게한다. (즉 return 값이 있어야한다.) **/
// 미사용시 → 404 페이지를 찾을 수 없음
// 사용시 → {"bodyVO" : {"name" : "lee", "age":"20"}}
/**
* jsonToObject.do을 사용하기 위해서는 하기 라이브러리가 필요 (body 내용을 Object에 Injeciton)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
**/
@RequestMapping(value = "/deleteIndex", method = RequestMethod.GET)
@ResponseBody
public void deleteIndex(@RequestParam(value="No[]") ArrayList indexParams, HttpServletRequest request, HttpServletResponse response, HttpSession session) {
// http://localhost:8080/deleteIndex?No=keyword_index2
ArrayList<String> indexNames = new ArrayList<String>();
indexNames = indexParams;
IndexInfo indexInfo = new IndexInfo();
indexInfo.deleteIndex(indexNames);
}
<script>
$(function() {
$("#index_delete_btn").on("click", function() {
var checked = [];
$("input[name='No']:checked").each(function(i) {
checked.push($(this).val());
});
$.ajax({
type : "GET",
url : "deleteIndex",
data : {
No : checked
},
success : function(data) {
location.reload();
}
error : function()
}); // ajax 종료
});
});
</script>
<tbody id="indexVOs">
<c:forEach var="indexVO" items="${indexVOs}" begin="0"
end="${fn:length(indexVOs)}" step="1" varStatus="status">
<tr>
<td>${status.count}</td>
<td>
<input class="form-check-input" type="checkbox"
value=${indexVO.name } id="flexCheckChecked" name="No"></td>
<td>${indexVO.status}</td>
<td><a href="/indexDetail?name=${indexVO.name}&status=${indexVO.status}
&docsCount=${indexVO.docsCount}&storeSize=${indexVO.storeSize}">${indexVO.name}</a></td>
<td>${indexVO.docsCount}</td>
<td>${indexVO.storeSize}</td>
</tr>
</c:forEach>
</tbody>
RequestBody
- RequestBody는 HTTP Body안에 JSON을 VO에 맵핑하는 스프링 어노테이션.
ReponseBody
- ResponseBody는 사용자가 읽을 수 있게 return 해준다. (outputStream으로 현재 화면에 flush하는 것과 같은 동작)
📝 @PathVariable (동적 URL 매핑)
// PathVariable에 userId에 값이 GetMapping에 {userId}에 들어간다
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) {
log.info("mappingPath userId={}", data);
return "ok";
}
// 2개도 사용 가능
@GetMapping("/mapping/{userId}/test/{orderNo}")
public String mappingPath(@PathVariable("userId") String data, @PathVariable("orderNo") String data2) {
log.info("mappingPath userId={}, orderNo={}", data, data2);
return "ok";
}
📝 @RequestHeader, @CookieValue
@GetMapping("/headers")
public String headers(HttpServletRequest request,
HttpServletResponse response,
HttpMethod httpMethod,
Locale locale,
@RequestHeader MultiValueMap<String, String> headerMap,
@RequestHeader("host") String host,
@CookieValue(value = "myCookie", required = false) String cookie)
{
log.info("request={}", request);
log.info("response={}", response);
log.info("httpMethod={}", httpMethod);
log.info("locale={}", locale);
log.info("headerMap={}", headerMap);
log.info("header host={}", host);
log.info("myCookie={}", cookie);
return "ok";
}
📝@Slf4j (롬복 필요) , @RestController
package hello.springmvc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController // @ResponseBody 역할
public class LogTestController {
@GetMapping(value = "")
public void testLog(){
String helloWorld = "hello world";
log.info("programming start : {}",helloWorld);
}
}
Slf4j
- 로깅하는데 도움을 줍니다.
RestController
- Controller + ResponseBody 역할을 합니다.