반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

Yeonee's Story

[Spring] 스프링에서 parameter(요청시 전달값)을 받는 방법(@RequestParam, @ModelAttribute) + 필드, 생성자, 수정자 주입방식 개념 본문

⋆ 。゜☁︎ 。⋆ 。゜☾゜。⋆⋆ 。゜☁︎ 。⋆ 。゜☾゜。⋆/Spring

[Spring] 스프링에서 parameter(요청시 전달값)을 받는 방법(@RequestParam, @ModelAttribute) + 필드, 생성자, 수정자 주입방식 개념

yeonee 여니 2023. 8. 3. 19:36
728x90
반응형
SMALL

안녕하세요.
https://blog.naver.com/sysysy0302 여니입니다 :)

 

yeonee 블로그 : 네이버 블로그

예쁘고 맛있게 먹고 건강하게,강인하지만 온화하게 행하라. ※맛스타운스타일상 인스타 www.instagram.com/s2._.y25n ※맛집감성일상 유튜브https://youtube.com/channel/@S2_yeonee 티스토리https://yeoneeluv.tistory.co

blog.naver.com

 

 

< 스프링에서 parameter(요청시 전달값)을 받는 방법 >


<필드부 영역코드>

package com.kh.spring.member.controller;


import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.kh.spring.member.model.service.MemberService;
import com.kh.spring.member.model.validator.MemberValidator;
import com.kh.spring.member.model.vo.Member;

import lombok.extern.slf4j.Slf4j;
@Slf4j

//; @Controller: servlet-context.xml이 자동으로 빈 클래스로 등록을 시켜준다
@Controller
// Controller 타입의 어노테이션을 붙여주면 빈 스캐너가 자동으로 빈(bean)으로 등록해줌.
// (servlet-context.xml안에 있는 <context:component-scan>태그)
// @RequestMapping("/member") -> 공통주소(클래스레벨에 선언)
// localhost:8081/spring/member(공통주소)/login.me(그외주소, 메소드레벨에 선언)
// 단, 클래스레벨에 @RequestMapping이 존재하지 않는 경우 메서드레벨에서 단독으로 요청을 처리한다.
@SessionAttributes({"loginUser"})
// Model에 추가된 값의 key와 일치하는 값이 있으면 해당값을 session scope로 이동시킨다.
public class MemberController {

	/*
	 * 기존객체 생성 방식 private MemberService mService = new MemberService();
	 * 
	 * 서비스가 동시에 많은 횟수가 요청이되면 그만큼 많은 객체가 생성된다. //; 메모리 관리상 유연성이 없다.
	 * 
	 * Spring의 DI(Dependency Injection) -> 객체를 스프링에서 직접 생성해서 주입해주는 개념
	 * 
	 * new 연산자를 쓰지 않고 선언만 한 후 @Autowired어노테이션을 붙이면 객체를 주입받을수 있다.
	 */

	// @Autowired //; spring 형식의 MemberService객체를 주입받고 있는 방식
	private MemberService mService;
	private MemberValidator memValidator;
	private BCryptPasswordEncoder bcryptPasswordEncoder; 
	/*
	 * ; 객체를 주입받는 방식이 여러가지 있다.
	 * 
	 * 필드주입방식 장점 : 이해하기 편함. 사용하기도 편함.
	 * 
	 * 필드주입방식의 단점 : 순환 의존성 문제가 발생할 수 있다. 무분별한 주입시 의존관계 확인이 어렵다. final 예약어를 지정할수가 없다.
	 * //; 즉 객체가 변경될 수 있으므로 위험하다.
	 * 
	 */

	// 생성자 주입방식

	public MemberController() {

	}

	@Autowired // ; 여기서 붙여주면 위에 @Autowired는 지워주기
	public MemberController(MemberService mService, MemberValidator memValidator, BCryptPasswordEncoder bcryptPasswordEncoder) {	//; memValidator객체를 주입해줄것임.
		this.mService = mService;
		this.memValidator = memValidator;
		this.bcryptPasswordEncoder = bcryptPasswordEncoder;
	}
	/*
	 * 의존성 주입시 권장하는 방식 (;객체를 주입하는 것임) 생성자에 참조할 클래스로 인자를 받아서 필드에 매핑시킴
	 * 
	 * 장점 : 현재클래스에서 내가 주입시킬 객체들을 모아서 관리할 수 있기 때문에 한눈에 알아보기 편함 코드분석과 테스트에 유리하며,
	 * 		 final로 필드값을 받을수 있어서 안전하다.
	 */

