본문 바로가기

자바 웹/스프링

스프링 애너테이션 기능

728x90

스프링 애너테이션


스프링 3.0부터는 DI와 같은 자바 코드와 관련된 설정은 직접 코드에서 할 수 있도록 애너테이션 기능을 제공한다. 현재 스프링 기반 애플리케이션에서는 XML에서 설정하는 방법과 애너테이션 기능을 사용하는 방법 두 가지를 혼합해서 사용하고 있다. 

 

<context:component-scan> 태그 기능

 

<context:component-scan>  태그를 사용해 패키지 이름을 지정하면 애플리케이션 실행 시 해당 패키지에서 애너테이션으로 지정된 클래스를 빈으로 만들어준다.

 

<context:component-scan base-package="패키지이름" /> 

 

@Controller 스프링 컨테이너가 지정한 클래스를 컨트롤러 빈으로 자동 변환
@Service 스프링 컨테이너가 지정한 클래스를 서비스 빈으로 자동 변환
@Respository 스프링 컨테이너가 지정한 클래스를 DAO빈으로 자동 변환
@Component 스프링 컨테이너가 지정한 클래스를 빈으로 자동 변환

 

servlet-action.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      	<property name="prefix" value="/WEB-INF/views/test/" />
      	<property name="suffix" value=".jsp"/>
   	</bean>

	<!-- 클래스 레벨에 @RequestMapping을 처리 -->
   	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
	<!-- 메서드 레벨에 @RequestMapping을 처리 -->
  	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
   	
   	<!-- com.spring 패키지에 존재하는 클래스에 애너테이션이 적용되도록 설정 -->
   	<context:component-scan base-package="com.spring"/>
</beans>

 

MainController

 

@Controller("mainController")//빈 id는 mainController
@RequestMapping("/test")//@RequestMapping를 이용해 첫 번째 단계의 요청이 /test이면 mainController빈을 요청
public class MainController {
	
	@RequestMapping(value = "/main1.do", method = RequestMethod.GET)
	public ModelAndView main1(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView mav = new ModelAndView();
		mav.addObject("msg", "main1");
		mav.setViewName("main");
		return mav;
	}
	
	@RequestMapping(value = "/main2.do", method = RequestMethod.GET)
	public ModelAndView main2(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView mav = new ModelAndView();
		mav.addObject("msg", "main2");
		mav.setViewName("main");
		return mav;
	}
}

 

main.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" 
    isELIgnored="false"  %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<%
  request.setCharacterEncoding("UTF-8");
%>    
<html>
<head>
<meta charset=UTF-8">
<title>결과창</title>
</head>
<body>
	<h1>안녕하세요!!</h1>
	<h1>${msg} 페이지입니다!!</h1>
</body>
</html>

 

http://localhost:8090/pro26/test/main1.do

http://localhost:8090/pro26/test/main2.do

 

로 각각 요청하면 각각 ${msg} 부분에 main1 / main2가 출력된다(컨트롤러에서 설정했던)

 

스프링 애너테이션 이용해서 로그인 기능


 

web.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">

	<!-- 한글 처리를 하는 필터 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping> 
	
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>

 

LoginController

 

@Controller("loginController")
public class LoginController {

	@RequestMapping(value = {"/test/loginForm.do", "/test/loginForm2.do"}, method = {RequestMethod.GET})
	public ModelAndView loginForm(HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		ModelAndView mav = new ModelAndView();
		mav.setViewName("loginForm");
		return mav;
	}
	
	@RequestMapping(value = "/test/login.do", method = {RequestMethod.GET, RequestMethod.POST})
	public ModelAndView login(@RequestParam("userID") String userID, @RequestParam("userName") String userName, 
							  //required 값을 설정 안하면 기본으로 true. false로 설정하면 값이 안넘어왔을 때 null로 처리 
							  @RequestParam(value = "email", required = false) String email,
							  HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		ModelAndView mav = new ModelAndView();
		mav.setViewName("result");
		
		//메서드에서 @RequestParam을 사용하면 getParameter()메서드로 일일이 가져올 필요 없음
//		String userID = request.getParameter("userID");
//		String userName = request.getParameter("userName");
		
		System.out.println("userID = "+userID);
		System.out.println("userName = "+userName);
		System.out.println("email = "+email);
		
		mav.addObject("userID", userID);
		mav.addObject("userName", userName);
		
		return mav;
	}
	
	//@RequestParam을 사용해서 Map에 매개변수 값 설정
	//전송되는 매개변수의 수가 많을 경우 일일이 변수 지정하기 불편하기 때문에 Map에 저장
	@RequestMapping(value = "/test/login2.do", method = {RequestMethod.GET, RequestMethod.POST})
	public ModelAndView login2(@RequestParam Map<String, String> info, HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		ModelAndView mav = new ModelAndView();
		
		//@RequestParam에서 절성한 Map 이름으로 바인딩
		mav.addObject("info", info);
		
		mav.setViewName("result");
				
		return mav;
	}
	
