HandlerMapping
클라이언트의 요청을 어떤 Commender가 수행할지의 여부를 결정해주는 역할을 수행한다.
구현체 | 설명 |
BeanNameUrlHandlerMapping | 요청 URI와 동일한 이름을 가진 Controller 빈을 매핑한다. |
SimpleUrlHandlerMapping | 패턴과 컨트롤러의 이름을 비교 URI가 패턴에 매칭 될때 지정한 컨트롤러를 사용한다. |
ControllerClassNameHandlerMapping | URI와 매칭되는 클래스 이름을 갖는 빈을 컨트롤러로 사용 |
DefaultAnnotationHandlerMapping | @RequestMapping 어노테이션을 이용하여 요청을 처리할 컨트롤러를 구한다. |
DefaultAnnotationHandlerMapping를 많이 사용한다.
1. applicationContext.xml
2. 어노테이션
@Component : 자동으로 빈을 등록한다. 2.5에서는 Controller 를 사용한다.
@Scope
자동으로 등록되는 빈의 범위 지정
singleton, prototype , session
@Required
Setter 메서드에 지정해서 (반드시 설정)해야 하는 필수 프로퍼티 정의
@Autowired
Setter 메서드 , 생성자 메서드 또는 필드(프로퍼티)에 직접 설정 해서 자동으로 의존성 주입이 수행 되도록 구성
@Autowired with(required = false) Option
컨테이너가 자동으로 의존성 주입을 수행할때 대상 Bean을 발견하지 못해도 오류를 발생시키지 않도록 설정
@Qualifler
@Autowired와 함께 사용되어서 자동 의존성 주입이 수행될 대상 Bean을 구체적으로 설정
-자신이 직접 Bean의 이름을 지정 (Spring 2.0기준 @Service("fileManager"))
같은 타입의 Bean이 두 개 이상 등록된 경우 @Autowired에 발생될 수 있는 모호성을 제거한다.
@Resource
- 객체를 자동으로 생성 및 이름 지정 , 기본클래스를 객체로 만듬
- Spring 2.0 기준으로 @Repository("dao") 이건 db객체를 만듬
@Controller("mainasdas") - 객체를 대신 생성해주며 적당한 컨트롤러를 상속받는다.
- 적당한 컨트롤러를 알아서 상속받아서 기능을 쓸 수 있다.
- <bean name="mainController" class="com.text.mainController"> 처럼 객체를 알아서 생성해준다.
즉 MainController main.mainController = new MainController();
나중에 프로젝트가 많으면 충돌이 발생될수가 있는데 그래서 ("이름")을 주게 된다.
이름은 사용자가 주고싶은 이름으로 준다.
@RequestMapping(value="/main.action")
- 사용자가 /main.action를 쓰면 무조건 메소드 mainController 이 실행된다.
컨트롤러
예제1 : A에서 B로 데이터를 전송하는 방법
- 어떻게 데이터를 넘기는지가 중요하다.
- 2.5까지는 패키지 이름이 2개까지 괜찮았지만 3.0부터는 최소 3개 작성해야 한다.
1. TestController.java
ModelAndView
- 스프링에만 있는 반환값
- model : 데이터 + view.jsp
- 데이터와 jsp를 한번에 묶어서 반환한다.
return new ModelAndView("test/view")";
- 스프링에는 맵이 없어 데이터와 보여주는 부분을 한번에 돌려준다.
- test폴더의 view.jsp파일로 바로 보낸다.
- 원래는 /test/view.jsp 로 적어야 하나 앞에 / (슬래쉬) 와 .jsp는 항상 동일하다
-> dispatcher-servlet.xml 의 "viewRosolver" 에서 기본셋팅값으로 넣어준다.
-> / 와 jsp 생략하여 작성
-> 포워딩 진짜주소로 보냄 .jsp
package com.test;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class TestController2 extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
String msg = "";
if(hour>=6&&hour<=8) {
msg = "아침입니다.";
} else if(hour>=8&&hour<=13) {
msg = "지각입니다.";
} else if(hour>=13&&hour<=14) {
msg = "점심시간입니다.";
} else if(hour>=14&&hour<=18) {
msg = "오후입니다.";
} else {
msg = "저녁 입니다.";
}
request.setAttribute("msg", msg);
return new ModelAndView("test/view");
}
}
2. dispatcher-servlet.xml
역할 : 요청이 오면 누구한테 보내야 돼? 라고 핸들러 매핑에게 보낸다. 이 핸들러 매핑에는 종류가 4가지가 있다.
방법1. BeanNameUrlHandlerMapping
<bean id="beanNameUrlMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean name="/test/msg.action" class="test.TestController"/>
url에 /test/msg.action 이 오게되면 com.test.TestController 로 간다.
TestController 에서 retrun new ModelAndView("test/view");
데이터를 보내야하므로 ModelAndView를 객체생성하면서 test폴더의 view.jsp파일을 실행한다.
예제 2 : 스프링 DTO
스프링에서는 command 라고 한다.
1. ListCommand.java
- DTO
public class ListCommand {
private String userId;
private String userName;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
2. ListFormController
-데이터를 처리해주는 컨트롤러
- DTO를 가져오는데 DTO를 담을 그릇이 필요 그게 바로 ListFormController 이다.
- 그리고 자동으로 매개변수에 있는 command 로 들어간다.
public class ListFormController impelemtns Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response)
thrwos Exception {
return new ModelAndView("test/write"); // test폴더에 wrtie.jsp 로 이동시킨다.
}
}
3. ListController
AbstractCommandController
- DTO를 받아내는 컨트롤러
- Coomand = DTO 이다.
DTO(Command) 객체 생성한다.
생성자에서 실행
setCommandCLass(Command파일이름.java) -> 객체 생성
setCommandName(DTO객체 이름) -> 이름 설정
ListCommand listComand = new ListCommand() 와 같이 객체를 생성한 것이다.
-> 스프링에서는 이렇게 객체 생성을 하지 않는다.
스프링은 알아서 객체를 넘겨준다.
ListController
package com.test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractCommandController;
public class ListController extends AbstractCommandController {
// 생성자 생성
public ListController2() {
setCommandClass(ListCommand.class);
setCommandName("listCommand");
// ListCommand listCommand = new ListCommand();
}
@Override
protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException arg3)
throws Exception {
// 스프링이 알아서 객체를 넘겨준다.
ListCommand dto= (ListCommand)command;
String message = "이름" + dto.getUserName();
message += "<br/>아이디 : " + dto.getUserId();
request.setAttribute("message", message);
return new ModelAndView("test/wrtie_ok");
}
}
4. test > write.jsp
body부분
넘겨줄 데이터 폼을 작성한다.
<%@ 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>
<form action="<%=cp %>/test/write_ok.action" method="post">
아이디 : <input type="text" name="userId"/><br/>
이름 : <input type="text" name="userName"/><br/>
<input type="submit" value="전송하기"/><br/>
</form>
</body>
</html>
5. test > write_ok.jsp
받은 데이터 출력한다.
<%@ 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>
<h1>Command를 이용하여 데이터 전송 </h1>
<hr/><br/>
${message }
</body>
</html>
6. dispatcher-servlet.xml
방법2. SimpleUrlHandlerMapping
order : 순서
스프링에서 어노테이션을 사용하면 어노테이션의 우선순위는 항상 1순위이다.
항상 어노테이션을 먼저 찾아서 실행한다.
order의 value값을 1로 주면 이 부분을 먼저 실행(1순위) 후 여기에 없는 방법은 어노테이션에서 찾아서 처리한다.
alwaysUseFullPath
- 원래 주소 : http://locahost/spring/board/list.action (가상주소)
- value = "true" : /spring/board/list.action -> 폴더 이름(board)작성 가능
- value = "false" : /spring/list.action -> 폴더를 사용할 수 없어 action 이름을 다르게 작성한다.
<!--방법2 : SimpleHandlerMapping -->
<bean id="SimpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="2"/>
<property name="alwaysUserFullPath" value="true"/>
<property name="mappings">
<props>
<!-- prop에 적는건 사용자 정의(listFormController)
<!-- key의 주소는 변경 가능 : 이 주소는 가상의 주소이다.
<prop key="/test/wrtie.action">listFormController</prop>
<prop key="/test/write_ok.action">listController</prop>
</props>
</property>
</bean>
<!-- ListFormController & ListController 객체 생성 -->
<!-- 위의 생성한 prop의 사용자 정의 이름과 동일하다 -->
<bean name="listFormController" class="com.test.ListFromController"></bean>
<bean name="listController" class="com.test.ListController"></bean>
예제 3 : 예외처리
1. LoginCommand.java ( DTO 역할을 함 )
package com.test1;
public class LoginCommand { // command 는 String에서의 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. 예외 처리
= 예외처리할때 필요한 파일이다.
-UserException java , Authenticator.java , LoginAuthenticator.java
1. UserException java
package com.test1;
public class UserException extends Exception {
private static final long serialVersionUID = 1L;
public UserException(String str) {
super(str);
}
}
2. Authenticator.java // 어샌틱케이터
package com.test1;
public interface Authenticator {
public void authen(String userid, String userPwd) throws UserException;
// 예외 처리를 떠넘긴다. UserException한테
// UserException은 부모 Exception를 상속받고있어서 super(str) 오류메시지 출력
}
3. LoginAuthenticator.java
- 로그인성공
-아이디 : kim
-비밀번호 : 123
package com.test1
public class LoginAuthenticatorImpl implements Authenticator {
@Override
public void authen(String userId,String userPwd) throws UserException {
// 예외를 발생시킴
if(!userId.equals("suzi") || !userPwd.equals("123")) {
throw new UserException("invalid id : " + userId);
}
}
}
3. LoginController.java
onSubmit 메소드
= submit 버튼을 클릭하면 자동으로 실행된다.
=command : dto가 자동으로 들어온다.
넘어온 dto를 받는다.
LoginCommand login = (LoginCommand)command;
지금은 login으로 받았지만 나중에는 dto로 작성한다.
showForm
- 스프링의 객체
- 로그인 실패 시 입력창(login.jsp)를 다시 띄어준다.
- referenceData 메소드
- 특정 데이터를 입력창에 보낼 때 사용한다.
- 예 ) 수정창을 띄울때 수정창에서 보여줄 데이터를 생성하는 작업을 기술한다.
referenceData를 알아서 읽어가 login.jsp 화면을 띄울때 데이터가 넘어가 사용이 가능하다.
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 LoginController2 extends SimpleFormController {
private Authenticator authenticator;
// 의존성 주입(DI) : setter 만 만든다
// 클래스 생성 시 자동으로 실행된다.
public void setAuthenticator(Authenticator authenticator) {
this.authenticator = authenticator;
}
// submit버튼을 눌렀을때 실행
@Override
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,
BindException errors) throws Exception {
// command 로 객체가 넘어옴
LoginCommand login = (LoginCommand)command; // 데이터가 넘어온다.
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) {
return showForm(request,response,errors);
}
}
// submit보다 먼저 실행되어야 함
@Override
protected Map<String, List<String>> referenceData(HttpServletRequest request) throws Exception {
// map 에 담아내야 하니까 map.put(String,list<String>)
List<String> loginTypes = new ArrayList<>(); // 담을 곳
loginTypes.add("일반회원");
loginTypes.add("기업회원");
loginTypes.add("특별회원");
// 추가된 리스트는 map에 추가
Map<String , List<String>> map = new HashMap<String,List<String>>();
map.put("loginType", loginTypes);
return map;
}
}
4. login.jsp
- 로그인 시 필요한 데이터 입력
<body>
<form action="<%=cp%>/test1/login.action" method="post">
아이디:<input type="text" name="userId"><br/>
패스워드 : <input type="text" name="userPwd"><br/>
로그인 타입:
<!--LoginController.java의 referenceData 데이터를 가져온다.-->
<select name="loginType">
<c:forEach var="type" items="${loginType}">
<option value="${type}">${type}</option>
</c:forEach>
</select>
<-- LoginController.java에서 onSubmit를 사용하기 때문
<input type="submit" value="로그인">
</form>
</body>
5. login_ok.jsp
로그인 성공 시 생성한 message 출력
<body>
<h2> 에러처리를 이용하 ㄴ로그인</h2>
<hr/><br/>
${message}
</body>
6. dispatcher-servlet.xml
prop의 key가 실제 물리적인 주소가 같으면 formView는 생략이 가능하다.
다만 key의 주소는 사용자 정의로 , key의 값이 실제 물리적인 주소와 다르면 formView를 다시 작성해야 한다.
<bean id="SimpleUrlMapping" class="org.springframework.web.servlet.handelr.SimpleUrlHandlerMapping">
<property name="order" value="1"></property>
<property name="alwaysUseFullPath" value="true"></property>
<property name="mappings">
<props>
<prop key="/test1/login.action">loginController</prop>
<props>
</property>
</bean>
2. <bean name="authenticator-ref" class="com.test1.LoginAuthenticatorImpl"/>
- authenticator 의존성 주입에 값을 넘겨주기 위해 객체 생성
- 여기서 authenticator 값을 넘겨주기 시작
3. 객체 생성
<property name="commandName" value="loginCommand"/>
<property name="commandClass" value="com.test1.LoginCommand"/>
- LoginCommand.java를 loginCommand라는 이름으로 객체 생성
- commandClass의 value값에 있는 클래스를 commandName의 value값으로 객체 생성
LoginCommand loginCommand = new LoginCommand(); 같은 것
- 항상 2개가 짝으로 다닌다
4. formView
명시적으로 다음 화면을 띄우라고 지정해주는 것
<bean name="authenticator-ref" class="com.test1.LoginAuthenticatorImpl"/>
<bean name="loginController" class="com.test1.LoginController">
<!-- authenticator 의존성 주입에서 값을 넘겨주는 부분 -->
<!-- 제어의 역전 -->
<property name="authenticator" ref="authenticator-ref"/>
<property name="commandName" value="loginCommand"/>
<property name="coomandClass" value="com.test1.LoginCommand"/>
<propery name="formView" value="test1/lgoin"/>
</bean>
'BACKEND > 스프링 Spring' 카테고리의 다른 글
[spring2.5] 스프링 Annotation (0) | 2022.03.23 |
---|---|
[spring2.5] 스프링 간단한 예제(2) (0) | 2022.03.23 |
[Spring2.5] 스프링 2.5 환경 설정 (0) | 2022.03.22 |
[spring2.5]스프링 프레임워크 시작 (0) | 2022.03.22 |
[Spring2.5] 스프링 환경설정 (0) | 2022.03.22 |