프로젝트 마이그레이션 중 ( 구조 중심 설명)
1) 의존성 (라이브러리)
2) web.xml 세팅 (접근주소)
3) 프로젝트세팅
4) 프로젝트 동작방식 (Controller ->service-> mapper -> view )
4-1)controller
4-2)service
4-3)mapper
4-4)총정리
프로젝트의 내용은똑같으므로
동작방식이 달라진것만 설명을하겠슴다
1) 의존성 (라이브러리)
일단 스프링부트를 사용해서 전체적인 프로젝트구조도 달라졌으며
이제는 라이브러리를 jar파일로 넣지않고 pom.xml에 의존성을 추가해서
가져오는 방식을 사용함
해당사이트에서 원하는 라이브러리명을 입력하면 의존성 코드가나올거다
다음과같이 추가해주면된다!!!!!
2) web.xml 세팅 (접근주소)
다음 코드는 web.xml 코드이다
우리 프로젝트의 주소를 나타냄!!!!
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<display-name>lms</display-name>
<context-param>
<param-name>contextPath</param-name>
<param-value>/</param-value>
</context-param>
</web-app>
web.xml을 적용하지않았던 기존의 servlet구조 프로젝트
web.xml을 적용한 현재의 springBoot프로젝트
3) 프로젝트세팅
/resources/application.properties
application.version=1.0.0
server.servlet.context-path=/
# JSP View
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
# MariaDB DataSource
spring.datasource.url=jdbc:mariadb://kdt.goodee.co.kr:10001/lms
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
# Mybatis
mybatis.config-location=classpath:mybatis-config.xml
# MyBatis
mybatis.type-aliases-package=com.ldb.lms.dto.**
mybatis.mapper-locations=classpath:mapper/**/*.xml
spring.mvc.view.cache=false
spring.mvc.hiddenmethod.filter.enabled=true
spring.devtools.restart.additional-paths=/WEB-INF/views/
#Log level
logging.level.org.mybatis.spring=DEBUG
logging.level.org.apache.ibatis=DEBUG
logging.level.com.ldb.lms.mapper=TRACE
#picture
spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
spring.messages.basename=messages
spring.messages.encoding=UTF-8
여기서중요한것들만 간단히설명하겠음
#jsp view의 주석 하위의 코드는
컨트롤러에서 String을 반환하면 해당 경로의 jsp를 찾는다는 소리임
또한
Datasource를 따로만들지않고
application.properties에 DB정보를 모두 넣어둬
자동으로 연동을 시킴
4) 프로젝트 동작방식 (Controller ->service-> mapper -> view )
4-1) controller
controller/mypage/MypageController
package com.ldb.lms.controller.mypage;
import java.util.Map;
import org.springframework.stereotype.Controller;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.ldb.lms.service.mypage.MypageService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
@Controller
@RequestMapping("/mypage")
@RequiredArgsConstructor //final이 붙은 필드이용 생성자 자동생성
public class MypageController {
private final MypageService mypageService;
@GetMapping("doLogin")
public String callDoLogin (HttpServletRequest request) {
//로그인 상태로 doLogin에 접근 불가능
if(mypageService.loginChk(request)) {
return "error";
}
return "mypage/doLogin";
}
@PostMapping("login")
public String login(@RequestParam String id, @RequestParam String password, HttpServletRequest request) {
if (mypageService.login(id, password, request)) {
// 로그인성공시 메인페이지로
return "redirect:/";
} else {
return "mypage/doLogin";
}
}
localhost8080:/mypage/doLogin 이라는 주소가 매핑되면
@getMapping("doLogin")이 붙은 메서드를 타게됨
(get방식의 파라미터만 받을 수 있음)
request매개변수를 설정 해
mypageService(서비스계층) 으로 보내
반환값에 따라 error페이지로 이동하거나
/WEB-INF/views/mypage/doLogin 이라는 jsp를 찾아갈것임!!!
%%postMapping은 post방식으로 호출할때만 가능한 방법임
@RequestParam을이용해 속성을 받을 수 있음
@ModelAttribute로 객체를 통쨰로 받을수도 있긴합니다!!!!
( id,password를 속성으로 가지는 DTO생성하면가능)%%
4-2) service
(@Service 를 이용해 서비스계층사용하겠다고 명시!!!!
@RequiredArgsconstructor 를 이용해 final 자동생성자 주입 ( 안하면 mapper사용불가)
@Service
@RequiredArgsConstructor
public class MypageService {
private final StudentMapper studentMapper;
private final ProfessorMapper professroMapper;
private final ProStuMapper proStuMapper;
private final DeptMapper deptMapper;
public boolean loginChk(HttpServletRequest request) {
String login = (String)request.getSession().getAttribute("login");
if(login==null) {
request.getSession().invalidate(); //일단세션 다날려
return false;
}
else {
request.setAttribute("error", "로그아웃을 하세요");
return true;
}
}
public boolean login(String id , String password , HttpServletRequest request) {
LoginChkDto loginChkDto = proStuMapper.loginChk(id);
if(loginChkDto == null) {
request.setAttribute("error", "존재하지않는 정보");
return false;
}
else {
//loginChkDto코드를 보면이해가능 studentId가존재 시 studentId를 반환
//professorId가 존재한다면 professorId가 반환되게 getId를 튜닝함
String dbId = loginChkDto.getId();
String dbPw = loginChkDto.getPassword();
//Bcrypt.checkpw(입력,검증) : 입력과 검증(암호화된비번) 을 비교할수있음
if(BCrypt.checkpw(password, dbPw) ){
if(dbId.contains("S")) { //학생 중 퇴학상태인 학생을 검증하는 단계
if(studentMapper.selectStatus(dbId).equals("퇴학")) {
request.setAttribute("error", "퇴학한사람은 로그인 할 수 없어요");
return false;
}
}
//모든정보가 일치한다면
request.getSession().setAttribute("login", dbId);
request.setAttribute("out",null);
return true;
}
else{
request.setAttribute("error", "아이디혹은비밀번호를 확인해주세요");
return false;
}
}
}
}
loginCheck메서드는 간단하게 세션검증만 하므로 mapper까지 넘어가지않는다
login메서드에 대해 아주간단히설명하겟음
(로직설명은 하지않고 구조만)
DB조회가 필요하므로 proStuMapper라는 곳의 메서드에 id하나를 매개변수로 넘겨서
select문을 통해 loginChkDto를 반환하는 것임
(loginchkDto : id,pasword 존재)
그 후 null값 검증과 회원의 퇴학여부 검증 , 비밀번호검증 등등을 한 후
모두 정상일 시 true반환
4-3) mapper , Dto
application.properties
# MyBatis
mybatis.type-aliases-package=com.ldb.lms.dto.**
mybatis.mapper-locations=classpath:mapper/**/*.xml
해당 설정으로 인해
1.dto패키지 내의 클래스들을 경로없이 클래스명으로
paramType or ResultType으로 사용이가능(별명설정) ,
2.mapper패키지 하위의 클래스들이 xml파일들을 인식할 수 있게함)
dto/LoginChkDto
package com.ldb.lms.dto.mypage;
@Getter
@Setter
@ToString
public class LoginChkDto {
private String id;
private String password;
private String studentId;
private String studentPassword;
private String professorId;
private String professorPassword;
public String getId() {
if(this.studentId==null) {
return getProfessorId();
}
else {
return getStudentId();
}
}
public String getPassword() {
if(this.studentPassword==null) {
return getProfessorPassword();
}
else {
return getStudentPassword();
}
}
}
id와 password의 get프로퍼티를 다음과같이 튜닝함
(null값이 아닌 속성을 뽑아냄)
mapper/ProStuMapper.interface
(xml에서 해당 메서드명과 똑같은 id를 가진 문장을 실행시킴)
@Mapper
public interface ProStuMapper {
//넘어온 id와 맞는 학생의id,pawssword를 추출
LoginChkDto loginChk(String id);
}
resource/mapper/mypage/ProStuMapper.xml
(namespace 설정 : 해당 경로의 mapper를사용하겠다는의미)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ldb.lms.mapper.mypage.ProStuMapper">
<!-- 넘어온 id와 맞는 학생의id,name,pawssword를 추출 -->
<select id="loginChk" resultType="LoginChkDto" parameterType="String">
SELECT student_id , student_password
FROM student
WHERE student_id = #{val}
UNION
SELECT professor_id ,professor_password
FROM professor
WHERE professor_id = #{val}
</select>
</mapper>
4-4) 총정리
controller는 속성을받아 service에 넘기거나
주소를 반환하는 용도로만 사용하게 구성
왠만한 로직은 service에서 담당
DB조회가필요하다면 mapper를 통해 조회 후
결과값에 따른 처리를 service에서 담당