	//@ModelAttribute를 사용해서 VO에 매개변수 값 설정
	@RequestMapping(value = "/test/login3.do", method = {RequestMethod.GET, RequestMethod.POST})
	public ModelAndView login3(@ModelAttribute("info")LoginVO loginVO, HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		ModelAndView mav = new ModelAndView();
		
		mav.setViewName("result");
		
		return mav;
	}
	
	//Model 클래스를 사용해서 값 전달
	@RequestMapping(value = "/test/login4.do", method = {RequestMethod.GET, RequestMethod.POST})
	public String login4(Model model, HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		
		model.addAttribute("userID", "hong");
		model.addAttribute("userName", "홍길동");
		
		return "result";
	}
}

 

LoginVO

 

public class LoginVO {
	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;
	}
}

 

loginForm.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" 
    isELIgnored="false"  %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<c:set var="contextPath"  value="${pageContext.request.contextPath}"/>
<%
  request.setCharacterEncoding("UTF-8");
%>    
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>로그인창</title>
</head>

<body>
	<form   method="post"  action="${contextPath}/test/login2.do">
	    <input  type="hidden"  name="email" value="hong@test.com" />
		<table width="400">
			<tr>
				<td>아이디 <input type="text" name="userID" size="10"></td>
			</tr>
			<tr>
				<td>이름 <input type="text" name="userName" size="10"></td>
			</tr>
		    <tr>
				<td>
				  <input type="submit" value="로그인">
				  <input type="reset" value="다시입력">
				</td>
			</tr>
		</table>
	</form>
</body>
</html>

 

result.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" 
    isELIgnored="false"  %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>
<%
  request.setCharacterEncoding("UTF-8");
%>    
<html>
<head>
<meta charset=UTF-8">
<title>결과창</title>
</head>
<body>
	<h1>아이디 : ${userID }</h1>
	<h1>이 름 : ${userName }</h1>
	
	<h1>아이디 : ${info.userID }</h1>
	<h1>이 름 : ${info.userName }</h1>
</body>
</html>

 

 

설정한 거에 따라서 위와 같이 출력

 

@Autowired 이용해서 빈 주입


 

위에서 처럼 XML 파일을 통해 빈을 주입시키면 불편하기 때문에 @Autowired를 사용해서 빈을 직접 자바 코드에서 생성해 사용한다.

 

  • 기존 XML 파일에서 각각의 빈을 DI로 주입했던 기능을 코드에서 애너테이션으로 자동으로 수행
  • @Autowired를 사용하면 별도의 setter나 생성자 없이 속성에 빈을 주입할 수 있음

빈 주입 경로

sqlSession => memberDAO => memberService => memberController

 

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">

   <!-- ContextLoaderListener를 사용해서 애플리케이션이 실행될 때 action-mybatis.xml을 읽어들이도록 설정 -->	 
   <listener>
      <listener-class>
         org.springframework.web.context.ContextLoaderListener
     </listener-class>
   </listener>
	<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
          /WEB-INF/config/action-mybatis.xml
      </param-value>
   </context-param>  

	<!-- 한글 처리를 하는 필터 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping> 
	
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>



action-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	<property name="prefix" value="/WEB-INF/views/member/" />
      	<property name="suffix" value=".jsp"/>
   	</bean>

	<!-- 클래스 레벨에 @RequestMapping을 처리 -->
   	<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
	<!-- 메서드 레벨에 @RequestMapping을 처리 -->
  	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
   	
   	<!-- com.spring 패키지에 존재하는 클래스에 애너테이션이 적용되도록 설정 -->
   	<context:component-scan base-package="com.spring"/>
</beans>



action-mybatis.xml

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

	<bean id="propertyPlaceholderConfigurer"
	class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>/WEB-INF/config/jdbc.properties</value>
		</property>
	</bean>
	
 	<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
		<property name="driver" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
 
 	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation"
			value="classpath:mybatis/model/modelConfig.xml" />
		<property name="mapperLocations" value="classpath:mybatis/mappers/*.xml" />
	</bean>

	<bean id="sqlSession"
		class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
	</bean>
</beans>



modelConfig.xml

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

<configuration>
	<typeAliases>
		<typeAlias type="com.spring.member.vo.MemberVO"  alias="memberVO" />
	</typeAliases>
</configuration>



MemberController

@Controller("memberController")
public class MemberController {
	
	@Autowired
	private MemberService memberService;
	@Autowired
	private MemberVO memberVO;
	
	@RequestMapping(value = "/member/listMembers.do", method = RequestMethod.GET)
	public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		String viewName = getViewName(request);
		List membersList = memberService.listMembers();
		ModelAndView mav = new ModelAndView(viewName);
		mav.addObject("membersList", membersList);
		
