
자바는 서블릿 컨테이너 기능을 제공하면 WAS
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request,
HttpServletResponse reponse)
throws ServletException, IOException {
}
request.getParameter("username"); //단일 파라미터 조회
request.getParameterValues("username"); //복수 파라미터 조회
request.getParameterNames(); //파라미터 이름들 모두 조회
@WebServlet(name = "servlet", urlPatterns = "/request-body-json")
public class Servlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString
(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody); //단순 텍스트
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
System.out.println(helloData.getUsername()); //JSON
System.out.println(helloData.getAge()); //JSON
해당 HTTP 요청이 시작부터 끝날 때까지 유지되는 임시 저장소 기능
request.setAttribute(name, value) //저장
request.getAttribute(name) //조회
webapp 경로에 index.html을 두면 http://localhost:8080 호출시 index.html 페이지가 열린다.
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
@WebServlet(name = "servlet", urlPatterns = "/response-json")
public class Servlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("content-type", "application.json");
response.setCharacterEncoding("utf-8");
HelloData data = new HelloData();
data.setUsername("kim");
data.setAge(20);
//JSON -> {"username" : "kim", "age" : 20}
String result = objectMapper.writeValueAsString(data);
response.getWriter().write(result);


HTTP 요청이 오면 DispatcherServlet을 통해 적절한 핸들러와 어댑터를 반환하고 요청을 처리한다. 그 후 핸들러가 ModelAndView를 반환하고 viewResolver를 통해 실제 뷰로 변경하여 랜더링한다.
/**
* 클래스 단위 -> 메서드 단위
* @RequestMapping 클래스 레벨과 메서드 레벨 조합
*/
@Controller
@RequestMapping("/springmvc/v2/members")
public class SpringMemberControllerV2 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@RequestMapping("/new-form")
public ModelAndView newForm() {
return new ModelAndView("new-form");
}
@RequestMapping("/save")
public ModelAndView save(HttpServletRequest request, HttpServletResponse
response) {
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
ModelAndView mav = new ModelAndView("save-result");
mav.addObject("member", member);
return mav;
}
@RequestMapping
public ModelAndView members() {
List<Member> members = memberRepository.findAll();
ModelAndView mav = new ModelAndView("members");
mav.addObject("members", members);
return mav;
}
}
/** * v3
* Model 도입
* ViewName 직접 반환
* @RequestParam 사용
* @RequestMapping -> @GetMapping, @PostMapping
*/
@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {
private MemberRepository memberRepository = MemberRepository.getInstance();
@GetMapping("/new-form")
public String newForm() {
return "new-form";
}
@PostMapping("/save")
public String save(
@RequestParam("username") String username,
@RequestParam("age") int age,
Model model) {
ember member = new Member(username, age);
mberRepository.save(member);
model.addAttribute("member", member);
return "save-result";
}
@GetMapping
public String members(Model model) {
List<Member> members = memberRepository.findAll();
model.addAttribute("members", members);
return "members";
}
}
Model 파라미터
ViewName 직접 반환
@RequestParam 사용
@RequestMapping -> @GetMapping, @PostMapping
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam("username") String memberName,
@RequestParam("age") int memberAge) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam String username,
@RequestParam int age) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(String username, int age) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam(required = true) String username,
@RequestParam(required = false) int age) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
@RequestParam.required
주의 - 기본형에 null 입력
@ResponseBody
@RequestMapping("/request-param-v2")
public String requestParamV2(
@RequestParam(defaultValue = "guest") String username,
@RequestParam(defaultValue = "-1") int age) {
log.info("username={}, age={}", memberName, memberAge);
return "ok";
}
@ResponseBody
@RequestMapping("/request-param-map")
public String requestParamMap(@RequestParam Map<String, Object> paramMap) {
log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
return "ok";
}
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(@ModelAttribute HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@ResponseBody
@RequestMapping("/model-attribute-v1")
public String modelAttributeV1(HelloData helloData) {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return "ok";
}
@PostMapping("/request-body-string-v3")
public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) {
String messageBody = httpEntity.getBody();
log.info("messageBody={}", messageBody);
return new HttpEntity<>("ok");
}
//JSON 정보를 @ModelAttribute처럼 바로 객체로 변환
@ResponseBody
@PostMapping("/request-body-json-v4")
public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
HelloData data = httpEntity.getBody();
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requestBodyStringV4(@RequestBody String messageBody) {
log.info("messageBody={}", messageBody);
return "ok";
}
@RequestBody
요청 파라미터 vs HTTP 메세지 바디
@ResponseBody
//JSON
@ResponseBody
@PostMapping("/request-body-json-v2")
public String requestBodyJsonV2(@RequestBody String messageBody) throws
IOException {
HelloData data = objectMapper.readValue(messageBody, HelloData.class);
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
//JSON 정보를 @ModelAttribute처럼 바로 객체로 변환
@ResponseBody
@PostMapping("/request-body-json-v3")
public String requestBodyJsonV3(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return "ok";
}
//객체를 HTTP 메세지 바디에 직접 반환
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
log.info("username={}, age={}", data.getUsername(), data.getAge());
return data;
}
@RestController
public class MappingController {
private Logger log = LoggerFactory.getLogger(getClass());
@ResponseBody
@RequestMapping("/hello-basic")
public String helloBasic() {
log.info("helloBasic");
return "ok";
}
}
@RestController : 클래스 레벨
@ResonseBody : 메서드 레벨
@RestController 애노테이션을 사용하면, 해당 컨트롤러에 모두 @ResponseBody가 적용되는 효과가 있다.
@Controller는 반환 값이 String이면 뷰 이름으로 인식된다. 그래서 뷰를 찾고 뷰가 렌더링 된다.
@RestController는 반환 값으로 뷰를 찾는 것이 아니라, HTTP 메세지 바디에 바로 입력한다.따라서 실행 결과로 ok 메세지를 받을 수 있다.
@GetMapping("/mapping/{userId}")
public String mappingPath(@PathVariable("userId") String data) {
log.info("mappingPath userId={}", data);
return "ok";
}
//다중
@GetMapping("/mapping/users/{userId}/orders/{orderId}")
public String mappingPath(@PathVariable String userId, @PathVariable Long
orderId) {
log.info("mappingPath userId={}, orderId={}", userId, orderId);
return "ok";
}
@GetMapping(value = "/mapping-param", params = "mode=debug")
public String mappingParam() {
log.info("mappingParam");
return "ok";
}
@GetMapping(value = "/mapping-header", headers = "mode=debug")
public String mappingHeader() {
log.info("mappingHeader");
return "ok";
}
@PostMapping(value = "/mapping-consume", consumes = "application/json")
public String mappingConsumes() {
log.info("mappingConsumes");
return "ok";
}
@PostMapping(value = "/mapping-produce", produces = "text/html")public String mappingProduces() {
log.info("mappingProduces");
return "ok";
}
참고
HTTP 응답 - 정적 리소스, 뷰 템플릿
src/main/resources/static 경로에 보관하면 리소스 서비스 제공

