의존성 설정

build.gradle

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}

스프링 부트 라이브러리

  • spring-boot-starter-web

    • spring-boot-starter-tomcat: 톰캣(웹서버)
    • spring-webmvc: 스프링 웹 MVC
  • spring-boot-starter-thymeleaf : 타임리프 템플릿 엔진(view)

  • spring-boot-starter(공통) : 스프링 부트 + 스프링 코어 + 로깅

    • spring-boot
      • spring-core
    • spring-boot-starter-logging
      • logback,slf4j

테스트 라이브러리

  • spring-boot-starter-test
    • junit: 테스트 프레임워크
    • mockito : 목 라이브러리
    • assertj : 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리
    • spring-test : 스프링 통합 테스트 지원

 

 


 

 

기본 view

 

  Welcome Page

   

resources/static/index.html

 

 

 

index.html

<!DOCTYPE HTML>
<html>
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello Spring
</body>
</html>

 

http://localhost:8080/

 

 

@Controller

 

 

HelloController.java

@Controller
public class HelloController {

    @GetMapping("hello") //http://localhost:8080/hello
    public String hello(Model model){
        model.addAttribute("data","hello");
 
        return "hello";    //   resources/templates/hello.html
    }
    
    
    }

 

resources/templates/hello.html

 

 

hello.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" >안녕하세요</p>
</body>
</html>

 

${data}  <=  HelloContrller 에 Model model 에 있는 key 값  (value는 hello)

 

 

 

 

 

 

 


 

MVC와 템플릿엔진

 

HelloController.java

 
 @Controller
public class HelloController {
 
 @GetMapping("hello-mvc")
    public String helloMvc(@RequestParam("NAME") String name , Model model){

         model.addAttribute("name", name);

        return "hello-template";  //resources/templates/hello-template.html
    }
    
   }

 

 

http://localhost:8080/hello-mvc?NAME=""

 

@RequestParam("NAME")  <=  ( ?NAME= )

 

 

@RequestParam의 값이 Model 의 value가 된다.

 

 

 

resources/templates/hello-template.html

 

hello-template.html

<html xmlns:th="http://www.thymleaf.org" >
<body>

<p th:text="'안녕 내이름은' +${name} + '야!!'" >hello! empty</p>

</body>

</html>

 

실행

http://localhost:8080/hello-mvc?NAME=park

 

 

 

 

 

 

 

출처 www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8

정적콘텐츠

 

공식 문서

Spring Boot Feature

 