		return mav;
	}
	
	//회원 가입창에서 전송된 회원 정보를 바로 MemberVO 객체에 설정하고, 이를 SQL문으로 전달해 회원 등록
	@RequestMapping(value = "/member/addMember.do", method = RequestMethod.POST)
	public ModelAndView addMember(@ModelAttribute("member") MemberVO memberVO, HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		memberService.addMember(memberVO);
		ModelAndView mav = new ModelAndView("redirect:/member/listMembers.do");
		
		return mav;
	}
	
	//전송된 id에 해당하는 회원 삭제
	@RequestMapping(value = "/member/removeMember.do", method = RequestMethod.GET)
	public ModelAndView removeMember(@RequestParam("id") String id, HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		memberService.removeMember(id);
		ModelAndView mav = new ModelAndView("redirect:/member/listMembers.do");
		
		return mav;
	}
	
	//요청명이 Form.do로 끝나면 form() 메서드를 호출
	@RequestMapping(value = "/member/*Form.do", method = RequestMethod.GET)
	public ModelAndView form(HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		request.setCharacterEncoding("utf-8");
		String viewName = getViewName(request);
		ModelAndView mav = new ModelAndView();
		mav.setViewName(viewName);
		
		return mav;
	}
	
	private String getViewName(HttpServletRequest request) throws Exception {
		String contextPath = request.getContextPath();
		String uri = (String) request.getAttribute("javax.servlet.include.request_uri");
		if (uri == null || uri.trim().equals("")) {
			uri = request.getRequestURI();
		}

		int begin = 0;
		if (!((contextPath == null) || ("".equals(contextPath)))) {
			begin = contextPath.length();
		}

		int end;
		if (uri.indexOf(";") != -1) {
			end = uri.indexOf(";");
		} else if (uri.indexOf("?") != -1) {
			end = uri.indexOf("?");
		} else {
			end = uri.length();
		}

		String viewName = uri.substring(begin, end);
		if (viewName.indexOf(".") != -1) {
			viewName = viewName.substring(0, viewName.lastIndexOf("."));
		}
		if (viewName.lastIndexOf("/") != -1) {
			viewName = viewName.substring(viewName.lastIndexOf("/"), viewName.length());
		}
		return viewName;
	}
}



MemberServiceImpl

@Service("memberService")//id가 memberService인 밴 자동 생성
public class MemberServiceImpl implements MemberService{
	
	@Autowired
	private MemberDAO memberDAO;

	@Override
	public List listMembers() throws DataAccessException {
		List<MemberVO> membersList = null;
		membersList = memberDAO.selectAllMemberList();
		return membersList;
	}

	@Override
	public int addMember(MemberVO memberVO) throws DataAccessException {
		
		return memberDAO.insertMember(memberVO);
	}

	@Override
	public int removeMember(String id) throws DataAccessException {
		
		return memberDAO.deleteMember(id);
	}
}



MemberDAOImpl

@Repository("memberDAO")
public class MemberDAOImpl implements MemberDAO{
	
	//XML 설정 파일에서 생성한 id가 sqlSession인 빈을 자동 주입
	@Autowired
	private SqlSession sqlSession;

	@Override
	public List selectAllMemberList() throws DataAccessException {
		List<MemberVO> membersList = sqlSession.selectList("mapper.member.selectAllMemberList");
		return membersList;
	}

	@Override
	public int insertMember(MemberVO memberVO) throws DataAccessException {
		int re = sqlSession.insert("mapper.member.insertMember", memberVO);
		return re;
	}

	@Override
	public int deleteMember(String id) throws DataAccessException {
		int re = sqlSession.delete("mapper.member.deleteMember", id);
		return re;
	}
}



member.xml

<?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="mapper.member">
	<resultMap id="memResult" type="memberVO">
		<result property="id" column="id" />
        <result property="pwd" column="pwd" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <result property="joinDate" column="joinDate" />
	</resultMap> 

	<select id="selectAllMemberList" resultMap="memResult">
      <![CDATA[
         select * from t_member	order by joinDate desc	 	
      ]]>
	</select>

     <insert id="insertMember"  parameterType="memberVO">
		<![CDATA[
		 insert into t_member(id,pwd, name, email)
		 values(#{id}, #{pwd}, #{name}, #{email})
		]]>      
	</insert>

   <delete id="deleteMember"  parameterType="String">
	<![CDATA[
	   delete from  t_member
	   where
	   id=#{id}
	]]>      
  </delete>

</mapper>



MemberVO

@Component("memberVO")
public class MemberVO {
	private String id;
	private String pwd;
	private String name;
	private String email;
	private Date joinDate;

	public MemberVO() {
		
	}

	public MemberVO(String id, String pwd, String name, String email) {
		this.id = id;
		this.pwd = pwd;
		this.name = name;
		this.email = email;
	}
    
    ...getter/setter
}

 

728x90

'자바 웹 > 스프링' 카테고리의 다른 글

다중 파일 업로드  (0) 2022.07.04
메이븐과 STS  (0) 2022.07.04
스프링 트랜잭션  (0) 2022.07.01
마이바티스  (0) 2022.06.30
스프링 MVC 기능  (0) 2022.06.29