Java - 자바 버전 변경하는 방법 ( JDK 8 -> JDK 17)
책에서 소개하는 대로 JDK버전을 17로 변경 후 https://start.spring.io/ 에서 위 사진과 같이 첫번째 프로젝트를 만들어 돌려보았다.
...그러나 바로 에러발생.
이유도 제대로 안나와서 뭔가 했으나 실행 시 에러가 나는 위치에 printStackTrace();를 찍어봤다.
결론은 port번호 8080은 이미 사용중이라는 에러였다.
바로 application.properties
에 server.port = 8081
을 입력해 8081
로 변경했다.
static폴더에 hello.html 파일을 추가한 후 실행해보니 정상적으로 돌아간다.
Controller에 Model객체를 받아와 사용자에게서 속성과 속성에 대한 값을 받아올 수 있도록 함.
- FirstController -
@Controller
public class FirstController {
@GetMapping("/hi")
public String niceToMeetYou(Model m, String name){
m.addAttribute("username", name);
return "greetings"; // greetings.mustache 파일반환
}
@GetMapping("/bye")
public String seeYouNext(Model m, String name){
m.addAttribute("username", name);
return "goodbye";
}
}
- greetings.mustache -
<h1>{{username}}님, 반갑습니다!</h1>
- goodbye.mustache -
<h1>{{username}}님, 안녕히 가세요.</h1>
name속성의 값을 넘겨주면 이름과 뷰페이지의 내용이 정상적으로 출력됨.
만약 name속성을 넘겨주지 않을 경우 위 사진처럼 에러가 발생.
@PathVariable
을 사용하면 어떨까 싶어 seeYouNext메서드만 아래와 같이 변경.
@GetMapping("/bye/{name}")
public String seeYouNext(Model m, @PathVariable String name){
m.addAttribute("username", name);
return "goodbye";
}
마찬가지로 http://localhost:8081/bye 로 접속하면 404오류가 발생. 아래 사진처럼 URI로 변수를 받아올 수 있다.
참고: mustache파일의 경우 빌드를 다시해야 변경점이 반영됨.
빌드 단축키: ctrl + f9
Article entity클래스의 id필드에 @GeneratedValue
를 빼먹어서 숫자 자동증가가 안되어 에러발생했었음.
CREATE TABLE hongongspringboot.article(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50) NOT NULL,
content VARCHAR(1000) NOT NULL
)DEFAULT CHARSET=UTF8;
INSERT INTO hongongspringboot.board(title, content) VALUES("첫번쨰 게시글", "첫 게시글의 내용입니다.");
책에서는 H2 DB를 사용하지만 나는 MySQL을 사용하기로 함.
// https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.4'
- application.properties -
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/DB스키마이름
spring.datasource.username=접속ID
spring.datasource.password=패스워드
#update the schema with the given values.
#spring.jpa.hibernate.ddl-auto=update
#To beautify or pretty print the SQL
spring.jpa.properties.hibernate.format_sql=true
#show sql
spring.jpa.properties.hibernate.show-sql=true
#show parameter binding
logging.level.org.hibernate.type.descriptor.sql=DEBUG
logging.level.org.hibernate.SQL=DEBUG
server.servlet.encoding.force=true
server.port = 포트번호
https://wecandev.tistory.com/71
위 링크를 참고해 application.properties에 속성을 몇개 추가했는데, 몇개 주의해야할 속성이 있으므로 무엇인지 확인해놓자. (주의점은 링크 를 참고.)
spring.jpa.hibernate.ddl-auto=update
속성은 사용에 주의가 필요한 것 같아 우선은 주석처리해둠.
@Controller
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
@GetMapping("/articles/new")
public String newArticleForm() {
return "articles/new";
}
@PostMapping("/articles/create")
public String createAricle(ArticleForm form) {
System.out.println("form.toString() = " + form.toString());
// 1. DTO를 entity로 변환
Article article = form.toEntity();
System.out.println(article.toString());
// 2. repository로 entity를 DB에 저장
Article saved = articleRepository.save(article);
System.out.println(saved.toString());
return "";
}
}
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 자동생성. GenerationType.IDENTITY는 기본키 생성을 DB에 맞기는 전략.
private Long id;
@Column
private String title;
@Column
private String content;
public Article() {}
public Article(String title, String content) {
this.title = title;
this.content = content;
}
// toString 생성
}
책에서는 @GeneratedValue(strategy = GenerationType.IDENTITY)
속성을 기본형인 @GeneratedValue
로 사용하지만 아마 DB 저장이 안되는 H2를 사용해서인것으로 추측.
나의 경우 mariaDB를 사용하므로 DB에서 autoincrement를 해주도록 GenerationType.IDENTITY
속성으로 사용함.
entity클래스에는 getter setter를 만들지 않음.
- ArticleForm (DTO클래스) -
public class ArticleForm {
private String title;
private String content;
public ArticleForm() { }
public ArticleForm(String title, String content) {
this.title = title;
this.content = content;
}
// getter setter toString 생성
public Article toEntity() {
return new Article(title, content);
}
}
article을 참고하여 member 가입기능 만들기.
CREATE TABLE hongongspringboot.members(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(50) NOT NULL,
password VARCHAR(100) NOT NULL,
name VARCHAR(30) NOT NULL
)DEFAULT CHARSET=UTF8;
만약 롬복인식이 안된다면 링크를 확인하여 참고하자.
계속 값을 못받아오거나 log
를 사용할수가 없어 한참 헤맷더니 롬복이 제대로 적용되지 않아서 생긴 문제였다.
CrudRepository
의 기본메서드인 findById, findAll메서드를 이용함.
@Slf4j
@Controller
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
@GetMapping("/articles/new")
public String newArticleForm() {
return "articles/new";
}
@PostMapping("/articles/create")
public String createAricle(ArticleForm form) {
log.info(form.toString());
// 1. DTO를 entity로 변환
Article article = form.toEntity();
System.out.println(article.toString());
// 2. repository로 entity를 DB에 저장
Article saved = articleRepository.save(article);
log.info(saved.toString());
return "redirect:/articles/" + saved.getId();
}
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model m){
log.info("id = " + id);
// 1. DB에서 데이터 조회해 가져오기
Optional<Article> articleEntity = articleRepository.findById(id);
// 2. model에 데이터 등록하기
m.addAttribute("article", articleEntity.get());
// 3. 뷰 페이지 반환하기
return "articles/show";
}
@GetMapping("/articles")
public String showAll(Model m){
// 1. DB에서 모든 데이터 가져오기
List<Article> articleEntityList = articleRepository.findAll();
// 2. model에 데이터 등록하기
m.addAttribute("articleList", articleEntityList);
// 3. 뷰 페이지 반환하기
return "articles/index";
}
@GetMapping("/articles/{id}/edit")
public String edit(){
return "articles/edit";
}
}
findAll()
메서드의 기본리턴형이 Iterable
형이라 List형으로 변경하기 위해 Override해줌.
public interface ArticleRepository extends CrudRepository<Article, Long> {
@Override
ArrayList<Article> findAll();
}
- ArticleForm (dto) -
@ToString
@AllArgsConstructor
@Builder
public class ArticleForm {
private Long id;
private String title;
private String content;
// 이 부분 생성자말고 빌더패턴으로 변경하고싶은데 잘안돼서 그냥놔둠
public Article toEntity(){
System.out.println("toEntity()에서 title = " + title +" content = " + content);
return new Article(id, title, content);
}
}
toEntity메서드를 Entity의 생성자를 이용하지 않고 빌더패턴을 사용하고싶으나, 현재로는 마음대로 적용되지않아 추후 변경할 예정.
- Article (entity) -
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Entity
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 자동생성. GenerationType.IDENTITY는 기본키 생성을 DB에 맞기는 전략.
private Long id;
@Column
private String title;
@Column
private String content;
}
id값도 같이 넘겨줘도 무관.
id값을 생성자에서 빼버리면 추후 수정, 삭제기능 구현 시 게시글을 구별할 수 없음.
현재로써는 service단을 따로 만들지 않아 구조가 이렇지만 책을 따라 진행하며 service단을 추가할듯함.