20220824 [Spring Boot]

Yeoonnii·2022년 8월 24일
0

TIL

목록 보기
11/52
post-thumbnail

Spring Boot 시작하기

vscode Spring Boot 환경설정

Extension

Spring Boot Extension Pack 설치

pom.xml 라이브러리 설치

  1. Project Lombok(lombok)
    : 상용구 코드를 최소화하기 위한 코드를 생성 하는 Java 라이브러리 도구
  2. web 웹개발환경
  3. tomcat : 웹서버 구동용,
    웹 애플리케이션을 기반으로 하는 Servlet 및 JAVA 서버 페이지를 실행
  4. DB연동 : mongodb
        <!-- lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>


        <!-- web --> 웹 개발 환경
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		
	<!-- web server --> 웹서버 구동용
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>
		
	<!-- mongodb --> DB연동  => mongoConfig.java 와 같은 역할
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>

프로젝트 생성

view > commandpalette > Spring Initializr

설치한 라이브러리 이용하여 속성 설정

📁 resource > application.properties

# 포트번호 설정 127.0.0.1:8080
server.port=8080

# controller, service가 변경되면 자동으로 서버 구동
spring.devtools.livereload.enabled=true

# 서버의 주소 설정 127.0.0.1:8080/ROOT
server.servlet.context-path=/ROOT

#Mongodb연동 설정
spring.data.mongodb.uri=mongodb://id207:pw207@1.234.5.158:37017/db207
spring.data.mongodb.database=db207

💡 서버의 주소 설정
server.servlet.context-path=/ROOT
= 127.0.0.1:8080/ROOT
= 127.0.0.1:8080 ➡️ ROOT생략가능 (default값)
ex)
127.0.0.1:8080/ROOT => naver.com
127.0.0.1:8080/news => news.naver.com
127.0.0.1:8080/land => land.naver.com


📁 Homecontroller.java

👨‍🏫 어떻게 와서 어떻게 호출하는지
뭐가 오고 뭐가 가는가 ! 이게 중요하다

controller = view로 생각하면 된다

@RestController
➡️ 이 파일이 컨트롤러라는 것을 명시해 주는 역할
해당파일이 어떤 파일인지 명시가 되어야 그 역할을 인식할 수 있다.

@GetMapping("/test")
➡️ 여기에서 만드는 모든 업무는 주소에 /test가 붙는다


회원서비스

📁entity / member.java

entity 생성 및 DB추가

package com.example.entity;

import java.util.Date;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter   // service에서 가져감
@Setter   // controller에서 넣음
@NoArgsConstructor // 생성자
@ToString  // 객체 값 확인용
@Document(collection = "boot_member") // DB새 컬랙션 생성 

public class Member {
    
    @Id => mongodb에 id 입력시 mongodb기본키 _id자리에 입력하겠다!
    private String id = null; 
    
    // @Field(name = "pw") =>나는 pw 변수명 사용하고 mongodb에는 password로 입력하겠다!
    private String password = null;

    private String name = null;
    private String phone = null;
    private Date regdate = null;
}

@Id
➡️ mongodb에 id 입력시 mongodb기본키 _id자리에 입력하겠다
나는 변수명 id사용하고 mongodb에는 기본키 값으로 입력함!

@Field(name = "pw")
➡️ 기본키 값 이외에 다른 값들도 변수명과 DB입력명 따로 입력할 수 있다
하지만 예외적인 경우 제외하고 굳이 이렇게 사용할 필요가 없다..
다르게 쓰면 복잡하기 때문!

@Document(collection = "boot_member")
➡️ 몽고db컬렉션 지정해줌 = mongodb에 boot_member 컬렉션에 저장
자바에서는 직접 설정했었는데 여기에서는 entity에 바로 적어주면 된다


📁controller / MemberController.java

홈 컨트롤러에 계속 생성 가능하지만 한 컨트롤러에 많은 코드를 생성하는 경우 파일이 길어지고 관리하기 어려워진다
새 파일로 생성하여 관리해주면 나중에도 유지관리가 편리해진다

  • @ModelAttribute
    ➡️ 데이터 올때 entity로 달라고 요청 + entity를 가져오면서 동시에 set이 동작
  • @Autowired
    ➡️ 하나의 객체 내에서 필요에 의해 다른 객체를 생성자(Constructor) 또는 Setter 를 통해 주입해주는 역할
    스프링에서 빈 인스턴스가 생성된 이후 @Autowired를 설정한 메서드가 자동으로 호출되고, 인스턴스가 자동으로 주입된다.
  • Map<String, Object> 생성하여 return map의 결과를 {status:200}, {status:0}로 받는다
  • 💡 데이터 전송시 key값은 엔티티의 변수명을 입력해줘야 한다!
    postman에서 데이터 전송시 get > body > formdata로 보내야 한다.
    암호가 있으니 params로 보내면 안된다!
  • 데이터가 formadata로 전송되는 경우 RequestParam으로 받는다

    💡 @RequestParam은 사용자가 제공한 HTML 양식 데이터를 읽어서 request 매개변수에 바인딩 하는 용도이다.
    하지만 RequestParam을 하나씩 써서 개별로 데이터를 받아오는건 entity를 만든 의미가 없다!
    entity를 사용하는게 더 편리하고 간결하기 때문에 아래와 같이 개별로 데이터를 받아오는 방식은 거의 사용하지 않는다.

     @PostMapping(value = {"/join", "/join.json"})
        public Map<String, Object> joinPOST(
            @RequestParam(name = "id") String id,
            @RequestParam(name = "pw") String pw, 
            @RequestParam(name = "name") String name,
            @RequestParam(name = "phone") String phone){
    		//입력된 id를 service로 전송하는 용도
    		Member member = new Member(); 
             member.setId(id);
                member.setPassword(pw);
                member.setName(name);
                member.setPhone(phone);
                Map<String, Object> map = new HashMap<>();
                map.put("status", 200);
                map.put("member", member);
                return map;
        }

