Spring Boot Extension Pack 설치
- Project Lombok(lombok)
: 상용구 코드를 최소화하기 위한 코드를 생성 하는 Java 라이브러리 도구- web 웹개발환경
- tomcat : 웹서버 구동용,
웹 애플리케이션을 기반으로 하는 Servlet 및 JAVA 서버 페이지를 실행- 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
👨🏫 어떻게 와서 어떻게 호출하는지
뭐가 오고 뭐가 가는가 ! 이게 중요하다
controller = view로 생각하면 된다
@RestController
➡️ 이 파일이 컨트롤러라는 것을 명시해 주는 역할
해당파일이 어떤 파일인지 명시가 되어야 그 역할을 인식할 수 있다.
@GetMapping("/test")
➡️ 여기에서 만드는 모든 업무는 주소에 /test가 붙는다
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에 바로 적어주면 된다
홈 컨트롤러에 계속 생성 가능하지만 한 컨트롤러에 많은 코드를 생성하는 경우 파일이 길어지고 관리하기 어려워진다
새 파일로 생성하여 관리해주면 나중에도 유지관리가 편리해진다
@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;
}
}
- 서비스에서 만든 회원정보수정을
컨트롤러에서 사용
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;
}
}
}
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);
int
형태로 returninsertMember
사용if(ret == 1)
이면 return map// MongoTemplate.remove(Query query, Class<?> entityClass) : DeleteResult
DeleteResult result = mongoTemplate.remove(query, Member.class);
Query query = new Query();
Criteria criteria = Criteria.where("_id").is(member.getId());
query.addCriteria(criteria);
int
형태로 returndeleteOneMember
사용if(ret == 1)
이면 return map
MemberService
의 시퀀스 만들기
counter entity 있어야 DB랑 일할 수 있다!
엔티티 완성 후 서비스 생성
@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
}
- 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;
}
}