	/*
	 * 그외 방식 Setter 주입방식 : setter메서드로 빈을 주입받는 방식 생성자에 너무 많은 의존성을 주입하게 되면 알아보기 힘들다는
	 * 단점이 있어서 보완하기 위해 사용하거나, 혹은 의존성이 항상 필요한 경우가 아니라 선택사항이라면 사용함.
	 */

	@Autowired // ; 쓰기 좀 어려워서 있다는 것만 알아두기
	public void setMemberService(MemberService memeService) {
		this.mService = memeService;
	}
	
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		binder.addValidators(memValidator);	//; id,name,pwd 에는 빈값이 들어가면 안되게 만들어줌.
	}

먼저 필드부 셋팅이 필요합니다. 
- @Controller는 servlet-context.xml이 자동으로 빈 클래스로 등록을 시켜줍니다.
(Controller 타입의 어노테이션을 붙여주면 빈 스캐너가 자동으로 빈(bean)으로 등록해줌.)

- 기존객체 생성 방식 private MemberService mService = new MemberService(); 이지만, 서비스가 동시에 많은 횟수가 요청이 되면 그만큼 많은 객체가 생성됩니다. (즉, 메모리 관리상 유연성이 없다는 뜻임.)
Spring의 DI(Dependency Injection) -> 객체를 스프링에서 직접 생성해서 주입해주는 개념, new 연산자를 쓰지 않고 선언만 한 후 @Autowired어노테이션을 붙이면 객체를 주입 받을 수 있습니다. 
객체를 주입받는 방식이 여러가지 있습니다.


1) 필드 주입방식 

@Controller
public class MemberController {
     @Autowired
      private MemberService mService;
      private MemberValidator memValidator;
      private BCryptPasswordEncoder bcryptPasswordEncoder; 
}

필드에 @Autowired 어노테이션만 붙여주면 자동으로 의존성 주입됩니다.
사용법이 매우 간단하기 때문에 가장 많이 접할 수 있는 방법입니다.
 

장점

  • 이해하기 편하다.
  • 사용하기도 편하다.


단점

  • 코드가 간결하지만, 외부에서 변경하기 힘들다.
  • 프레임워크에 의존적이고 객체지향적으로 좋지 않다.

 


2) 생성자 주입방식

public class MemberController {
    //final을 붙일 수 있음
    private MemberService mService;
	private MemberValidator memValidator;
	private BCryptPasswordEncoder bcryptPasswordEncoder; 

	public MemberController() {

	}
    
    //@Autowired 
    public MemberController(MemberService mService, MemberValidator memValidator, BCryptPasswordEncoder bcryptPasswordEncoder) { //;MemberValidator memValidator : memValidator객체를 주입해줄것임.
        this.mService = mService;
        this.memValidator = memValidator;
        this.bcryptPasswordEncoder = bcryptPasswordEncoder;
	}
}

클래스의 생성자가 하나이고, 그 생성자로 주입받을 객체가 빈으로 등록되어 있다면  @Autowired를 생략 할 수 있습니다.

장점

  • 현재클래스에서 내가 주입시킬 객체들을 모아서 관리할 수 있기 때문에 한눈에 알아보기 편함 코드분석과 테스트에 유리하다.
  • final로 필드값을 받을수 있어서 안전하다.

 

 3) 그외 방식 : 수정자 (Setter) 주입방식

Setter 메소드에 @Autowired 어노테이션을 붙이는 방법입니다.
setter메서드로 빈을 주입받는 방식 생성자에 너무 많은 의존성을 주입하게 되면 알아보기 힘들다는 단점이 있어서 보완하기 위해 사용하거나, 혹은 의존성이 항상 필요한 경우가 아니라 선택사항이라면 사용합니다.

@Controller
public class MemberController {
    private MemberService mService;
	private MemberValidator memValidator;
	private BCryptPasswordEncoder bcryptPasswordEncoder; 
    
    @Autowired // ; 쓰기 좀 어려워서 있다는 것만 알아두기
	public void setMemberService(MemberService memeService) {
    	this.mService = memeService;
	}
}

단점

  • 수정자 주입을 사용하면 setXXX 메서드를 public으로 열어두어야 하기 때문에 언제 어디서든 변경이 가능합니다.

 


 

1. HttpServletRequest request를 이용해서 전달받기(기존방식 그대로)

해당 메소드의 매개변수로 HttpServletRequest를 작성해 놓으면 스프링 컨테이너가 해당 메소드를 호출할때,
자동으로 request객체를 생성해서 매개변수로 주입해줍니다.
+ ' method 자체가 없으면 get이든 post이든 신경쓰지 않겠다. ' 라는 뜻 입니다.