package com.example.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.entity.Member;
import com.example.service.MemberService;

@RestController
//여기에서 만드는 모든 업무는 주소에 member가 붙는다@RequestMapping("/member") 
public class MemberController {
    // 서비스 사용하려면 Autowired
    @Autowired
    private MemberService mService = null;
    // = MemberSercice mService = new MemberSercice();
   
  
    // 회원가입
    // 127.0.0.1:8080/ROOT/member/join1
    @PostMapping(value = {"/join1", "/join1.json"})
    public Map<String, Object> joinPOST(@ModelAttribute Member member){
       
        // 날짜 수동으로 넣기, 나머지 데이터는 입력되는대로 저장
        member.setRegdate(new Date());

        int ret = mService.insertMember(member);

        Map<String, Object> map = new HashMap<>();
        map.put("status", 0); // status 0으로 해놓고 
        if(ret == 1){ // ret =1 인경우
            map.put("status", 200); // status 200으로 바꿔준다.
        }
        return map;
    }

    // 회원 정보수정(이름, 연락처 변경/수정할 데이터) + (조건:회원정보)
    // (@ModelAttribute Member member) 를 가져와서 주어진 데이터만 넣는다
    // 127.0.0.1:8080/ROOT/member/update.json
    @PutMapping(value = {"/update", "/update.json"})
    public Map<String, Object> updatePUT(@ModelAttribute Member member){

        Map<String, Object> map = new HashMap<>();
        short ret = mService.updateMember(member);
        map.put("status", 0); // status 0으로 해놓고 
        if(ret == 1){ // ret = 1인경우 
            map.put("status", 200); // status 200으로 변경
        }
        return map;
    }

    // 회원 전체목록 가져오기
    // 127.0.0.1:8080/ROOT/member/selectlist.json
    @GetMapping(value = "/selectlist.json")
    public Map<String, Object> selectListGET(){

        Map<String, Object> map = new HashMap<>();

        // mService 이용해서 가져오기
        List<Member> list = mService.selectListMemberList();
        map.put("status", 0);
        if(list != null){
            map.put("status", 200);
            map.put("list", list);
        }
        return map;
    }

    // 회원 삭제하기
    // 127.0.0.1:8080/ROOT/member/deleteone.json
    @DeleteMapping(value = "/deleteone.json")
    public Map<String, Object> memberDELETE(@ModelAttribute Member member){
        
        Map<String, Object> map = new HashMap<>();
        int ret = mService.deleteOneMember(member);
        map.put("status", 0);
        if(ret == 1){
            map.put("status", 200);
        }
        return map;
    }
  }

📁 service / MemberService.java

  • 서비스에서 만든 회원정보수정을
    컨트롤러에서 사용
    map을 만든다
    멤버서비스에서 만들고 멤버 컨트롤러에서 사용
    updateMember
    Member.class 컬렉션 이름Member이기 때문에 타입class을 주어야 한다.
// Class<T> => 타입 => Member.class
package com.example.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.ExecutableInsertOperation.ExecutableInsert;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import com.example.entity.Member;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

@Service
public class MemberService {
    // 환경설정에 의해 연결된 DB의 객체
    @Autowired
    private MongoTemplate mongoTemplate;
    // = MongoTemplate mongoTemplate = new MongoTemplate();

    // 회원가입
    public int insertMember( Member member ){
        try{
            // mongoDB에 저장하기

            // insert(object) => MongoTemplate.insert(T objectToSave) : T
            // Member retMember = mongoTemplate.insert(member);

            // insert(Class<T>) => MongoTemplate.insert(Class<T> domainType) : ExecutableInsert<T>
            ExecutableInsert<Member> eInsert = mongoTemplate.insert(Member.class);
            Member retMember = eInsert.one(member);

            if( retMember != null ){
            return 1;
        }
        return 0;

        }catch(Exception e){
            e.printStackTrace();;
            return -1;
        }
    }

