출처: https://bumcrush.tistory.com/182 [맑음때때로 여름]

- preHandle()

컨트롤러가 호출되기 전에 실행된다. handler 파라메터는 핸들러 매핑이 찾아 준 컨트롤러 빈 오브젝트다. 컨트롤러 실행 이전에 처리해야 할 작업이 있다거나, 요청정보를 가공하거나 추가하는 경우에 사용할 수 있다. 또는 요청에 요청에 대한 로그를 남기기 위해 사용하기도 한다. 리턴 값이 true 이면 핸들러 실행 체인의 다음 단계로 진행되지만, false 라면 작업을 중단하고 리턴 하므로 컨트롤러와 남은 인터셉터들은 실행되지 않는다.
– postHandle() 

컨트롤러를 실행하고 난 후에 호출된다. 이 메소드에는 컨트롤러가 돌려준 ModelAndView 타입의 정보가 제공 되서 컨트롤러 작업 결과를 참조하거나 조작할 수 있다.
–afterCompletion() 

이름 그대로 모든 뷰에서 최종 결과를 생성하는 일을 포함한 모든 작업이 모두 완료된 후에 실행된다. 요청처리 중에 사용한 리소스를 반환해주기에 적당한 메소드다.

 

핸들러 인터셉터는 하나 이상을 등록할 수 있다. preHandle() 은 인터셉터가 등록된 순서대로 실행된다. 반면에 postHandle() 과 afterCompletion() 은 preHandle() 이 실행된 순서와 반대로 실행된다.

 

 

 

HandlerInterceptor를 통한 요청 가로채기

 

 

HandlerInterceptor 인터페이스의 구현
– 핸들러 인터셉터는 HandlerInterceptor 인터페이스를 구현해서 만든다. 이 인터페이스를 구현 할 경우 사용하지 않는 메서드도 구현 해주어야 한다.
– 이러한 불편함을 줄여주기 위해 HandlerInterceptorAdaptor 클래스를 제공.
– HandlerInterceptor 인터페이스를 구현해야 하는 클래스는 HandlerInterceptorAdaptor 클래스를 상속 받은 뒤 필요한 메서드만 오버라이딩 하여 사용.

 

 

 

1. HandlerMapping에 HandlerInterceptor 설정 하기

 

 

HandlerInterceptor를 구현 한 뒤에는 <mvc:interceptors> 의 interceptors 프로퍼티를 사용해

HandlerInterceptorAdaptor 를 등록해 주면 된다.

xmlns:mvc가아니라 생략되어 있으므로 <interceptors>로 등록했다.

 

2. HandlerInterceptor 인터페이스의 구현

 

 

 

예외처리

 

 

 

 

@ExceptionHandler 어노테이션을 이용한 처리

 

– AnnotationMethodHandlerExceptionResolver 클래스는 @Controller 어노테이션이 적용된 클래스에서 @ExceptionHandler 어노테이션이 적용된 메서드를 이용해서 예외 처리한다. @ModelAttribute 에서 ExceptionHandler 에서 지정한 예외가 발생하면 @ExceptionHandler가 적용된 메서드를 이용해서 뷰를 지정.

 

 

mypage3에서 강제로 예외를 발생시켜보았다. 에러가 발생시 error/nullpoiner.jsp로 이동한다.

 

 

'spring' 카테고리의 다른 글

