[Spring 2.5] SimpleFormController
by 무작정 개발2022.03.22(61일 차_화요일)
- 스프링(Spring) 2일 차
오늘 스프링의 데이터 전송 방식 및 스프링의 컨트롤러에 대해 정리할 것이다. 양이 많아 나눠서 정리할 건데
여기서는 Spring(스프링)에서의 데이터 전송 방식, SimpleFormController에 대해 정리할 것이다.
예외 처리 (Exception) & SimpleFormController
실행화면


위의 실행 화면은 이번에 만들 예제 화면이다.
1. LoginCommand 클래스 생성
- Command 클래스는 스프링에서 DTO 역할을 하는 클래스
javapackage com.test1; //Command는 스프링의 DTO public class LoginCommand { // DTO private String userId; private String userPwd; private String loginType; //회원등급을 구분하는 파라미터 // getter/setter 생성
2. 예외 처리
- 예외 처리 시 필요한 파일 : UserException클래스, Authenticator인터페이스, LoginAuthenticatorImpl 클래스
(1) - UserException.java 생성
javapackage com.test1; //예외처리 필요한 파일 public class UserException extends Exception { private static final long serialVersionUID = 1L; //에러를 처리할때 애한테 보낸다. // - 생성자 public UserException(String str) { super(str);//super는 Exception이다. } }
(2) - Authenticator.java (인터페이스)
javapackage com.test1; public interface Authenticator { //예외처리를 UserException한테 맡긴다. public void authen(String userId,String userPwd) throws UserException; }
(3) - LoginAuthenticator.java 생성
- Authenticator 인터페이스를 구현한 클래스
javapackage com.test1; //Authenticator인터페이스를 구현한 클래스 public class LoginAuthenticatorImpl implements Authenticator { @Override public void authen(String userId, String userPwd)//애를 호출했을 때 throws UserException { if(!userId.equals("suzi") || !userPwd.equals("123")) { //suzi, 123이 아니면 예외를 발생시킨다. throw new UserException("invalid id: " + userId); } } }
3. LoginController 클래스 생성
- SimpleFormController를 상속(extends) 받음
- SimpleFormController : Form을 출력하고 Form에 입력한 데이터를 처리할 때 사용된다.
- onSubmit() 메서드 : submit 버튼을 클릭하면 자동으로 실행하는 메서드
- referenceData() 메서드 : 특정 데이터를 입력창에 보낼 때 사용
javapackage com.test1; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.SimpleFormController; // SimpleFormController : 사용자가 폼에서 버튼클릭시 submit이 실행되는데 자동으로 onSubmit() 자동호출 // 창을 띄우기 전에 준비 작업 정보를 referenceData 를 가지고 창에 띄어진다. // 그리고 ok버튼누르면 submit실행이 되면 onSubmit이 실행됨 public class LoginController extends SimpleFormController { private Authenticator authenticator; // 의존성 주입(DI) - setter만 만든다. // 클래스 생성 시 자동으로 실행 public void setAuthenticator(Authenticator authenticator) { this.authenticator = authenticator; } //2. 로그인버튼을 누르면 submit이 실행되서 이 메서드를 실행한다. // 실행되면서 DTO가 command로 넘어와서 여기서 받아준다. // 그리고 _ok에 있는 {message}로 던져준다. @Override protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, //입력한 데이터는 command로 들어온다. BindException errors) throws Exception { // ok버튼을 누르면 onSubmit이 자동으로 실행되며 , 데이터는 Object command 에 넘어온다. LoginCommand login = (LoginCommand)command; try { //넘어온 ID,PWD를 넘긴다. authenticator.authen(login.getUserId(), login.getUserPwd()); String message = "id: " + login.getUserId(); message += ", pwd: " + login.getUserPwd(); message += ", type: " + login.getLoginType(); request.setAttribute("message", message); // test1폴더에 login_ok한테 넘긴다. return new ModelAndView("test1/login_ok"); } catch (Exception e) { // 로그인버튼을 누르면 화면이 바뀌므로 창을 다시 보여주게 해야한다. return showForm(request, response, errors);// 에러메시지를 가지고 입력창을 다시 띄운다.(다시 로그인을 하게끔) } } //1. 여기에 코딩한 부분이 login.jsp가 뜰때 로그인 타입에 데이터를 띄워준다. // 그래서 여기에는 타입부분에 들어갈 내용을 코딩 ( referenceData가 먼저 실행된다) @Override protected Map<String, List<String>> referenceData(HttpServletRequest request) throws Exception { List<String> loginTypes = new ArrayList<>(); loginTypes.add("일반회원"); loginTypes.add("기업회원"); loginTypes.add("특별회원"); // 추가된 리스트는 맵에 추가 Map<String, List<String>> map = new HashMap<String, List<String>>(); map.put("loginType", loginTypes);// loginType이라는 이름으로 넘긴다. return map; } }
4. View 생성 (JSP페이지 - login.jsp, login_ok.jsp 생성)
(1) - login.jsp - (로그인 시 필요한 데이터 입력)
- Type를 submit으로 설정해야 컨트롤러의 onsubmit 메서드가 실행된다.
- 로그인 타입을 referenceData 메서드를 통해 전달받아서 출력하기에 <c:each> 태그 사용
- 주의 - items의 변수명과 보내는 데이터명이 같아야 한다.
html<body> <form action="<%=cp%>/test1/login.action" method="post"> 아이디: <input type="text" name="userId"/><br/> 패스워드: <input type="password" name="userPwd"/><br/> 로그인 타입: <!-- LoginController.java의 referenceData 데이터를 가져온다. --> <select name="loginType"> <c:forEach var="type" items="${loginType }"> <option value="${type }">${type }</option> </c:forEach> </select> <br/> <!-- LoginController.java에서 onSubmit을 사용하기 때문에 type을 submit으로 한다. --> <input type="submit" value="로그인"/> </form> </body>
(2) - login_ok.jsp - (로그인 성공 시 생성한 message 출력)
html<%@ page contentType="text/html; charset=UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% request.setCharacterEncoding("UTF-8"); String cp = request.getContextPath(); %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${message } </body> </html>
5. dispatcher-servlet.xml 작성
- 여기서 2가지 작업을 해줘야 한다.
(1) pro의 key가 실제 물리적인 주소와 같으면 formView는 생략 가능
html<bean id="simpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="order" value="1"/> <!-- Spring은 어노테이션으로 쓸수있는데 수동적인 주소 어떤걸 우선할것인가 , value = 1 얘를 먼저 실행해라 --> <property name="alwaysUseFullPath" value="true"/> <property name="mappings"> <props> <!-- login.action 으로 이동하면 bean name=loginController 찾는다. --> <prop key = "/test1/login.action">loginController</prop> </props> </property> </bean>
(2) <bean name="authenticator" class="com.test 1.LoginAuthenticatorImpl"/>
- authenticator 의존성 주입에 값을 넘겨주기 위해 객체 생성
- 여기서 authenticator 값을 넘겨주기 시작
(3) 객체 생성
<property name="commandClass" value="com.test 1.LoginCommand"/>
<property name="commandName" value="loginCommand"></property>
- LoginCommand.java를 loginCommand라는 이름으로 객체 생성
- commandClass의 value값에 있는 클래스를 commandName의 value값으로 객체 생성
- LoginCommand loginCommand = new LoginCommand();와 같다.
- 항상 2개가 짝으로 같이 다님
- formView : 명시적으로 다음 화면을 띄우라고 지정해주는 것
html<!-- 예제1 (com.test1)--> <!-- authenticator의 setter에게 ref="authenticator-ref"의 객체를 전달해줘서 bean(객체) 생성 / (제어의 역전) --> <!-- property name:setter에 ref:bean으로 객체 생성한걸 넣어주면서 의존성 주입 --> <bean name="authenticator" class="com.test1.LoginAuthenticatorImpl"/> <bean name="loginController" class="com.test1.LoginController"> <!-- LoginController 에 setAuthenticator(Authenticator authenticator) 에 의존성주입을 한다. --> <property name="authenticator" ref="authenticator"></property> <!--(의존성주입) authenticator 객체를 생성해서 LoginController authenticator를 setter로 저장한다. --> <!-- com.test에 LoginController에 객체생성해준것과 같음. xml에서의 문법 --> <!-- com.test1.LoginController가 사용해야 하므로 Command 객체 생성 --> <property name="commandClass" value="com.test1.LoginCommand"/> <!-- LoginCommand 클래스를 loginCommand라는 이름으로 객체 생성 --> <property name="commandName" value="loginCommand"></property> <!-- LoginCommand의 value값에 있는 클래스를 commandName의 value값으로 객체 생성 --> <!-- LoginCommand loginCommand = new LoginCommand();와 동일 --> <!-- formView속성으로 정의되어 있는 페이지로 이동 --> <property name="formView" value="test1/login"/><!-- 처음실행시 login.jsp띄우고 에러발생시 login.jsp가 떠야한다. --> </bean>
블로그의 정보
무작정 개발
무작정 개발