Dev/Spring

Spring2.5 MVC - Exception & SimpleFormController

창문닦이 2019. 4. 5. 18:15

 

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클래스

SimpleFormController : 폼을 출력 하고 폼에 입력한 데이터를 처리할 때 사용된다.
onSubmit : Submit 버튼을 클릭하면 자동으로 실행하는 메소드이다.
referenceData메소드 : 페이지를 띄우기전에 데이터를 가져오는 작업이 필요하다. 해당 선작업을 코딩

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 프로퍼티를 이용하여 설정하면 액션의 이름과 물리적파일이름이 상이하더라도 프로퍼티를 읽어 찾아간다.