요청 메서드(method)
@RequestMapping

@RequestMapping(path = "/member/join", method = {RequestMethod.GET,RequestMethod.POST}) //두개의 요청을 가져올 수 있는 상태
public String join(Model model, HttpServletRequest request){
model.addAttribute("member", "안녕하세요.");
//jsp에서 el식으로 접근 가능
System.out.println("method: "+request.getMethod());
return "member/join";
}

가입하기 했을때 Post방식으로 변경 되서 유입




@GetMapping("/join" )
public String join1(Model model, HttpServletRequest request){
System.out.println("mode없음");
return "member/join";
}
mode 없을때 mapping을 따로 넣어줘야함 400오류 나오지 않는다.
🔽 mode값 여러개 적용시


@PostMapping
@PatchMapping : 부분 수정
@PutMapping : 치환
@DeleteMapping
<공통>
👩💻참고) sysout.println 대신 로거 사용
private final Logger log = LoggerFactory.getLogger(MemberController.class);
log.fatal()
log.debug()
log.info()
log.warn()
log.error()
log.trace().. public class MemberController { private final Logger log = LoggerFactory.getLogger(MemberController.class); @GetMapping("/join" ) public String join1(Model model, HttpServletRequest request){ log.info("mode없음"); return "member/join"; } @GetMapping(path="/join",params ={"mode=join"} ) //mode값에 반드시 join이 있어야지 여기로 유입이 된다. public String join(Model model, HttpServletRequest request){ log.info("mode=join"); return "member/join"; } ..🔽🔽
- lombok 활용시
@slf4j
@log4j
@log4j2
.. 애노테이션으로 로거 연도 코드 자동 생성
변수명은 log

return "redirect:/member/login";는 클라이언트를 /member/login URL로 리다이렉트 시켜준다.contextPath+/member/login으로 리다이렉트redirect -> 뷰이동 x 주소이동 시켜주는데 HandlerAdapter가 읽고 주소 앞에 contextPath를 붙여준다.

302: 임시이동 - 요청한 페이지가 일시적으로 옮겨졌다. 즉 언제든지 이전 URL로 다시 돌아올 수 있다.
상대경로 지정시
return "redirect:member/login";
-> 현재 URL 경로를 기준으로 이동한다.
반환값으로 forward:주소 형태도 가능
해당 주소의 출력 데이터로 버퍼를 치환
RequestDispatcher

주소는 바뀌지 않음!!!
MockMvc - 컨트롤러 테스트
-> 서버를 껏다키지 않아도 알아서 코드가 반영된다.
@SpringJUnitConfig
@ContextConfiguration(classes = MvcConfig.class)
public class MemberControllerTest {
private WebApplicationContext ctx;
private MockMvc mockMvc;
@BeforeEach
void init(){
// mockMvc = MockMvcBuilders.standaloneSetup() // 특정 컨트롤러 한정 테스트
mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build(); //전체
}
}
...
webAppContextSetup(..)

서버 재로딩 없이 콘솔에서 확인 가능
@PostMapping(value = "/join", headers = "appKey=1234")
//Post방식 처리시 여기로 유입됨 요청 헤더 쪽에 appKey=1234가 있어야 이 메서드가 실행된다.
public String joinPs(RequestJoin form){
log.info("JoinPs실행...");
return "redirect:/member/login";
}
🔽


테스트 환경에서 요청헤더에 values넣어줌
@SpringJUnitWebConfig
@ContextConfiguration(classes = MvcConfig.class)
public class MemberControllerTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@BeforeEach
void init() {
mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
@Test
void test1() throws Exception {
mockMvc.perform(post("/member/join")
.header("appKey","1234") //요청헤더
)
.andDo(print());
}
}


@PostMapping(value = "/join", headers = "appKey=1234", consumes = "application/json")
public String joinPs(RequestJoin form){
log.info("JoinPs실행...");
return "redirect:/member/login"; // 절대경로 기준 이동
}


오타 방지를 위해서 enum 상수 형태로 코드 수정!
...컨트롤러
@PostMapping(value = "/join", headers = "appKey=1234", consumes = MediaType.APPLICATION_JSON_VALUE)
public String joinPs(RequestJoin form){
log.info("JoinPs실행...");
return "redirect:/member/login"; // 절대경로 기준 이동
}
...
@Test
void test1() throws Exception {
mockMvc.perform(post("/member/join")
.header("appKey","1234") //요청헤더
.contentType(MediaType.APPLICATION_JSON_VALUE)
)
.andDo(print());
}
@PostMapping(value = "/join", headers = "appKey=1234", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public String joinPs(RequestJoin form){
log.info("JoinPs실행...");
return "redirect:/member/login";
}
...
커맨드 객체 클래스명 -> EL 속성으로 자동 추가
ex) RequestJoin -> requestJoin
@PostMapping("/join")
public String joinPs(RequestJoin form){ //같은 이름의 setter가 있으면 알아서 값을 대입해준다.
log.info(form.toString()); //폼에 작성한 요청 데이터 넘어오는지 확인
return "member/join";
}
내가 요청했던 form 데이터들 el속성으로 추가 가능하다.



<input type="text" name="email" value="${requestJoin.email}">
기존 HTMl코드처럼 하면 서버 측에서 폼 데이터와 객체의 필드를 매핑하는 코드가 추가로 필요하고, 검증 로직을 따로 작성해야 하는 단점이 있다.
스프링에서 지원하는 form 형태로 바꾸기
커스텀 태그 추가
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>


RequestJoin form: 커맨드 객체
커맨드 객체가 검증 실패시 다시 양식을 보여주게 되는데..
커맨드 객체는 Post방식일때만(양식을 제출할때만) 넘어온다.
하지만 Getmapping일때는 커맨드객체로 주입된게 없다. el식에 값 비어있는 상태가 되버림

비어있으면 오류 발생함
스프링 커스텀태그를 사용할 시 커맨드객체와 동일한 이름의 객체를 유지시켜줘야한다.
Model주입!
@Slf4j
@Controller
@RequestMapping("/member")
public class MemberController {
@GetMapping("/join")
public String join(Model model) {
//값이 없더라도 비어있는 값이라도 줘야함
RequestJoin form = new RequestJoin();
model.addAttribute("requestJoin",form);
return "member/join";
}
...
@PostMapping("/join")
public String joinPs(RequestJoin form){ //같은 이름의 setter가 있으면 알아서 값을 대입해준다.
log.info(form.toString()); //폼에 작성한 요청 데이터 넘어오는지 확인
return "member/join";
}
...

🔽🔽🔽
@GetMapping("/join")
public String join(@ModelAttribute RequestJoin form) {
// 값이 없을때 RequestJoin 이름을 가지고 앞자를 소문자로 바꿔서 자동으로 만들어줌
return "member/join";
}

Get방식 요청때도 자동으로 null값 주입된 것을 확인 할 수 있다!
기본 이름은 클래스명에서 앞자를 소문자로 바꿔서 커맨드 객체 이름으로 사용했다.

value값에 입력하면 이름 바꿀 수 있다.


속성명 새롭게 만듦!༼ つ ◕_◕ ༽つ
커맨드 객체 그대로 이름을 사용하는 경우가 더 많다(. ❛ ᴗ ❛.)
Controller, RestController: 컨트롤러에서의 공통 데이터로 설정
ControllerAdvice, RestControllerAdvice: 지정된 패키지 범위에서의 공통 데이터



1) <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
2) <form:form>
3) <form:input>
4) <form:password>
스프링쪽에서 제공하는 기능을 사용하면 단순히 페이지만 연동하는 경우 컨트롤러 생성 없이 뷰만 연동해서 주소를 연결 할 수 있다.
컨트롤러 구성을 할 필요 없는 간단한 페이지 구성
WebMvcConfigurer 인터페이스