@RequestMapping(value = "login.me" , method = RequestMethod.POST)
RequestMapping이라는 어노테이션을 붙이면 HandlerMapping곳에 등록이 됩니다. 
()안에 여러개의 속성을 추가할 수 있습니다.
+ HandlerMapping을 관리하는 것이 DispatchServlet입니다.

@RequestMapping(value = "login.me" , method = RequestMethod.POST)
public String loginMember(HttpServletRequest request) {
    String userId = request.getParameter("userId");
    String userPwd = request.getParameter("userPwd");

    System.out.println("userId : "+userId );
    System.out.println("userPwd : "+userPwd);

    return "main";
}

 

 

2. @RequestParam어노테이션을 이용하는 방법 

@RequestParam 어노테이션은 HttpServletRequest 객체와 같은 역할을 합니다.
HttpServletRequest에서는 getParameter() 메소드를 이용했지만, @RequestParam을 이용해서 받아오는 방법도 있습니다. 메소드의 파라미터 값으로 @RequestParam을 넣어주면 됩니다.

@RequestParam ("가져올 데이터의 이름") [데이터타입] [가져온 데이터를 담을 변수]

기존의 request.getParameter("키")로 뽑는 역할을 대신 수행해주는 어노테이션 input 속성의 value로,
jsp에서 작성했던 name값을 입력해주면 알아서 매개변수로 값을 담아옵니다.
만약 넘어온 값이 비어있다면 디폴트 값을 지정해주는 defaultValue로 설정 가능합니다.

@RequestMapping(value = "login.me" , method = RequestMethod.POST)
public String loginMember(
                //@RequestParam(value="userId") String userId,
                @RequestParam(value="userId" , defaultValue="m") String userId, //;defaultValue="m" 값이 없을 때 디폴트값, 꼭 입력하지 않아도 되는 경우 사용.
                @RequestParam(value="userPwd") String userPwd
        ) {
    System.out.println("userId : "+userId );
    System.out.println("userPwd : "+userPwd);

    return "main";
}

@RequestParam(value="userId") String userId,으로 적을 경우 id값이 없을 때 출력되는 내용이 없는데,
defaultValue="m"을 추가해서 적으면 id 값이 없을 때 디폴트값으로 "m"을 출력하도록 지정할 수 있습니다.
(즉, 꼭 값을 입력하지 않아도 되는 경우에 사용합니다.)

+ 로그인시에 사용자가 입력한 id와 pwd값이 콘솔창에 출력되게 됩니다.

 

3. @RequestParam어노테이션을 생략하는 방법 

매개변수의 변수명을 jsp에서 전달한 파라미터의 name속성값과 일치시켜줘야 합니다.
+ defaultValue 사용불가

@RequestMapping(value = "login.me" , method = RequestMethod.POST)
public String loginMember(
                String userId,
                String userPwd
        ) {
    System.out.println("userId : "+userId );
    System.out.println("userPwd : "+userPwd);

    return "main";
}

@RequestParam(value="userId")으로 @RequestParam 어노테이션을 생략할 수 있으며, 대신 매개변수의 변수명을 파라미터의 name속성값과 일치시켜야 가능합니다.

+ 로그인시에 사용자가 입력한 id와 pwd값이 콘솔창에 출력되게 됩니다.

 

 

4. 커멘드 객체 방식 해당 메소드의 매개변수로 요청시 전달값을 담고자하는 VO클래스타입의 변수를 셋팅하고, 요청시 전달값의 name속성값이 VO클래스의 담고자하는 필드명과 일치시켜서 작성

스프링컨테이너에서 해당 객체를 "기본 생성자"로 호출해서 생성 후, 내부적으로 전달받은 key값에 해당하는 setter메서드를 찾아서 전달한 값을 필드에 담아준다. 따라서 반드시 name속성값(키값)과 vo객체의 필드명이 일치해야한다.
+ @ModelAttribute는 생략이 가능하여 'Member m ' 만 적어주어도 됩니다.

@RequestMapping(value = "login.me" , method = RequestMethod.POST)
public String loginMember(
        @ModelAttribute Member m 
        //; @ModelAttribute : 생략 가능
        ) {
    System.out.println("userId : "+m.getUserId() );
    System.out.println("userPwd : "+m.getUserPwd());

    return "main";
}

+ 로그인시에 사용자가 입력한 id와 pwd값이 콘솔창에 출력되게 됩니다.

728x90
반응형
LIST