    // 로그인
    public int loginMember( Member member ){
        try {
            // MongoTemplate.findOne(Query query, Class<T> entityClass) : T
            // Member retMember = mongoTemplate.findOne();
            return 0;

        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    // 회원정보수정
    public short updateMember( Member member ){
        try {
            // 조건
            Query query = new Query();
            Criteria criteria = Criteria.where("_id").is(member.getId());
            query.addCriteria(criteria);

            // 이름과 연락처만 변경
            Update update = new Update();
            update.set("name", member.getName());
            update.set("phone", member.getPhone());

            // (조건, 변경값, 클래스)
            // MongoTemplate.updateFirst(Query query, UpdateDefinition update, Class<?> entityClass) : UpdateResult
            // Class<T> => 타입 => Member.class
            UpdateResult result = mongoTemplate.updateFirst(query, update, Member.class);
            if(result.getModifiedCount() == 1L){
                return 1;
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();;
            return -1;
        }
    }


    // 회원목록
    // 목록일경우 List<Entity>
    public List<Member> selectListMemberList(){
        try {
            // MongoTemplate.findAll(Class<T> entityClass) : List<T>
            // Class<T> => Member.class
            return mongoTemplate.findAll(Member.class);
            
        } catch (Exception e) {
            e.printStackTrace();;
            return null;
        }
    }

    // 회원 삭제
    public int deleteOneMember( Member member ){
        try {

            Query query = new Query();
            Criteria criteria = Criteria.where("_id").is(member.getId());
            query.addCriteria(criteria);
        
            // MongoTemplate.remove(Query query, Class<?> entityClass) : DeleteResult
            DeleteResult result = mongoTemplate.remove(query, Member.class);
            if(result.getDeletedCount() == 1L){
                return 1;
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();;
            return -1;
        }
    }

}

회원가입

  1. MemberService에서 mongoTemplate 사용하여 필요한 형태의 insert선택
//insert(Class<T>) => MongoTemplate.insert(Class<T> domainType) : ExecutableInsert<T>
ExecutableInsert<Member> eInsert = mongoTemplate.insert(Member.class);
            Member retMember = eInsert.one(member);
  1. int 형태로 return
  2. mService객체 사용하여 insertMember사용
  3. if(ret == 1)이면 return map

회원삭제

  1. MemberService에서 mongoTemplate 사용하여 필요한 형태 remove선택
// MongoTemplate.remove(Query query, Class<?> entityClass) : DeleteResult
            DeleteResult result = mongoTemplate.remove(query, Member.class);
  1. 해당 remove에 필요한 (조건, 클래스) 넣어주기
Query query = new Query();
            Criteria criteria = Criteria.where("_id").is(member.getId());
            query.addCriteria(criteria);
  1. int 형태로 return
  2. mService객체 사용하여 deleteOneMember 사용
  3. if(ret == 1)이면 return map

counter 생성

MemberService의 시퀀스 만들기
counter entity 있어야 DB랑 일할 수 있다!
엔티티 완성 후 서비스 생성

📁 entity / counter.java

@Document ➡️ DB counters에 collection 생성

package com.example.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@NoArgsConstructor //생성자
@ToString
@Document(collection = "counters") //counters에 생성
public class Counter {

    @Id
    private String no=null; //_id
    private String id=null; //id
    private Long seq=null; //seq
    
}

📁 service / CounterService.java

  • CounterService는 꼭 컨트롤러에서만 쓰는게 아니라 다른곳에서도 필요하면 사용할 수 있다.
  • 카운터 서비스에는 수정삭제조회 넣을필요 없다!
    ➡️ 카운터 서비스는 시퀀스 조회 전용이다. 그래서 수정,삭제,조회 등 추가적인 서비스 넣을 필요 없이 시퀀스 세는 서비스 하나만 있으면 된다.
  • 현재 사용하고 싶은 시퀀스 아이디 SEQ_~ 를 일치하는것을 찾고,
    해당하는 아이디의 시퀀스를 1 증가
  • upsert(true) = 업데이트 + 인서트
    ➡️ 옵션에서 upsert를 주면 인서트와 업데이트 동시수행

    DB에 컬렉션이 있으면 조회 후 seq 1 증가,
    DB에 컬렉션이 없으면 컬렉션 새로 생성 + seq에 1 설정

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import com.example.entity.Counter;

@Service
public class CounterService {
    @Autowired // mongodb연동
    MongoTemplate mongoTemplate;

    public long generateCounter(String id) {
        // MongoTemplate.findAndModify(Query query, UpdateDefinition update, Class<T>
        // entityClass) : T
        // 조건
        Query query = new Query();
        // where("id") => mongodb의 id, is(id)=> generateCounter(String id)의 값
        query.addCriteria(Criteria.where("id").is(id));

        Update update = new Update();
        // inc = 증가
        // Update.inc(String key, Number inc) : Update
        update.inc("seq", 1);

        // 옵션
        FindAndModifyOptions option = FindAndModifyOptions.options().returnNew(true).upsert(true);

        // 조회 후 업데이트 => query가 존재하면 seq 증가, query가 없으면 counter 데이터 생성 후 inc 1증가
        Counter counter = mongoTemplate.findAndModify(query, update, option, Counter.class);
        if (counter != null) {
            return counter.getSeq(); //counter에 부여된 seq번호를 return한다
        }
        return 1;
    }

}

0개의 댓글