컨트롤러 없이 페이지 연동 시켜보겠듬!!!!

index.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<h1>메인 페이지</h1>
...
MvcConfig
...
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/")
.setViewName("main/index");
}
registry로 하단에 코드 추가해주면 컨트롤러없이 연동할 페이지 추가 가능함
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/")
.setViewName("main/index");
registry.addViewController("/mypage")
.setViewName("mypage/index");
}
package org.choongang.member.controllers;
public record RequestLogin2(
//값만 담을 수 있는 데이터 클래스
String email,
String password
) {}


요청 데이터가 여러개일때 ex) 체크박스

form 태그에 체크박스 기능



커맨드도 주소 같은 경우 동일 내용을 입력하는 항목이 있을것이다 -> 재활용 하고싶을때
분리!


addr.항목명
join.jsp

중첩된 커맨드 객체의 매핑 완성 ˋ( ° ▽、° )

강의자료
1. <form> 태그를 위한 커스텀 태그: <form:form>






체크박스 관련 커스텀 태그 : <form:checkboxes>, <form:checkbox>

라디오버튼 관련 커스텀 태그: <form:radiobuttons>, <form:radiobutton>

<dl>
<dt>이메일</dt>
<dd>
<form:input path="email" cssClass="input-txt" cssStyle="border-color: red"/>
</dd>
</dl>
id, title, dir
disabled, tabindex
onfocus, onblur, onchange onclick, ondblclick
onkeydown, onkeypress, onkeyup
onmousedown, onmousemove, onmouseup
onmouseout, onmouseover
각 커스텀 태그는 htmlEscape 속성을 사용해서 커맨드 객체의 값에 포함된 HTML 특수 문자를 엔티티 레퍼런스로 변환할지를 결정할 수 있다.