[스프링] 웹소켓 : 채팅  (0) 2021.01.29
[스프링] 메일발송하기  (0) 2021.01.25
[스프링] REST API / @RequestBody @ResponseBody , HttpMessageConverter  (0) 2021.01.20
[스프링] mapper / CRUD  (0) 2021.01.15
[스프링] mybatis  (0) 2021.01.12
[스프링] jdbc  (0) 2021.01.11
[스프링] 파일업로드  (0) 2021.01.08

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper 
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.aia.op.member.dao.MemberDao">

	<!-- Member 타입의 resultMap : 로그인시 사용 -->
	<resultMap id="memberResult"
		type="com.aia.op.member.domain.Member">
		<id column="idx" property="idx" />
		<result column="memberid" property="memberid" />
		<result column="membername" property="membername" />
		<result column="password" property="password" />
		<result column="memberphoto" property="memberphoto" />
		<result column="regdate" property="regdate" />
	</resultMap>


 <!-- Member 타입인데 위랑 다르게 비밀번호 안받음 -->
 
	<resultMap id="memberListResult"
			 type="com.aia.op.member.domain.Member">
		<id column="idx" property="idx" />
		<result column="memberid" property="memberid" />
		<result column="membername" property="membername" />
		<result column="memberphoto" property="memberphoto" />
		<result column="regdate" property="regdate" />
	</resultMap>




	<!-- 회원가입 -->
	<insert id="insertMember"
		parameterType="com.aia.op.member.domain.Member">
		
		INSERT INTO member
		
		<if test="memberphoto == null">		
		(memberid, password, membername)
		VALUES 
		(#{memberid},#{password},#{membername})
		</if>
		
		<if test="memberphoto != null">
		(memberid, password, membername, memberphoto)
		VALUES 
		(#{memberid},#{password},#{membername},#{memberphoto})
		</if>
		
		
		
	</insert>
	
	
	
	

	<!-- 로그인 -->
	<select id="selectLogin" resultMap="memberResult">
		select * from member where memberid=#{param1} and password=#{param2}
	</select>


	<!-- 회원의 총 수 -->
	<select id="selectTotalCount" resultType="int">
		select count(*) from
		member
	</select>


<!-- 멤버 리스트 구하기 -->
	<select id="selectMemberList"
					parameterType="map"
					resultMap="memberListResult">

		select * from member 
		<where>
			<if test="searchParam != null">
				<if test="searchParam.searchType == 'id'">
					<include refid="searchId"/>
				</if>
				<if test="searchParam.searchType == 'name'">
					<include refid="searchName"/>
				</if>
				<if test="searchParam.searchType == 'both'">
					<include refid="searchId"/>
					<include refid="searchName"/>
				</if>
			</if>
		</where>
		
		
		limit #{index}, #{count}

	</select>
	
	
	
	<!-- 검색 시 검색 결과에 나오는 회원의 수 구하기 -->
	<select id="selectSearchMemberCount" 
	        parameterType="com.aia.op.member.domain.SearchParam"
	        resultType="int"
	        >
	        
		select count(*) from member
		
		<!-- where idx>0  -->
		
		<where>
			<if test="searchParam.searchType == 'id'">
				  <!-- memberid like	concat('%',#{keyword},'%') -->
				  <include refid="searchId"/>
			</if>
			
			<if test="searchParam.searchType == 'name'">
				 <!-- membername like	concat('%',#{keyword},'%') -->
				 <include refid="searchName"/>
			</if>
			
			<if test="searchParam.searchType == 'both'">
				 <!-- membername like	concat('%',#{keyword},'%') 				 
				 or 
				 memberid like	concat('%',#{keyword},'%') --> 
				 <include refid="searchId"/>
				 <include refid="searchName"/>
			</if>
		</where>
		
			
	</select>
	
	
<!-- 가져다가 쓸수 있는 반복적인 sql문 만들기 / 아이디찾기 이름으로찾기 -->
	<sql id="searchId">
		or memberid like	concat('%',#{searchParam.keyword},'%')
	</sql>
	
	<sql id="searchName">
	  or membername like	concat('%',#{searchParam.keyword},'%')
	</sql>
	
	
<!-- 삭제 -->
	<delete id="deleteMemberByIdx">
		delete from member where idx=#{idx}
	</delete>


<!-- IDX를 기반으로 멤버찾기 -->
	<select id="selectMemberByIdx"
	        resultMap="memberListResult">
																		<!-- no를 쓴이유는 #{idx}가 아니어도 된다는 것을 보여주기위해 -->
		select * from member where idx=#{no}
		
	</select>



	<!-- 수정하기 -->
	<update id="updateMember"
					parameterType="com.aia.op.member.domain.Member">
	
		update member 
		set membername=#{membername}, 
				password=#{password}, 
				memberphoto=#{memberphoto}
		where idx=#{idx}  
	
	</update>









</mapper>d

'spring' 카테고리의 다른 글

[스프링] 메일발송하기  (0) 2021.01.25
[스프링] REST API / @RequestBody @ResponseBody , HttpMessageConverter  (0) 2021.01.20
[스프링] 인터셉터 / intercepter  (0) 2021.01.15
[스프링] mybatis  (0) 2021.01.12
[스프링] jdbc  (0) 2021.01.11
[스프링] 파일업로드  (0) 2021.01.08
[스프링] MVC - 컨트롤러 구현  (0) 2021.01.08

설정하기

 

pom.xml에 라이브러리 등록해주기.

스프링 트랜잭션은 별다른 이유가 없는한 스프링프레임워크 버전과 맞춰준다. (나는 3.1.1이었음)

 

sqlsessionfactory bean등록하기 (id=SqlSessionFactory와 SqlSessionTemplate부분)

경로 안에있는 모든 xml파일을 mapper로사용하겠다는뜻

 

아직 mapper가 없어서 warn이뜨지만 제대로 실행되는 것을 볼 수 있다.

 

 

 

SqlSessionTemplate을 이용한 DAO 구현

 

예제1)

 

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

Mapper 작성 (id=selectAll)

 

 

package com.aia.firstspring.member.dao;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.aia.firstspring.domain.Member;

@Repository
public class MybatisMemberDao {
	
	
	private String nameSpace = "com.aia.firstspring.mybatis.mapper.memberMapper";
	@Autowired
	private SqlSessionTemplate template;
	
	public List<Member> selectMemberList(){
		return template.selectList(nameSpace + ".selectAll");
	}

}

Dao 작성

이전 코드와 비교했을때 Mybatis를 이용하면 코드가 매우간결해지는 것을 볼 수 있다.

(물론 서비스에서 Dao를 바꿔줘야하는 것 잊지말자)

 

 

 

예제2)

mapper 작성

 

	public int insertMember(Member member) {
		return template.update(nameSpace+ ".insertMember", member);
	}

Dao

 

 

예제3) 외래키값 가져오기.

 

이렇게 keyproperty를 이용하면 idx값을 받아올 수 있다.

 

 

자동 매퍼 생성 기능을 이용한 DAO 구현

 

package com.aia.firstspring.member.dao;

import java.util.List;

import com.aia.firstspring.domain.Member;

public interface MemberInterfaceDao {

	
	//abstract public 생략	
	List<Member> selectMemberList();
	int insertMember(Member member);
	int totalCount();
}

인터페이스생성!

MyBatis는 인터페이스를 이용해서 런타임에 매퍼 객체를 생성하는 기능을 제공한다.

 

마찬가지로 서비스에서 Dao를 바꿔줘야하는 것 잊지말아야하고

template를 주입받아야 한다.

 

Mapper

mapper에서는 인터페이스 안에 있는 메서드와 이름을 같에 만들어 주는 것이 중요하다.

이름이 같아야 자동으로 인식되기 때문이다 :)

 

'spring' 카테고리의 다른 글

[스프링] REST API / @RequestBody @ResponseBody , HttpMessageConverter  (0) 2021.01.20
[스프링] 인터셉터 / intercepter  (0) 2021.01.15
[스프링] mapper / CRUD  (0) 2021.01.15
[스프링] jdbc  (0) 2021.01.11
[스프링] 파일업로드  (0) 2021.01.08
[스프링] MVC - 컨트롤러 구현  (0) 2021.01.08
[스프링] MVC : 패턴  (0) 2021.01.08

mysql / hikariCP / springjdbc라이브러리를 pom.xml에 등록

 

스프링은 버전에 맞춰서 라이브러리를 추가해주는데,

스프링 버전이 바뀔때마다 자동으로 바뀌게 하려면 이런식으로 값을 넣어주면 된다.

 

 

데이터 베이스 / JdbcTemplate 클래스 빈 등록 / root-context.xml

package com.aia.firstspring.domain;

import java.sql.Timestamp;
import java.util.Date;

public class Member {
	
	private int idx;
	private String memberid;
	private String password;
	private String membername;
	private String memberphoto;
	private Timestamp regdate;
	public int getIdx() {
		return idx;
	}
	public void setIdx(int idx) {
		this.idx = idx;
	}
	public String getMemberid() {
		return memberid;
	}
	public void setMemberid(String memberid) {
		this.memberid = memberid;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getMembername() {
		return membername;
	}
	public void setMembername(String membername) {
		this.membername = membername;
	}
	public String getMemberphoto() {
		return memberphoto;
	}
	public void setMemberphoto(String memberphoto) {
		this.memberphoto = memberphoto;
	}
	public Timestamp getRegdate() {
		return regdate;
	}
	public void setRegdate(Timestamp regdate) {
		this.regdate = regdate;
	}
	
	
	public Date getToDate() { // ${member.toDate}
		return new Date(getRegdate().getTime());
		
	}
	
	
	
	
	@Override
	public String toString() {
		return "Member [idx=" + idx + ", memberid=" + memberid + ", password=" + password + ", membername=" + membername
				+ ", memberphoto=" + memberphoto + ", regdate=" + regdate + "]";
	}
	
	

}

 

 

 

예제1) 회원리스트출력

 

Memberdao [@Reporitory]로 Dao를 등록해준다 (bean등록안해도 간단하게 등록가능)

package com.aia.firstspring.member.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.aia.firstspring.domain.Member;


@Repository
public class MemberDao {
	
	
	@Autowired
	private JdbcTemplate template;

	
	// jdbctemplate template 인스턴스를 주입
	// 1. 생성자 주입방식
	// 2. 프로퍼티 주입 방식
	// 3. 자동주입
	
	// 생성자를 이용한 객체 주입
	/*
	 * public MemberDao(JdbcTemplate t) { template = t;
	 * System.out.println("MemberDao 인스턴스 생성");
	 * 
	 * }
	 */
	
	public List<Member> selectMemberList() {
		String sql="select*from member order by memberid";
		
			return template.query(sql, new RowMapper<Member>() {

				@Override
				public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
					Member member = new Member();
					member.setIdx(rs.getInt("idx"));
					member.setMemberid(rs.getString("memberid"));
					member.setMembername(rs.getString("membername"));
					member.setPassword(rs.getString("password"));
					member.setMemberphoto(rs.getString("memberphoto"));
					member.setRegdate(rs.getTimestamp("regdate"));
					return member;
				}
			}	
				
			);
	}
	
	public int selectTotalCount() {
		String sql = "select count(*) from member";
		return template.queryForObject(sql, Integer.class);
	}
}

 

 

MemberListController

package com.aia.firstspring.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.aia.firstspring.member.service.MemberListService;

@Controller
public class MemberListController {
	
	@Autowired
	private MemberListService listService;
	
	
	@RequestMapping("/member/list")
	public String getMemberList(Model model) {	
		
		model.addAttribute("members",listService.getMemberList());
		model.addAttribute("memberCnt", listService.getMemberTotalCount());
		
		return "member/list";		
	}

}

MemberListService

package com.aia.firstspring.member.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aia.firstspring.domain.Member;
import com.aia.firstspring.member.dao.MemberDao;

@Service
public class MemberListService {
	
	@Autowired
	MemberDao dao;
	
	/*
	 * public MemberListService(MemberDao dao) { this.dao=dao; }
	 */
	
	// 회원목록 반환 메서드
	public List<Member> getMemberList(){		
		return dao.selectMemberList();
	}
	
	// 회원수 몇명인지 int로 반환해주는 메서드
	public int getMemberTotalCount() {		
		return dao.selectTotalCount();
	}

}

view > list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Member List</title>
</head>
<body>

	<h1>회원리스트</h1>

	<hr>
	${members}
	
	<h3>총회원수 ${memberCnt}</h3>

	<table>
		<tr>
			<th>idx</th>
			<th>id</th>
			<th>password</th>
			<th>name</th>
			<th>사진</th>
			<th>가입일</th>
		</tr>
		
		<c:forEach items="${members}" var="member"> 
			<tr>
				<td>${member.idx}</td>
				<td>${member.memberid}</td>
				<td>${member.password}</td>
				<td>${member.membername}</td>
				<td>${member.memberphoto}</td>
				<td>${member.toDate}</td>
			</tr>
		</c:forEach>
		
	</table>

</body>
</html>

 

 

 

 

예제2 ) 회원가입하기

 

컨트롤러 > 회원가입 성공시 리스트출력으로

package com.aia.firstspring.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.aia.firstspring.domain.Member;
import com.aia.firstspring.member.service.MemberRegService;

@Controller
@RequestMapping("/member/reg")
public class MemberRegController {
	
	@Autowired
	private MemberRegService regService;

	@RequestMapping(method = RequestMethod.GET)
	public String getRegForm() {
		return "member/regForm";
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public String memberReg(Member member, Model model) {
		
		int resultCnt = regService.insertMember(member);
		String view="member/reg";
		model.addAttribute("resultCnt", resultCnt);
		
		if(resultCnt==1) {
			view= "redirect:/member/list";
		}
		return view;
	}
}

서비스

package com.aia.firstspring.member.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aia.firstspring.domain.Member;
import com.aia.firstspring.member.dao.MemberDao;

@Service
public class MemberRegService {

	@Autowired
	private MemberDao dao;

	public int insertMember(Member member) {
		int result=0;
		try {
			result = dao.insertMember(member);
		}catch (Exception e){
			e.printStackTrace();
			
		}
		return result;
		
	}
}

MemberDao에 회원가입 메서드 추가

	public int insertMember(Member member) {
		//그냥 세개만 하기로 했음 ㅎ..
		String sql="insert into member (memberid, membername, password) values (?,?,?)";
		return template.update(sql, member.getMemberid(), member.getMembername(), member.getPassword());
		
	}

 

 

RegForm / name속성 맞춰줄것

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 폼</title>
</head>
<body>

<h1>회원 가입 폼</h1>
<form method="post">
아이디 <input type="text" name="memberid"><br>
비밀번호 <input type="password" name="password"><br>
이름 <input type="text" name="membername"><br>
<input type="submit">


</form>
</body>
</html>

reg / 가입 실패시 나오는 창

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 폼</title>
</head>
<body>

<h1>회원 가입 실패</h1>
${resultCnt}


</form>
</body>
</html>

'spring' 카테고리의 다른 글

[스프링] 인터셉터 / intercepter  (0) 2021.01.15
[스프링] mapper / CRUD  (0) 2021.01.15
[스프링] mybatis  (0) 2021.01.12
[스프링] 파일업로드  (0) 2021.01.08
[스프링] MVC - 컨트롤러 구현  (0) 2021.01.08
[스프링] MVC : 패턴  (0) 2021.01.08
[스프링] DI / xml 설정파일 / 어노테이션  (0) 2021.01.06

 

 

MultipartResolover 설정

 

Multipart 지원 기능을 사용하려면 MultipartResolver를 스프링 설정 파일에 등록해야 한다.

Multipart 형식으로 데이터가 전송된 경우 해당 데이터를 스프링 MVC에서 사용 가능 하도록 변환해준다.

Commons FileUpload API 라이브러리를 이용해서 Multipart를 처리해 준다.

CommonsMultipartResolver를 MultipartResolver로 사용하기 위해서는 “multipartResolver” 이름의 빈으로 등록

 

 

파일업로드의 방법

1.@Requestparam 애노테이션을 이용한 업로드 파일 접근

2. MultipartHttpServletRequest 이용한 업로드 파일 접근

3. 커맨드 객체를 통한 업로드 파일 접근

MultipartRequest 인터페이스가 제공하는 메소드

 

입력받는 uploadForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1>파일업로드</h1>
<hr>
<h3>@RequestParam 이용한 파일 업로드</h3>
<form action="upload1" method="POST" enctype="multipart/form-data">
 
	 <!-- /fisrtspring/upload/uploadForm > /fisrtspring/upload/upload -->
	 
	 학번 : <input type="text" name="sn"><br>
	 리포트 파일 : 	<input type="file" name="report"><br>
	 <input type="submit">
	
</form>

<hr>
<h3>MultipartHttpServletRequest를 이용한 파일 업로드</h3>
<form action="upload2" method="POST" enctype="multipart/form-data">
	 
	 학번 : <input type="text" name="sn"><br>
	 리포트 파일 : 	<input type="file" name="report"><br>
	 <input type="submit">
	
</form>



<hr>
<h3>커맨드 객체를 통한 업로드 파일 접근</h3>
<form action="upload3" method="POST" enctype="multipart/form-data">
	 
	 학번 : <input type="text" name="sn"><br>
	 리포트 파일 : 	<input type="file" name="report"><br>
	 <input type="submit">
	
</form>

</body>
</html>

컨트롤러 FileuploadController.java

package com.aia.firstspring.controller;

import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.aia.firstspring.domain.ReportUploadRequest;

@Controller
public class FileuploadController {

	final String uri = "/uploadfile";

	@RequestMapping("/upload/uploadForm")
	public String uploadForm() {
		return "upload/uploadForm";
	}

	
	
	@RequestMapping("/upload/upload1")
	public String upload1(
			@RequestParam("sn") String sn,
			@RequestParam("report") MultipartFile report, 
			Model model,
			HttpServletRequest request) throws IllegalStateException, IOException {

		System.out.println(report.getOriginalFilename());

		model.addAttribute("sno", sn);
		model.addAttribute("reportFile", report.getOriginalFilename());
		
		// 파일의 저장
		report.transferTo(getFile(request, uri, report.getOriginalFilename()));

		return "upload/uploadComplete";
	}

	
	
	
	
	@RequestMapping("/upload/upload2")
	public String upload2(MultipartHttpServletRequest request, Model model) throws IllegalStateException, IOException {

		String sn = request.getParameter("sn");
		MultipartFile report = request.getFile("report");

		System.out.println(report.getOriginalFilename());

		model.addAttribute("sno", sn);
		model.addAttribute("reportFile", report.getOriginalFilename());
		
		// 파일 저장
		report.transferTo(getFile(request, uri, report.getOriginalFilename()));

		return "upload/uploadComplete";
	}
	
	
	

	@RequestMapping("/upload/upload3")
	public String upload3(
			ReportUploadRequest uploadrequest,
			Model model,
			HttpServletRequest request) throws IllegalStateException, IOException {

		System.out.println(uploadrequest.getReport().getOriginalFilename());

		model.addAttribute("sno", uploadrequest.getSn());
		model.addAttribute("reportFile", uploadrequest.getReport().getOriginalFilename());
		
		// getReport = 멀티파트파일
		uploadrequest.getReport().transferTo(getFile(request, uri,uploadrequest.getReport().getOriginalFilename())); 

		return "upload/uploadComplete";
	}


	
	
	
	/*
	  private String getRealpath(HttpServletRequest request, String uri) { return
	  request.getSession().getServletContext().getRealPath(uri); }
	 */

	
	// File 객체를 생성해서 반환
	private File getFile(HttpServletRequest request, String uri, String fileName) {
		String rpath = request.getSession().getServletContext().getRealPath(uri);
		File newFile = new File(rpath, fileName);
		return newFile;
	}
}

커맨드 객체를 이용하기 위한 ReportUploadRequest.java

package com.aia.firstspring.domain;

import org.springframework.web.multipart.MultipartFile;

public class ReportUploadRequest {
	
	private String sn;
	private MultipartFile report;
	
	public String getSn() {
		return sn;
	}
	public void setSn(String sn) {
		this.sn = sn;
	}
	public MultipartFile getReport() {
		return report;
	}
	public void setReport(MultipartFile report) {
		this.report = report;
	}

	
}

 

결과 view / uploadeComplete.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1> 학생 1 학번 : ${sno} , 리포트 파일 : ${reportFile}</h1>
<img alt="레포트이미지" src="../uploadfile/${reportFile}">

</body>
</html>

 

 

 

hunit.tistory.com/190

 

Spring〃Dispatcher Servlet / HandlerMapping 설정

MVC 패턴 흐름을 정리하면서 새로운 용어인 DispatcherServlet이라는게 새로 튀어나왔죠? 바로 저번글에서 한번에 정리할까 하다가 그냥 따로 하나의 주제로 정리하는게 낫다 싶어서 게시글을 분리했

hunit.tistory.com

 

hunit.tistory.com/189

 

Spring〃스프링 MVC 패턴의 흐름

스프링 프레임워크 기반으로 게시판을 짜기 위해 MVC(Model / View / Controller) 패턴을 사용할 예정이라 이번글에서 정리해보도록 하겠습니다. 스프링 MVC 패턴은 좀 복잡한 구조를 가지고 있지만, 며

hunit.tistory.com

 

 

'memo' 카테고리의 다른 글

최근 에러 참고  (0) 2021.02.03
[스프링] ajax 참고  (0) 2021.01.29
RESTCLIENT  (0) 2021.01.28
tomcat서버 에러 발생시 해결 방법  (0) 2020.12.28
Server Tomcat v8.5 Server at localhost failed to start  (0) 2020.12.23
과제  (0) 2020.11.14
이클립스(Eclipse) 개발환경 / uft-8  (0) 2020.11.02

컨트롤러 구현

 

 

@Controller 애노테이션 이용을 권장하며,

@Controller & @RequestMapping 는 구현을 위한 필수 애노테이션이다.

@Controller Controller 클래스 정의 
@RequestMapping HTTP요청 URL을 처리할 Controller 메소드 정의 
@RequestParam HTTP 요청에 포함된 파라미터 참조 시 사용 
@ModelAttribute HTTP 요청에 포함된 파라미터를 모델 객체로 바인딩

                                 @ModelAttribute의 ‘name’으로 정의한 모델 객체를 다음 View에게 사용 가능

 

 

 

문법

1. 요청 URL만 선언할 경우

@RequestMapping("/요청url")

2. 요청방식을 지정한 경우

@RequestMapping( value="/요청url" method=RequestMethod.메서드방식(ex)get/post)

 

Controller의 처리 결과를 보여줄 View 지정 방법 / 메소드의 반환 값에 따른 view page지정 방법

1. ModelAndView인 경우

setViewName() 메소드 파라미터로 설정

2. String인 경우

메소드의 리턴 값

 

 

 

예제

 

RequestMapping 예제 - 요청방식 지정에 따른 경우 

package com.aia.firstspring.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.aia.firstspring.member.domain.LoginRequest;

@Controller
@RequestMapping("/member/login")
public class memberLoginController {
	//사용자의 요청 url 처리해야될 기능, 메서드를 바인딩 하는 것이 컨트롤러다.
	
	// @RequestMapping(value = "/member/login", method = RequestMethod.GET)
		@RequestMapping(method = RequestMethod.GET)
		public ModelAndView getLoginForm() {
			return new ModelAndView("member/loginForm"); // setViewName과 동일, 
		}
		
		// @RequestMapping(value = "/member/login", method = RequestMethod.POST)
		@RequestMapping(method = RequestMethod.POST)
		public ModelAndView login() {

			ModelAndView mav = new ModelAndView();
			mav.setViewName("/member/login"); // 로그인 되었을 때 보이는 페이지 -> mapping에 밸류가 동일해서 오류 생김
			return mav;
		}

	}

 

 

 

사용자의 파라미터값을 받는 방법
1. HttpServletRequest 객체 이용
2. @RequestParam(폼의 네임속성)
3. 커맨드 객체(Beans) 이용

 

 

 

@RequestParam 예제 = @RequestParam(폼의 네임속성) 

package com.aia.firstspring.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.aia.firstspring.member.domain.LoginRequest;

@Controller
@RequestMapping("/member/login")
public class memberLoginController {
	//사용자의 요청 url 처리해야될 기능, 메서드를 바인딩 하는 것이 컨트롤러다.
	
	// @RequestMapping(value = "/member/login", method = RequestMethod.GET)
		@RequestMapping(method = RequestMethod.GET)
		public ModelAndView getLoginForm() {
			return new ModelAndView("member/loginForm"); // setViewName과 동일, 
		}
		
		// @RequestMapping(value = "/member/login", method = RequestMethod.POST)
		@RequestMapping(method = RequestMethod.POST)
		public ModelAndView login(
				@RequestParam("uid") String uid,
				@RequestParam("pw") String pw) {
			//리퀘스트파람이 파라미터를 받아올 수 있게 해준다.

			ModelAndView mav = new ModelAndView();
			mav.setViewName("/member/login"); // 로그인 되었을 때 보이는 페이지 -> mapping에 밸류가 동일해서 오류 생김
			mav.addObject("uid", uid);
			mav.addObject("pw", pw);
			
			return mav;
		}

	}

.

 

HttpServletRequest = HttpServletRequest 객체 이용 

 

package com.aia.firstspring.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.aia.firstspring.member.domain.LoginRequest;

@Controller
@RequestMapping("/member/login")
public class memberLoginController {
	//사용자의 요청 url 처리해야될 기능, 메서드를 바인딩 하는 것이 컨트롤러다.
	
	// @RequestMapping(value = "/member/login", method = RequestMethod.GET)
		@RequestMapping(method = RequestMethod.GET)
		public ModelAndView getLoginForm() {
			return new ModelAndView("member/loginForm"); // setViewName과 동일, 
		}
		
		// @RequestMapping(value = "/member/login", method = RequestMethod.POST)
		@RequestMapping(method = RequestMethod.POST)
		public ModelAndView login(
				HttpServletRequest request) {

			
			String userId = request.getParameter("uid");
			String userPw = request.getParameter("pw");
			
			ModelAndView mav = new ModelAndView();
			mav.addObject("userId", userId);
			mav.addObject("userPw",userPw);
			
			return mav;
		}

	}

 

커맨드 객체 = (Beans) 이용 

이때 객체간의 파라미터 이름이 같아야 한다!!!!!!

package com.aia.firstspring.member.domain;

public class LoginRequest {

	
	// 변수의 이름이 form에있는 name과 같아야 한다.
	String uid;
	String pw;
	
	public String getUid() {
		return uid;
	}
	public void setUid(String uid) {
		this.uid = uid;
	}
	public String getPw() {
		return pw;
	}
	public void setPw(String pw) {
		this.pw = pw;
	}
	@Override
	public String toString() {
		return "LoginRequest [uid=" + uid + ", pw=" + pw + "]";
	}
	
	
}
package com.aia.firstspring.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.aia.firstspring.member.domain.LoginRequest;

@Controller
@RequestMapping("/member/login")
public class memberLoginController {
	//사용자의 요청 url 처리해야될 기능, 메서드를 바인딩 하는 것이 컨트롤러다.
	
	// @RequestMapping(value = "/member/login", method = RequestMethod.GET)
		@RequestMapping(method = RequestMethod.GET)
		public ModelAndView getLoginForm() {
			return new ModelAndView("member/loginForm"); // setViewName과 동일, 
		}
		
		// @RequestMapping(value = "/member/login", method = RequestMethod.POST)
		@RequestMapping(method = RequestMethod.POST)
		public ModelAndView login(
				HttpServletRequest request,
				LoginRequest loginRequest) {
			
			// login("cool","1111")
			System.out.println(loginRequest);
			
			String userId = request.getParameter("uid");
			String userPw = request.getParameter("pw");
			
			ModelAndView mav = new ModelAndView();
			mav.addObject("userId", userId);
			mav.addObject("userPw", userPw);
			//mav.addObject("loginRequest", loginRequest); 
			//안해도 공유가 됨 변수이름은 클래스 이름의 앞글자를 소문자로 바꾼 것으로 됨
			
			return mav;
		}

	}

 

 

 

 

MVC : List 타입의 프로퍼티 바인딩 처리하기 예제

 

 

아이템 목록 : OrderItem.java

package com.aia.firstspring.domain;

public class OrderItem {
	
	private String itemId;
	private String number;
	private String remark;
	public String getItemId() {
		return itemId;
	}
	public void setItemId(String itemId) {
		this.itemId = itemId;
	}
	public String getNumber() {
		return number;
	}
	public void setNumber(String number) {
		this.number = number;
	}
	public String getRemark() {
		return remark;
	}
	public void setRemark(String remark) {
		this.remark = remark;
	}
	@Override
	public String toString() {
		return "OrderItem [itemId=" + itemId + ", number=" + number + ", remark=" + remark + "]";
	}
	
	

}

 

주소 목록 : Address.java

package com.aia.firstspring.domain;

public class Address {
	
	private String zipcode;
	private String address1;
	private String address2;
	public String getZipcode() {
		return zipcode;
	}
	public void setZipcode(String zipcode) {
		this.zipcode = zipcode;
	}
	public String getAddress1() {
		return address1;
	}
	public void setAddress1(String address1) {
		this.address1 = address1;
	}
	public String getAddress2() {
		return address2;
	}
	public void setAddress2(String address2) {
		this.address2 = address2;
	}
	
	@Override
	public String toString() {
		return "Address [zipcode=" + zipcode + ", address1=" + address1 + ", address2=" + address2 + "]";
	}
	
	

}

 

orderCommand.java

/ 커맨드는 이걸루 사용 

/ 주소랑 상품 묶어줌

package com.aia.firstspring.domain;

import java.util.List;

public class orderCommand {
	
	private List<OrderItem> orderItems; 
	private Address address;
	public List<OrderItem> getOrderItems() {
		return orderItems;
	}
	public void setOrderItems(List<OrderItem> orderItems) {
		this.orderItems = orderItems;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	@Override
	public String toString() {
		return "orderCommand [orderItems=" + orderItems + ", address=" + address + "]";
	}
	
	

}

 

컨트롤러 OrderControoler.java

GET / POST 타입 방식에 따른 리퀘스트맵핑

@ModelAttribute 애노테이션을 사용하여 모델명을 설정 (uo로 줄여줌)

package com.aia.firstspring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.aia.firstspring.domain.orderCommand;

@Controller
@RequestMapping("/order/order")
public class OrderController {
	
	@RequestMapping(method = RequestMethod.GET)
	public String getOrderForm() {
	    	return "order/orderForm";
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public String orderComplete(@ModelAttribute("uo") orderCommand order) {
		System.out.println(order);
		return "order/orderComplete";
	}

}

 

[VIEW-1]

입력받을 폼 > orderForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>주문</title>
</head>
<body>

	<h1>주문 폼</h1>
	<form method="post">
		<table border="1">
			<tr>
				<td rowspan="3">상품-1</td>
				<td>ID</td>
				<td><input type="text" name="orderItems[0].itemId"></td>
			</tr>
			<tr>
				<td>개수</td>
				<td><input type="number" name="orderItems[0].number"></td>
			</tr>
			<tr>
				<td>주의</td>
				<td><input type="text" name="orderItems[0].remark"></td>
			</tr>
			<tr>
				<td rowspan="3">상품-2</td>
				<td>ID</td>
				<td><input type="text" name="orderItems[1].itemId"></td>
			</tr>
			<tr>
				<td>개수</td>
				<td><input type="number" name="orderItems[1].number"></td>
			</tr>
			<tr>
				<td>주의</td>
				<td><input type="text" name="orderItems[1].remark"></td>
			</tr>
			<tr>
				<td rowspan="3">상품-3</td>
				<td>ID</td>
				<td><input type="text" name="orderItems[2].itemId"></td>
			</tr>
			<tr>
				<td>개수</td>
				<td><input type="number" name="orderItems[2].number"></td>
			</tr>
			<tr>
				<td>주의</td>
				<td><input type="text" name="orderItems[2].remark"></td>
			</tr>
			<tr>
				<td rowspan="3">주소</td>
				<td>우편번호</td>
				<td><input type="text" name="address.zipcode"></td>
			</tr>
			<tr>
				<td>주소1</td>
				<td><input type="text" name="address.address1"></td>
			</tr>
			<tr>
				<td>주소2</td>
				<td><input type="text" name="address.address2"></td>
			</tr>
			<tr>
				<td></td>
				<td><input type="submit"></td>
				<td></td>
			</tr>
		</table>

	</form>

</body>
</html>

[VIEW-2]

결과출력 > orderComplete.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h1>주문정보</h1>
	
	<h3>상품 주문 정보</h3>
	
	<c:forEach items="${uo.orderItems}" var="oi">
		<div>
			상품 ID : ${oi.itemId} / 개수 : ${oi.number}개 / 주의사항 : ${oi.remark} 	
		</div>	
	</c:forEach>
	
	<h3>배송지</h3>
	<div>
	
		우편번호 : ${uo.address.zipcode}
		주소1 :  ${uo.address.address1}
		주소2 :  ${uo.address.address2}
	</div>
	
</body>
</html>

 

1단계 – client의 요청을 받을 DispatcherServlet 을 web.xml 파일에 설정

 

ContextLoaderListener

- 디스패쳐서블릿의 부모(모든서블릿에 공통적용) / 디스패쳐서블릿 여러개 설정시 필수로 리스너 설정

 

DispatcherServlet / 서블릿매핑

- url패턴의 / 로 해줌. 보통 학원 예제에서는 .do로 많이 나온 부분

/ <- 로 요청되는 모든 client 의 요청을 DispatcherServlet이 처리하도록 요청

/ 이때 servlet-context.xml 이라는 이름의 Spring 설정 파일을 사용하도록 설정

 

2단계 – 컨트롤러 구현 및 설정 추가 하기 

 

컨트롤러 구현

@Controller – Spring MVC의 controller 를 구현한 클래스로 지정

@RequestMapping –/hello 라는 url값으로의 요청을 처리할 메소드 지정

 

설정파일에 등록 / 생략가능(여기선생략함)

servlet-context.xml 

 

package com.aia.firstspring.controller;

import java.util.Calendar;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;


//컨트롤 클래스라고 알려주는 어노테이션 > 이걸 해주어야 handler mapping에 등록
@Controller 
public class HelloController {
	
	// 이 메서드는 프론트컨트롤러 쪽으로 Viewname을 반환해야 한다.
	// 반환 타입은 ModelAndView를 이용해서 반환하자.
	@RequestMapping("/hello")
	public ModelAndView hello() {
		ModelAndView mav = new ModelAndView();
		
		// prefix suffix를 제외한 이름 /WEB-INF/views/member/hello.jsp -> member/hello
 		mav.setViewName("member/hello");
 		mav.addObject("greeting", greeting());
		
		return mav;
	}

	private String greeting() {
		String result = "안녕!";
		
		int nowTime = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
		if(nowTime>=6 && nowTime <= 10) {
			result="좋은 아침";
		} else if(nowTime >= 12 && nowTime<=15) {
			result="맛점";
		} else if(nowTime >=18 && nowTime<=22) {
			result="굿밤";
		}
		
		return result;
	}

}

 

 

3단계 – 설정파일에 viewResolver 설정 추가하기

이부분이 viewResolver

Context 설정 추가

/ namespace에서 context 추가 필수

/ 빈 설정

/ 기본패키지를 컨트롤러로 연결시켜줌

 

 

3.5단계 -  필요하다면 핸들러매핑(의존성주입)


4단계 – JSP를 이용한 View 영역의 코드 작성 


5단계 – 실행

 

우리가 보던 인터넷 사이트처럼 주소가 깔끔해짐 .jsp 이런거 없어졌다!

 

 

 

 

 

 

의존성 주입

 

 

Spring Framework가 지원하는 핵심 기능으로 객체 사이의 의존 관계가 객체 자신이 아닌 외부(조립기)에 의해 설정된다. 외부 조립기는 xml 설정 파일을 기반으로 의존을 설정한다.

 

package member.dao;

public interface Dao {
	
	// public abstract void insert();
	
	void insert();
	void select();
	void delete();
	void update();
}
package member.dao;

public class MemberDao implements Dao {

	@Override
	public void insert() {
		System.out.println("회원 정보 데이터베이스 저장");

	}

	@Override
	public void select() {
		System.out.println("회원 정보 검색");
	}

	@Override
	public void delete() {
		System.out.println("회원 정보 삭제");

	}

	@Override
	public void update() {
		System.out.println("회원 정보 수정");
	}

}

 

 

생성자 타입의 주입방식

 

package member.service;

import member.dao.Dao;

public class MemberRegService implements MemberService {

	// Dao dao = new MemberDao(); // 의존성이 높은 코드이므로 X
	
	
	/* 생성자 방식 */
	
	private Dao dao; // 주입받아야하는 참조변수
	
	// 생성자를 통해서 Dao타입의 인스턴스를 주입받는다.
	// Dao dao = new MemberDao(); -> 다형성.
	public MemberRegService(Dao dao) {
		this.dao = dao;
	}
	
	@Override
	public Object process() {
		System.out.println("MemberRegService 실행");
		dao.insert();
		
		return null;
	}
	
	

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- MemberDao를 Bean(인스턴스)으로 등록 -->
	<bean
	id="memberDao"
	class="member.dao.MemberDao"
	>
	</bean>
	
	<!-- MemberRegService bean으로등록 -->
	<bean id="memberRegService" 
		class="member.service.MemberRegService">
	<!-- <constructor-arg ref="memberDao"/> -->
	<constructor-arg>
		<ref bean="memberDao"/>
	</constructor-arg>
	</bean>
    
</beans>

 

 

프로퍼티 타입의 주입방식

 

package member.service;

import member.dao.Dao;

public class MemberInfoService implements MemberService{
	
	/* 프로퍼티 타입 */
	Dao dao;
	
	// 프로퍼티 타입의 주입 방식 : setter 메소드 정의가 필요하다
	public void setDao(Dao dao) {
		this.dao = dao;
	}
	
	
	
	
	@Override
	public Object process() {
		System.out.println("MeberInfoService 실행");
		dao.select();
		return null;
	}

}
 <!-- 멤버인포서비스 Bean등록 -->
 <bean id="memberInfoService" class="member.service.MemberInfoService">
 <!-- <property name="dao" ref="memberDao"></property> -->
 <property name="dao">
 		<ref bean="memberDao"/>
 </property>

 

MemberMain 실행

package member.main;

import org.springframework.context.support.GenericXmlApplicationContext;

import member.service.MemberInfoService;
import member.service.MemberRegService;

public class MemberMain {

	public static void main(String[] args) {

		
		//1. Spring 컨테이너 생성
		GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx.xml");
	
		//2. MemberRegService 객체가 필요
		MemberRegService regService = ctx.getBean("memberRegService", MemberRegService.class);

		//3. MemberRegService 프로세스 메서드 실행
		regService.process();
		
		//4. MemberinfoService 객체가 필요
		MemberInfoService infoService = ctx.getBean("memberInfoService", MemberInfoService.class);
		
		//5. MemberInfoService 프로세스 메서드 실행
		infoService.process();
	}

}

 

xml 설정파일

 

1. XML 네임스페이스를 이용한 프로퍼티 설정

 <!-- 멤버인포서비스 Bean등록 -->
 <bean id="memberInfoService" class="member.service.MemberInfoService">
 <!-- <property name="dao" ref="memberDao"></property> -->
 <property name="dao">
 		<ref bean="memberDao"/>
 </property>
 
 
 
 ↓ 아래처럼 간결해짐
 	<!-- 프로퍼티 방식에서 p를 사용하면 속성을 사용하지 않고 한 줄 처리가 가능 -->	
    

<!-- 멤버인포서비스 Bean등록 -->
 <bean id="memberInfoService" class="member.service.MemberInfoService"
 	p:dao-ref="memberDao">

 </bean>
</beans>

 

2. 의존관계 설정 : 임의 빈 객체 전달

 <bean id="memberInfoService" class="member.service.MemberInfoService">
 <!-- <property name="dao" ref="memberDao"></property> -->
 <property name="dao">
 		<bean class="member.dao.MemberDao"/>
 </property>
 

 

3. 여러개의 xml 사용 / 두 개 이상의 설정파일 사용하기 > import 이용

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<import resource="classpath:appCtx4_1.xml"/>
<import resource="classpath:appCtx4_2.xml"/>

</beans>

 

 

 

 

 

DI - 의존관계자동설정

 

 

 

 

빈 객체 범위

 

xml에서 scope 설정

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- MemberDao를 Bean(인스턴스)으로 등록 -->
	<bean
	id="memberDao"
	class="member.dao.MemberDao"
	>
	</bean>
	
	<!-- MemberRegService bean으로등록 -->
	<bean id="memberRegService" 
				class="member.service.MemberRegService"
				scope="prototype"
				>	
	<constructor-arg>
		<ref bean="memberDao"/>
	</constructor-arg>
	</bean>
	
 
 <!-- 멤버인포서비스 Bean등록 -->
 <bean id="memberInfoService"
 			class="member.service.MemberInfoService"
 			scope="singleton">
 <property name="dao">
 		<bean class="member.dao.MemberDao"/>
 </property>
 
 </bean>
</beans>
package member.main;

import org.springframework.context.support.GenericXmlApplicationContext;

import member.dao.Dao;
import member.service.MemberInfoService;
import member.service.MemberRegService;

public class MemberMain2 {

	public static void main(String[] args) {

		
		//1. Spring 컨테이너 생성
		GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:appCtx5.xml");
		
		

		Dao dao1 = ctx.getBean("memberDao", Dao.class);
		Dao dao2 = ctx.getBean("memberDao", Dao.class);
		
		// 아무 처리도 하지않으면 기본적으로 싱글톤이다.
		System.out.println("dao1참조변수 == dao2참조변수 ? " +(dao1==dao2));
		
		//2. MemberRegService 객체가 필요
		MemberRegService regService1 = ctx.getBean("memberRegService", MemberRegService.class);
		MemberRegService regService2 = ctx.getBean("memberRegService", MemberRegService.class);
		
		// 프로포타입이므로 false
		System.out.println("regService1==regService2 ? " + (regService1==regService2));
		
		
		//4. MemberinfoService 객체가 필요
		MemberInfoService infoService1= ctx.getBean("memberInfoService", MemberInfoService.class);
		MemberInfoService infoService2= ctx.getBean("memberInfoService", MemberInfoService.class);
		// 싱글톤타입이므로 true > 둘의참조변수가같다
		System.out.println("infoService1==infoService2 ? " + (infoService1==infoService2));
		
		
	}

}

 

.

 

 

 

애노테이션 기반 설정

JDK5 버전부터 추가된 것으로 메타데이터를 XML등의 문서에 설정하는 것이 아니라 소스 코드에 “@애노테이션”의 형태로 표현하며 클래스, 필드, 메소드의 선언부에 적용 할 수 있는 특정 기능이 부여된 표현법이다. 프레임워크들이 활성화 되고 애플리케이션 규모가 커질수록 XML 환경 설정은 복잡해지는데, 이러한 어려움을 개선시키기 위하여 자바 파일에 애노테이션을 적용해서 코드를 작성함으로써 개발자가 설정 파일에 작업하게 될 때 발생시키는 오류의 발생 빈도를 낮춰주기도 한다.

 

 

Java 에서 이미 정의되어 있는 애노테이션


@Override - 메소드가 오버라이드 됐는지 검증.

                 부모 클래스 또는 구현해야 할 인터페이스에서 해당 메소드를 찾을 수 없다면 컴파일 오류. 
@Deprecated - 메소드를 사용하지 말도록 유도. 만약 사용한다면 컴파일 경고. 
@SuppressWarnings - 컴파일 경고를 무시. 
@SafeVarargs - 제너릭 같은 가변인자 매개변수를 사용할 때 경고를 무시.(자바7 이상) 
@FunctionalInterface - 람다 함수등을 위한 인터페이스를 지정.

                               메소드가 없거나 두 개 이상 되면 컴파일 오류.(자바 8이상)

 

 

@Autowired 애노테이션을 이용한 의존 자동 주입

 

 

xml 파일에서 annotation-config.

이전 코드보다 훨신 간결하게 프로퍼티나 생성자 부분 없이 깔끔해졌다.

 

 

 

@Autowired 애노테이션으로 인해 코드가 더깔끔해짐 (위-애노테이션 / 아래-프로퍼티&생성자방식)

 

 

@Qualifier 애노테이션을 이용한 의존 객체 선택

 

package member.dao;

public class GuestDao implements Dao {

	@Override
	public void insert() {
		System.out.println("게스트 회원 정보 데이터베이스 저장");

	}

	@Override
	public void select() {
		System.out.println("게스트  회원 정보 검색");
	}

	@Override
	public void delete() {
		System.out.println("게스트  회원 정보 삭제");

	}

	@Override
	public void update() {
		System.out.println("게스트 회원 정보 수정");
	}

}

memberDao를 복사해서 GuestDao를 만들어준 뒤 실행하면 dao가 두개라서 에러가 난다.

 

Qualifier를 이용해서 value값을 설정해주고 클래스에서 Qulifier 어노테이션으로 지정해준 후 Main 실행

 

@Autowired 의 필수 여부 지정

 

주석처리 하니 Dao가 없어서 에러가난다 (당연..)

 

없더라도 인스턴스는 생성되도록 한다.

대부분은 꼭 있어야하는 Dao같은 상황에 사용하지만, 존재의 유무를 확인할 때 등등 정리해서 쓰면 좋다.

 

 

 

@Resource 애노테이션을 이용한 자동 의존 주입

 

id를 name으로 써서 구별한다.

그러나 타입으로 구별하는 @autowired를 더 자주사용한다.

타입을 맞추는 것이 더 정확하고 에러가 덜 나기 때문이래나 뭐래나.. 암튼 그렇다!

자동 주입과 명시적 의존 주입 설정이 함께 사용되는 경우 명시적인 의존 주입 설정이 우선한다

 

.

 

 

 

 

[Spring] 의존객체 자동 주입(Automatic Dependency Injection), @Autowired, @Resource, @Inject

| 의존객체 자동 주입(Automatic Dependency Injection) 의존 객체 자동 주입(Automatic Dependency Injection)은 스프링 설정파일에서  혹은  태그로 의존 객체 대상을 명시하지 않아도 스프링 컨테이너가 자..

xzio.tistory.com

 

'spring' 카테고리의 다른 글

[스프링] jdbc  (0) 2021.01.11
[스프링] 파일업로드  (0) 2021.01.08
[스프링] MVC - 컨트롤러 구현  (0) 2021.01.08
[스프링] MVC : 패턴  (0) 2021.01.08
[스프링] 자바 프로젝트를 메이븐 기반의 프로젝트로 변환하기  (0) 2021.01.06
[스프링] 기본 설정  (0) 2021.01.05
[스프링] 설치  (0) 2021.01.05

자바 프로젝트를 메이븐 기반의 프로젝트로 변환하기

 

자바 프로젝트 생성 후 Convert to Maven Project > pom.xml이 생성된다.

 

mvnrepository.com/artifact/org.springframework/spring-context/3.1.1.RELEASE

에서 버전에 맞는 것을 pom.xml에 넣어주면 이렇게 생기긔..

 

 

'spring' 카테고리의 다른 글

[스프링] jdbc  (0) 2021.01.11
[스프링] 파일업로드  (0) 2021.01.08
[스프링] MVC - 컨트롤러 구현  (0) 2021.01.08
[스프링] MVC : 패턴  (0) 2021.01.08
[스프링] DI / xml 설정파일 / 어노테이션  (0) 2021.01.06
[스프링] 기본 설정  (0) 2021.01.05
[스프링] 설치  (0) 2021.01.05

+ Recent posts