Exception처리는 웹에서도 구현이 가능하다. & SimpleFormController 를 이용하여 MVC 패턴을 실습해보자
1.command 클래스 생성
2.Exception 클래스
3. Authenticator 인터페이스 생성
4. Authenticator 를 구현한 클래스 생성
5. Controller 생성
6. View생성
7. FrontController 설정
참고 ★ SimpleFormController
GET 요청이 들어오면 showForm() 메소드를 호출하여 입력 폼 출력을 위한 ModelAndView 객체를 리턴.
POST 요청이 들어 오면 입력 폼 검증을 위한 onSubmit() 메소드를 호출하여 클라이언트의 요청을 처리.
1. Command 클래스 생성
package com.test1; public class LoginCommand { //DTO private String userId; private String userPwd; private String loginType;//회원등급을 구분하는 파라미터 public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserPwd() { return userPwd; } public void setUserPwd(String userPwd) { this.userPwd = userPwd; } public String getLoginType() { return loginType; } public void setLoginType(String loginType) { this.loginType = loginType; } } |
2. Exception 클래스
package com.test1; public class UserException extends Exception{ private static final long serialVersionUID = 1L; //생성자 public UserException(String str){ super(str); } } |
3. Authenticator 인터페이스 생성
package com.test1; public interface Authenticator { public void authen(String userId, String userPwd) throws UserException; } |
4. Authenticator 를 구현한 클래스 생성
package com.test1; public class LoginAuthenticatorImpl implements Authenticator{ @Override public void authen(String userId, String userPwd) throws UserException { if(!userId.equals("kim")||userPwd.equals("123")){ //입력되는 값이 일치하지 않으면 에러 발생 throw new UserException("invalid id: " + userId); } } } |
5. LoginController클래스
package 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; public class LoginController extends SimpleFormController{ private Authenticator authenticator; //의존성주입 public void setAuthenticator(Authenticator authenticator) { this.authenticator = authenticator; }
@Override //Submit 버튼을 클릭하면 자동으로 실행 protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { LoginCommand login = (LoginCommand)command;//command를 downcast try { //예외처리를 확인하러감. authenticator.authen(login.getUserId(), login.getUserPwd()); String message = "id:" + login.getUserId(); message += ",pwd: " + login.getUserPwd(); message += ",type: " + login.getLoginType(); request.setAttribute("message", message); return new ModelAndView("test1/login_ok");
} catch (Exception e) { //try문에서 에러가 발생하면 새로고침해서 다시 입력창이 조회될 수 있도록 처리 return showForm(request, response, errors);//입력창을 다시 보여주는 메소드 } }
@Override //입력창을 띄우기전에 특정데이터를 입력창에 보낼때 사용. 대표적인 예가 수정창을 띄울때 데이터 생성 작업을 기술. protected Map referenceData(HttpServletRequest request) throws Exception { List<String> loginTypes = new ArrayList<String>(); loginTypes.add("일반회원"); loginTypes.add("기업회원"); loginTypes.add("특별회원");
Map<String, List<String>> map = new HashMap<String, List<String>>(); map.put("loginTypes", loginTypes); return map; } } |
6. View
타입을 submit으로 설정해둬야 컨트롤러의 onsubmit메소드가 실행된다!
로그인타입을 referenceData 메소드를 통해 전달받아 출력할 것이므로 <c:forEach> 태그를 사용하였다.
단, items의 변수명과 보내는 데이터명이 동일해야함을 주의하자!
<%@ 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>예외처리</title> </head> <body> <form action="<%=cp%>/test1/login.action" method="post"> 아이디 : <input type="text" name="userId"/><br/> 패스워드 : <input type="text" name="userPwd"/><br/> 로그인타입 : <select name="loginType"> <c:forEach var="type" items="${loginTypes }"> <option value="${type }">${type }</option> </c:forEach> </select> <br/> <input type="submit" value="로그인"> </form> </body> </html> |
7. FrontController 설정
private Authenticator authenticator;에서 의존성 주입을 하기위해선 객체가 생성되어 있어야한다 .
그러므로 디스팻처서블릿에서 bean 객체 생성.
① authenticator의 setter에게 ref="authenticator-ref"의 객체를 전달해줘서 빈을 생성한다. (제어의 역전)
<bean name="authenticator-ref" class="com.test1.LoginAuthenticatorImpl"/>
<bean name="LoginController" class="com.test1.LoginController">
<property name="authenticator" ref="authenticator-ref"/>
</bean>
② com.test1.LoginController가 사용해야 하므로 Command 객체도 생성이 필요하다.
생성자에서 set을 하는 것과 같은 개념.
<property name="commandName" value="loginCommand"/>
<property name="commandClass" value="com.test1.LoginCommand"/>
③ formView 속성으로 정의되어 있는 페이지로 이동
<property name="formView" value="test1/login"/>
아래의 코드는와 동일한 내용은 앞선 예제에서 살펴본 생성자를 이용한 초기화와 일맥상통하다.
1. 객체생성(java)
LoginCommand loginCommand = new LoginCommand();
2. <bean>태그의 property(setter 메소드)로 객체 생성
<property name="commandName" value="loginCommand"/>
<property name="commandClass" value="com.test1.LoginCommand"/>
3. 컨트롤러 생성자를 이용한 초기화
public LoginController(){
setCommandClass(LoginCommand.class);.
setCommandName("loginCommand");
setFormView(test1/login");
setSuccessView("test1/login_ok");
}
8. 실행페이지 ① 로그인
8. 실행페이지 ② 출력페이지
MVC 전체 흐름
① 클라이언트의 요청url
② 프론트컨트롤러로 찾아감
③ 프론트컨트롤러는 매핑되는 컨트롤러 정보를 가지고 있음. 로그인컨트롤러로 가라고 핸들러매핑
④ 제일 먼저 인증작업을 위해 예외처리하는 객체 생성
⑤ 예외처리 객체 가져감
⑥ authenticator 초기화
⑦ 사용자가 담을 데이터는 loginCommand. 이 객체가 생성되야 데이터 담을 수 있음
⑧ 페이지를 띄우려면 formview 프로퍼티에 설정을 해줘야 함. 명시적으로 출력할 페이지 설정
(주석처리를 하더라도 실행됨/ 왜냐하면 login.action, login.jsp 물리적인 파일과 이름이 동일하면 스프링에서 알아서 찾아가기 때문)
⑨ 로그인컨트롤러 실행시 referenceData 메소드 제일 먼저 실행되어 페이지 출력됨
⑩ 데이터를 입력하고 submit 버튼을 클릭하면 onSubmit의 메소드 실행
# action의 이름(logins)을 물리적 파일인 login.jsp의 이름과 상이하게 설정하여 실행시 찾아가지 못한다.
# formView 프로퍼티를 이용하여 설정하면 액션의 이름과 물리적파일이름이 상이하더라도 프로퍼티를 읽어 찾아간다.
'Dev > Spring' 카테고리의 다른 글
Spring2.5 MVC - MultiActionController (0) | 2019.04.05 |
---|---|
Spring2.5 MVC - AbstractWizardFormController (0) | 2019.04.05 |
Spring2.5 MVC - SimpleUrlHandlerMapping (0) | 2019.04.05 |
Spring2.5 MVC - AbstractController & BeanNameUrlHandlerMapping & 핸들러와 컨트롤러의 종류 (0) | 2019.04.05 |
Spring2.5/iBatis 셋팅 (0) | 2019.04.05 |