resoureces/static/**

 

 

 

resources/static/hello-static.html

 

hello-static.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p> 정적 컨텐츠</p>
</body>
</html>

 

실행  => http://localhost:8080/hello.static.html

 

 

 

 

 

출처: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8

 

프로젝트 생성

 

start.spring.io/

 

 

스프링 부트 기반으로 프로젝트를 만들어주는 사이트이다.!!!

 

Maven Project , Gradle Project

 

필요한 라이브러리를 가져다 쓰고 빌드까지 관리해주는 툴이다.

 

과거에는 Maven을 많이 사용했지만,

 

요즘에는 Gradle를 많이쓴다!!

 

 

Spring Boot version 선택

 

SNAPSHOT = 만들고 있는 버전

 

 

Dependencies

사용할 라이브러리 선택!!

 

 

GENERATE를 눌러 설치!!

 

압축을 풀고

 

Eclipse 나 intellij에서 프로젝트 오픈!

의존성 설정

	<!-- 시큐리티 태그 라이브러리 -->
		
		<dependency>
		  <groupId>org.springframework.security</groupId>
		  <artifactId>spring-security-taglibs</artifactId>
		</dependency>
        
        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
        
        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

 

시큐리티 taglib 선언

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

 

security taglib

www.baeldung.com/spring-security-taglibs

 

Introduction to Spring Security Taglibs | Baeldung

Learn how to use Spring Security's tag library in your JSPs for finer-grained control of your views.

www.baeldung.com

 

 

시큐리티를 설정한 뒤 서버를 실행하면

이런 화면이 생성 된다.

 

어떤 url을 지정해도 스프링 시큐리티 라이브러리가 

서버를 가로채서

/login 으로 이동시킨다.

 

 

이때 아이디는 user를 입력하고

 

비밀번호는 

cosole에 있는 것을 입력한다.

 

 

이때 위에서 선언한 taglib와 함께

<sec:authorize access="isAuthenticated()">
	
	<script>
		alert("시큐리티 로그인");
	</script>
	<sec:authentication property="principal" var="principal" />
	
	
</sec:authorize>

속성을 지정한다.

 

isAuthenticated() = 시큐리티 로그인이 되었을때

 

principal = 시큐리티가 설정된 사용자에 대한  접근 권한

 

 

 

문서!

 

docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

 

15. Expression-Based Access Control

There are some built-in expressions which are specific to method security, which we have already seen in use above. The filterTarget and returnValue values are simple enough, but the use of the hasPermission() expression warrants a closer look. The Permiss

docs.spring.io

 

 

 

세션과 같은 역할을 하는 principal 사용

 

<c:choose>
		<c:when test="${empty principal}">
			<ul class="navbar-nav">
				<li class="nav-item">
               <a class="nav-link" href="/loginform">로그인</a></li>
				<li class="nav-item">
                <a class="nav-link"	href="/joinform">회원가입</a></li>
					</ul>
		</c:when>
		<c:otherwise>

			<ul class="navbar-nav">
				<li class="nav-item">
                <a class="nav-link" href="/board/form">글쓰기</a></li>
				<li class="nav-item">
                <a class="nav-link"	href="/user/form">회원정보</a></li>
				<li class="nav-item">
                <a class="nav-link"	href="/logout">로그아웃</a></li>
			</ul>
		</c:otherwise>

</c:choose>

 

 

시큐리티의 디폴트 url은  로그인 : /login , 로그아웃 : /logout

 

 

로그아웃:

 

기본 시큐리티 로그인 , 로그아웃에

사용자가 직접 만든 로그인, 로그아웃 form으로 커스터마이징 하여 사용하면 된다.

 

 

시큐리티를 사용하기 전

세션을 이용한  전통적인 로그인 방식

 

 

 

loginform.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%@ include file="../layout/header.jsp"%>
<form >
  <div class="form-group">
    <label for="username">아이디:</label>
    <input type="text" class="form-control" placeholder="아이디를 입력하세요" id="username">
  </div>
  
  <div class="form-group">
    <label for="pwd">비밀번호:</label>
    <input type="password" class="form-control" placeholder="비밀번호를 입력하세요" id="password">
  </div>
  <div class="form-group form-check">
    <label class="form-check-label">
      <input class="form-check-input" type="checkbox"> Remember me
    </label>
  </div>
</form>
  <button id="btn-login" class="btn btn-primary">로그인</button>

<script src="/js/user.js"></script>
<%@ include file="../layout/footer.jsp" %>

<script scr="/js/user.js"></script>

 

->

user.js

let index={
	init:function(){
		$("#btn-save").on("click",()=>{ //화살표 함수를 쓰는이유 this를 바인딩 하기 위해서
			this.save();
		});
		$("#btn-login").on("click",()=>{ //화살표 함수를 쓰는이유 this를 바인딩 하기 위해서
			this.login();
		});
	}
	,
	save:function(){
		//alert('user의 save함수 호출 됨')
		
		let data ={
			username: $("#username").val(),
			password: $("#password").val(),
			email: $("#email").val
		};
		
		//console.log(data);
		// ajax 호출시 default가 비동기 호출
		// ajax 통신을 이용해서 3개의 데이터를 json으로 변경하여 요청
		$.ajax({
			//회원가입 수행 요청
			type:"POST",
			url:"/api/user",
			data: JSON.stringify(data), // http body 데이터
			contentType:"application/json; charset=utf-8", //body 데이터가 어떤 타입인지(MIME)
			dataType: "json" // 요청을 서버로해서 응답이 왔을 때 기본적으로 모든것이 문자열
		}).done(function(resp){
			alert("회원가입이 완료되었습니다.");
			console.log(resp);
			location.href="/"
			
		}).fail(function(error){
			alert(JSON.stringify(error));
			
		}); //ajax 통신을 이용해서 3개의 데이터를 json으로
		//변경하여 insert 요청!!
	},
	login:function(){
		//alert('user의 save함수 호출 됨')
		
		let data ={
			username: $("#username").val(),
			password: $("#password").val(),
			
		};
		
		//console.log(data);
		// ajax 호출시 default가 비동기 호출
		// ajax 통신을 이용해서 3개의 데이터를 json으로 변경하여 요청
		$.ajax({
			//회원가입 수행 요청
			type:"POST",
			url:"/api/user/login",
			data: JSON.stringify(data), // http body 데이터
			contentType:"application/json; charset=utf-8", //body 데이터가 어떤 타입인지(MIME)
			dataType: "json" // 요청을 서버로해서 응답이 왔을 때 기본적으로 모든것이 문자열
		}).done(function(resp){
			alert("로그인이 완료되었습니다.");
			console.log(resp);
			location.href="/"
			
		}).fail(function(error){
			alert(JSON.stringify(error));
			
		}); //ajax 통신을 이용해서 3개의 데이터를 json으로
		//변경하여 insert 요청!!
	}
}

index.init();

ajax 통신을 이용!

url = /api/user/login

 

->

 

UserApiController.java

@Autowired
	private UserService userService;
	
	@Autowired
	private HttpSession session;

@PostMapping("/api/user/login")
	public ResponseDto<Integer> login(@RequestBody User user ){
		System.out.println("login 호출 됨 ");
		User principal = userService.로그인(user);
		//principal (접근주체)
		if(principal != null) {
			session.setAttribute("principal", principal); //세션 만듬
			
		}
		
		return new ResponseDto<Integer>(HttpStatus.OK.value(),1);
	}

UserService의 로그인 메서드 수행한 로직이

null 이 아니면

세션을 만들어

로그인 로직을 수행!!

 

 

UserService.java

@Autowired
	private UserRepository userRepository;
    
@Transactional(readOnly =true) 
	public User 로그인(User user) {
		
		return userRepository.findByUsernameAndPassword(user.getUsername(), user.getPassword());
		
	}

 

설정한 세션 값을 이용해

 

header.jsp

 

<div class="collapse navbar-collapse" id="collapsibleNavbar">
			<c:choose>
				<c:when test="${empty sessionScope.principal}">
					<ul class="navbar-nav">
						<li class="nav-item"><a class="nav-link"
							href="/loginform">로그인</a></li>
						<li class="nav-item"><a class="nav-link"
							href="/joinform">회원가입</a></li>
					</ul>
				</c:when>
				<c:otherwise>

					<ul class="navbar-nav">
						<li class="nav-item"><a class="nav-link"
							href="/board/form">글쓰기</a></li>
						<li class="nav-item"><a class="nav-link"
							href="/user/form">회원정보</a></li>
							<li class="nav-item"><a class="nav-link"
							href="/logout">로그아웃</a></li>
					</ul>
				</c:otherwise>

			</c:choose>
		</div>

화면 구성

 

www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm

 

JSP - Standard Tag Library (JSTL) Tutorial - Tutorialspoint

JSP - Standard Tag Library (JSTL) Tutorial In this chapter, we will understand the different tags in JSP. The JavaServer Pages Standard Tag Library (JSTL) is a collection of useful JSP tags which encapsulates the core functionality common to many JSP appli

www.tutorialspoint.com

 

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

jsp 파일에 붙여넣기

 

 

 

의존성 설정

<!-- JSTL -->
<dependency>
 	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>

 

 


※  그 전에 JSP 파일을 스프링 부트에서 사용하려면

 

<!-- JSP 템플릿 엔진 -->
		 	
		 <dependency>
		  <groupId>org.apache.tomcat.embed</groupId>
		  <artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

JPA란?

Java Persistence API 이다.

 

Persistence(영속성)

 

영속성(persistence)은 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성을 의미한다. 영속성은 파일 시스템, 관계형 테이터베이스 혹은 객체 데이터베이스 등을 활용하여 구현한다. 영속성을 갖지 않는 데이터는 단지 메모리에서만 존재하기 때문에 프로그램을 종료하면 모두 잃어버리게 된다. 결국 영속성은 특정 데이터 구조를 이전 상태로 복원할 수 있게 해주어 프로그램의 종료와 재개를 자유롭게 해준다.

출처: https://sugerent.tistory.com/587 [MISTERY]

 


 

의존성 설정

 <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

 

 

어노테이션

 

@Entity

DB에 테이블을 생성해주는 어노테이션

import javax.persistence.Entity;
@Entity // User 클래스가 MySql에 테이블이 생성이 된다.
public class User {
	
	@Id
	private int id; // 시퀀스, auto-increment
	private String username; //아이디
	private String password;
	private String email;
	private Timestamp createDate;
}

 

MySql에 User 테이블이 생성 된다.


@Id

DB에 primary key 생성

import javax.persistence.Id;
	@Id //primary key
	private int id; // 시퀀스, auto-increment
	private String username; //아이디
	private String password;
	private String email;
	private Timestamp createDate;

@GeneratedValue

넘버링 전략

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
	@Id //primary key
	@GeneratedValue(strategy = GenerationType.IDENTITY) //프로젝트에 연결된 DB의 전략을 따라감
	private int id; // 시퀀스, auto-increment
	private String username; //아이디
	private String password;
	private String email;
	private Timestamp createDate;

 

4가지 타입이 있다.

그 중 IDENTITY를 사용하면 프로젝트에 연결된 DB(필자는 mysql) 의 전략을 따라감

 

ex) 오라클의 경우 -> sequence , MySql의 경우 -> Auto Increment

 


 

 

 

@Column

DB에 Column에 해당하는 속성을 지정

import javax.persistence.Column;

속성은 다음과 같다.

 

결론

 JPA =

자바 프로그래밍을 할 때 영구적으로 데이터를 저장하기 위해 필요한 인터페이스 이다.

  • JPA는 ORM 기술이다.
  • JPA는 반복적인 CRUD 작업을 생략하게 해준다.
  • JPA는 DB와 OOP의 불일치성을 해결하기 위한 방법론을 제공한다.
  • JPA는 OOP의 관점에서 모델링을 할 수 있게 해준다. (상속, 콤포지션,연관관계)
  • 방언 처리가 용이하며 Migration하기 좋음, 유지 보수에도 좋다
  • JPA는 쉽지만 어렵다

 

출처 : https://getinthere.tistory.com/10

@AllArgsConstructor

lombok 어노테이션 의 하나로,

 

모든 매개변수가 있는 생성자를 의미한다.

 

 

@AllArgsConstructor

=

 

Member.java

public class Member {
	
	private int id;
	private String username;
	private String password;
	private String email;
	
	
	
	public Member(int id, String username, String password, String email) {
		super();
		this.id = id;
		this.username = username;
		this.password = password;
		this.email = email;
	}

으로 @AllArgsConstructor 어노테이션을 사용하면 굳이 이렇게 생성자를 만들 필요가 없다.

 

 

대신, 매개변수를 3개만 받는 경우

 

즉, 생성자 오버로드로 필요에 따른 매개변수를 설정을 할 때는 오류가 발생한다.

@RestController
public class HttpControllerTest {
	
	@GetMapping("/http/lombok")
	public String lombokTest() {
		Member m =  new Member(100,"hello","ddd@naver.com"); 
        //오류 발생
		
		
		
		return "lombok test 완료
	}
	
}

 

그렇기 때문에 그에 맞는 매개변수가 있는 생성자가 필요하다.

 


	public Member(int id, String username, String email) {
		super();
		this.id = id;
		this.username = username;
		this.email = email;
	}

 

매번 이렇게 생성자를 추가해야 할까?

 

이때 사용하는 것이 @Builder 어노테이션이다.

 


@Builder

생성자가 여러개 있을 필요 없이,

 

모든 매개변수가 있는 생성자를 하나 만든다.

 

	@Builder
	public Member(int id, String username, String password, String email) {
		super();
		this.id = id;
		this.username = username;
		this.password = password;
		this.email = email;
	}

생성자 위에 어노테이션을 입력한다.

 

※ @AllArgsConstructor은 모든 매개변수가 있는 생성자와 같은 역할이기때문에 중복이된다.

오류가 나기 때문에 Builder 패턴을 사용할 땐 지워야 한다.

 

 

이제 Builder 패턴을 사용해보자

 

Member m =  new Member(100,"hi","ddd@naver.com");

대신 ->

 

Member m =   Member.builder().email("ddd@").password("1122").build();

.builder()로 열고 .build()로 닫는다.

 

핵심은 !!

id,username,password,email 다 값을 넣어도 되고 일부분만 값을 넣어도 된다.

그리고 제일 좋은 점은 순서에 구애 받지 않는다는 것이다.

 

생성자로 초기화 할 때는 id,username, password, email 순서로 초기화를 시켜야 하지만

Builder 패턴은 순서에 상관없이 초기화 할 수 있는 것이 큰 장점이다.

 

 

projectlombok.org/download

 

Download

 

projectlombok.org

다운로드

 

 

 

설정

 

경로:

C:\Users\사용자이름\.m2\repository\org\projectlombok\lombok\1.18.16

 

git bash here

 

 

 

 

 

 

select 한 뒤

 

install 완료

 

 

 

 

 

 

+ Recent posts