bbs-basic 새로 만들기
pom.xml 에서 의존성 추가
spring-boot-starter-jdbc (버전태그 없애도 됨)
mariadb-java-client
mybatis-spring-boot-starter (2.2.2version)
MyBatis란?
객체 지향 언어인 자바의 관계형 데이터베이스 프로그래밍을 좀 더 쉽게 할 수 있게 도와 주는 개발 프레임 워크로서 JDBC를통해 데이터베이스에 엑세스하는 작업을 캡슐화하고 일반 SQL 쿼리, 저장 프로 시저 및 고급 매핑을 지원하며 모든 JDBC 코드 및 매개 변수의 중복작업을 제거 합니다. Mybatis에서는 프로그램에 있는 SQL쿼리들을 한 구성파일에 구성하여 프로그램 코드와 SQL을 분리할 수 있는 장점을 가지고 있습니다.
- 복잡한 쿼리나 다이나믹한 쿼리에 강하다 - 반대로 비슷한 쿼리는 남발하게 되는 단점이 있다.
프로그램 코드와 SQL 쿼리의 분리로 코드의 간결성 및 유지보수성 향상
resultType, resultClass등 Vo를 사용하지 않고 조회결과를 사용자 정의 DTO, MAP 등으로 맵핑하여 사용 할 수 있다.
빠른 개발이 가능하여 생산성이 향상된다.
ORM(MyBatis)
- DAO가 사라짐. ~Mapper 인터페이스가 생김. 역할은 같음
- DBCP(Database Connection Pool)
- this.dataSource.getConnection() => 은 부하율/지연이 높다.
- DBCP를 이용하면 Connection을 미리 열어 놓고 빌려준 뒤 돌려받는 형식으로 작동.
- 따라서 서비스 중 Connection 새로 수립하지 않음.
- 대표적으로 HikariCP 사용
application.properties 에서
mybatis.mapper-locations=classpath;mappers/*/.xml 해석하자면
패키지 resources부터 시작. mappers는 그 안에 static과 templates와 형제 디렉토리
mappers/*.xml // #mappers/a.xml
mappers/*/*.xml // #mappers/a/b.xml mappers디렉토리 안에 무슨 이름이든 하나 있어야하고, 그 다음 b.xml
mappers/**/*.xml // #mappers/a/b/c.xml **은 중간에 0개가 오든 무한개가 오든 상관없다. 따라서 위 2개도 조건에 부합함.
mappers/a/b/d.txt 이건 모든 경우에 부합하지 않다.
sql쿼리문을 xml파일이 다 담을 것이다.
preferences에서 (단축키 : CMD+, )
Edit Configurations 들어가서
static 까지 경로 설정
(CMD + ; )
static에 불들어오는거 확인
bbabasic에서 controllers, mappers, sservices 패키지 생성
RootController 생성 후
TestService 생성 후
RootController 에서 @Autowired 추가
루트 컨트롤러는 아무나 주입못하고 테스트서비스에 의존적이다 라는 의미
@Autowired 이 생성자가 가진 메서드는 스프링이 알아서 객체화해야 한다라는 의미. 이것이 바로 의존성 주입
이제부터 테스트서비스를 알아서 객체화 해줄 것. 단 조건은 스프링이 인식 가능해야 한다. 예를 들어 @Controller나 @Service가 붙어있어야 함
ITestMapper 생성 (인터페이스가 가진 모든 메서드의 접근 제한자는 public이다.)
컨트롤러는 컨트롤러, 서비스는 서비스 어노테이션이 붙듯이 마찬가지로 매퍼에도 매퍼 어노테이션을 붙인다.
XML은 다오 갯수만큼 늘어나기 때문에 앞으로 계속 써야할 구문을 내가Mybatis.XML을 직접 하나 만들어주는 것.
DB를 연결
이제 실제로 실행할 쿼리를 선택하면 된다.
ItetsMapper의 메서드를 실행하면 이 쿼리문을 실행하겠다 라는 뜻.
xml파일과 인터페이스 관계의 연결 자체를 수립하는 건 namespace의 역할이고 그 아래에 select에 이름을 주게 되면 그 메서드와 연결이 되는 것.
즉,
네임스페이스는 인터페이스의 풀네임이 와야 되고
셀렉트 아이디 속성 값은 메서드의 이름과 같아야 한다를 명심하자
@Select 어노테이션 사용해보기.
매퍼,서비스,xml 지우고 컨트롤러 백지로 돌려놓고 다시 시작.
resources에 templates 안에 fragments 디렉토리 생성.
footer.html 과 header.html을 만들고 내용추가
그 안에 root와 uesr를 만들고 index.html과 register.html을 각각 만들어준다.
templates디렉토리에서는 template.html 생성 후 내용 추가
th:fragment 이용하여 footer와 header html을 담음.
그리고
<th:block th:replace="~{fragments/header :: header}"></th:block>
<th:block th:replace="~{fragments/footer :: footer}"></th:block>
th:replace를 이용하여 두 html 내용을 전부 가져왔다.
title에는 templateTitle 객체를,
main에는 templateMain 객체를 지정.
RootController 생성 후 modelAndView를 이용해 templateTitle과 templateMain에 값을 지정한다.
주소를 http://localhost:8080/ 로 지정.
template이 뷰단이고 브라우저네임을 메인 페이지라 지정.
뷰단의 main태그 내용을 root/index에서 가져온다.
header 에서 form태그 안에 POST 메소드를 연결하였고,
<form method="post" th:action="@{/user/login(prev=${#request.getRequestURI()})}">
action으로 링크 연결. UserController의 postLogin.
그럼 RequestMapping POST가 요청을 받는다.
(UserController 추가해서 그 안에 만들었음.)
RequestParam으로 prev 이름을 가진 prevPath의 값이 '/'인 것을 만들고
return 을 "redirect:" +prevPath로 지정.
그럼 http://localhost:8080/ 이것과 같은 말이 된다.
고로 submit을 해도 제 자리인 것을 확인.
<form method="post" th:action="@{/user/login(prev=${#request.getRequestURI()})}">
request.getRequestURI()는 어느 주소든(사용자의 요청) 다 받는 목적으로 쓰인 것이고(즉, 그 요청한 페이지로 간다는 것), 여기서 쓰이는 이유는 클라이언트 요청에 따라 현재 어느 페이지에 있든 정보를 보내는 이 액션 태그의 경로가 POST의 prev로 보내지게끔 하기 위함이다.
우리가 8080/ 에서만 login이 있으면 필요없었겠지만, 회원가입을 눌러도 이 header는 고정이 되어 user/register 경로에서도 나타난다. 고로 이 경로에서도 정보를 보내야 하기 때문에 사용자의 요청 경로가 어디든 그 경로에서 정보를 보낼 때 저 POST 메소드로 향하게끔 하는게 목적인 것
(register 는 아직 구현 X
현재까지 확인해보면
template 뷰단으로 header(상단) root/index(메인) footer(하단) 을 구현해두었다.
로그인(submit)은 제자리 주소를 반환하고 있고,
비밀번호 재설정과 회원가입은 header의 아래 내용으로 경로를 설정해두었음.
<a th:href="@{/user/login}">비밀번호 재설정</a> <!--user 디렉토리 안 login.html로 연결-->
<a th:href="@{/user/register}">회원가입</a> <!--user 디렉토리 안 register.html로 연결-->
th:replace & th:insert
fragment와 함께 쓰이며, 각 화면에 분리해 놓은 fragment를 붙여넣을 때 사용한다.
th:replace는 태그 전체를 교체해주는 것이다.(아래 예시 경우, head 태그 자체가 fragments.html의 head로 바뀐다.)
// index.html
<head th:replace="fragments.html :: head"></head>
th:insert는 해당 태그 내부에 fragment를 삽입해주는 것이다.(아래 예시 경우, div 태그 내부에 fragments.html의 content가 삽입된다.)
// index.html
<div th:insert="fragments.html :: content">
</div>
context path
절대경로 설정
springboot 에서는 default context path 를 / 로 설정합니다.(기본값)
대부분의 웹서버, WAS, 혹은 Springboot 의 내장 서버 역시 다 root 를 기본으로 가지고 있습니다. 즉, 로컬 개발 시 http://localhost:8080/ 과 같은 주소가 되는 것입니다. 그리고 각 controller 에서 설정한 Request Mapping 정보에 따라서 그 하위로 경로가 생성됩니다.
그런데 경우에 따라서 이 경로를 수정해야 하는 경우가 있습니다.
설정 파일인 application.properties 에 설정하게 되므로, 실행하는 profile 에 따라서 application-dev.properties 등에 별도로 지정하여 활용할 수 있습니다.
application.properties 파일을 수정하여 적용하는 것이 가장 효율적인 적용 방법입니다. 다른 여러가지 방법이 있고, Spring 의 기본 객체를 상속(구현)하여 적용하는 방법 역시 가능합니다. 하지만 Springboot 는 application.properties 파일을 통한 설정 변경을 권장하고 있고, 더욱 상세한 설정이나 properties 파일로 적용되지 않는 사항을 제외하고는 가급적이면 properties 파일을 수정하여 적용하는 것을 권장합니다.
키 값은 server.servlet.context-path 입니다.
server.servlet.context-path=/simplify
스프링 프로젝트를 재실행하면 http://localhost:8080/simplify를 통해서만 접속되는 것을 확인할 수 있습니다.
${pageContext.request.contextPath} 사용함으로 써 상대 경로 즉, 내 위치에 따라 값이 변하던 게 고정이 된다.
정확히 말하면 고정이 아니라 알아서 위치를 찾아서 맞춰주는 겁니다.
참고링크