21.02.28~03.01 Untact프로젝트(페이징~history.back(), location.replace() 도입까지)
2021. 3. 1. 20:47ㆍJAVA/Spring & Vue APP 프로젝트(백엔드)
# NOTE
/* 랜덤 게시물 추가하는 쿼리(새로운 방식) */
INSERT INTO article
(regDate, updateDate, boardId, memberId, title, `body`)
SELECT NOW(), NOW(), FLOOR(RAND() * 2) + 1, FLOOR(RAND() * 2) + 1, CONCAT('제목_', FLOOR(RAND() * 1000) + 1), CONCAT('내용_', FLOOR(RAND() * 1000) + 1)
FROM article;
다이나믹 SQL
-<if test:조건></if>와 같이 특정 조건 등에 의해 쿼리를 동적으로 수정하도록 한 SQL
<CORS>
우리가 앱을 개발하고, 그 앱이 우리 서버와 통신하려면 CORS를 꼭 허용해주어야 한다.
기본적으로 타 사이트에서 우리 서버에 있는 데이터를 ajax로 요청하고
가져 오는 것은 막혀있다.
따라서 이것을 허용해 줄 필요가 있는데 이를 CORS허용? 이라 한다?
// CORS 허용하는 소스코드
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
-----------------------------------------------
<codepen으로 잘 나오는지 실험>
console.clear();
$.get(
'http://localhost:8024/usr/article/list?boardId=1',
function(data) {
for ( let key in data.body.articles ) {
const article = data.body.articles[key];
console.log(article);
const html = `<div>ID : ${article.id}, ${article.title}</div>`;
$('#articles').prepend(html);
}
},
'json'
);
< GET vs POST 요청 방식 차이 비교 >
<1.GET의 요청 방식>
예제)
<form action="http://localhost:8024/usr/home/main" method="GET">
<input type="hidden" name="age" value="11">
<input type="submit" value="전송">
</form>
http://localhost:8024/usr/home/main?age=11
GET HTTP Request(요청서)
--- Header ---
주소 : http://localhost:8024/usr/home/main
쿼리 파라미터 : age=11
---Body ---
없음
**부가정보들이 Header에 붙는다.**
---------------------------
<2.POST의 요청 방식>
예제)
<form action="http://localhost:8024/usr/home/main" method="POST">
<input type="hidden" name="age" value="11">
<input type="submit" value="전송">
</form>
http://localhost:8024/usr/home/main?age=11
POST HTTP Request(요청서)
--- Header ---
주소 : http://localhost:8024/usr/home/main
쿼리 파라미터 : 없음
---Body ---
age=11
**부가정보들이 Body붙는다.**
<history.back()과 location.replace()의 차이점>
- history.back() : 바로 이전의 url로 이동, 이전 기록 유지
- location.replace() : 지정한 url로 이동, 이전 기록 삭제
# 주요 소스코드
<AuthKey 개념 도입>
@Component("beforeActionInterceptor") // 컴포넌트 이름 설정
public class BeforeActionInterceptor implements HandlerInterceptor {
@Autowired
private MemberService memberService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//HttpSession session = request.getSession();
int loginedMemberId = 0;
Member loginedMember = null;
String authKey = request.getParameter("authKey");
//파라미터로 authKey가 들어왔으면
if (authKey != null && authKey.length() > 0) {
//authKey정보를 통해 해당 회원 검색하기
loginedMember = memberService.getMemberByAuthKey(authKey);
//authKey가 일치하는 회원이 없다면
if (loginedMember == null) {
//인증되지 않은 회원
request.setAttribute("authKeyStatus", "invalid");
} else {
//authKey가 일치한다면 인증된 회원
request.setAttribute("authKeyStatus", "valid");
//인증된 회원의 id를 저장(=세션 만료와 상관없이 저장되는 정보)
loginedMemberId = loginedMember.getId();
}
}
//파라미터로 authKey가 들어오지 않았다면
else {
//session 가져오기
HttpSession session = request.getSession();
request.setAttribute("authKeyStatus", "none");
//session에 로그인 정보 저장(=세션이 만료되면 초기화되는 정보)
if (session.getAttribute("loginedMemberId") != null) {
loginedMemberId = (int) session.getAttribute("loginedMemberId");
loginedMember = memberService.getMember(loginedMemberId);
}
}
// 로그인 여부에 관련된 정보를 request에 담는다.
boolean isLogined = false;
boolean isAdmin = false;
//int loginedMemberId = 0;
//Member loginedMember = null;
if (loginedMember != null) {
//loginedMemberId = (int) session.getAttribute("loginedMemberId");
isLogined = true;
//loginedMember = memberService.getMember(loginedMemberId);
isAdmin = memberService.isAdmin(loginedMemberId);
}
request.setAttribute("loginedMemberId", loginedMemberId);
request.setAttribute("isLogined", isLogined);
request.setAttribute("isAdmin", isAdmin);
request.setAttribute("loginedMember", loginedMember);
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
<Admin 개념 도입>
@Controller
public class AdmMemberController {
@Autowired
private MemberService memberService;
@RequestMapping("/adm/member/login")
//@ResponseBody: @ResponseBody를 안하면 /WEB-INF/jsp/adm/member/login.jsp를 찾는다.
public String doLogin() {
return "adm/member/login";
}
@RequestMapping("/adm/member/doLogin")
@ResponseBody
public String doLogin(String loginId, String loginPw, HttpSession session) {
//HttpSession session
//servlet에서와는 달리 스프링에선 session을 바로 요청해서 가져올 수 있다.
// ex) servlet에서는 requst를 통해 session을 요청하고 다시 HttpSession로 session 값을 가져왔었다.
if (loginId == null) {
//return new ResultData("F-1", "loginId를 입력해주세요.");
return Util.msgAndBack("loginId를 입력해주세요.");
}
Member existingMember = memberService.getMemberByLoginId(loginId);
if (existingMember == null) {
//return new ResultData("F-2", "존재하지 않는 로그인아이디 입니다.", "loginId", loginId);
return Util.msgAndBack("존재하지 않는 로그인아이디 입니다.");
}
if (loginPw == null) {
//return new ResultData("F-1", "loginPw를 입력해주세요.");
return Util.msgAndBack("loginPw를 입력해주세요.");
}
if (existingMember.getLoginPw().equals(loginPw) == false) {
//return new ResultData("F-3", "비밀번호가 일치하지 않습니다.");\
return Util.msgAndBack("비밀번호가 일치하지 않습니다.");
}
if ( memberService.isAdmin(existingMember) == false ) {
//return new ResultData("F-4", "관리자만 접근할 수 있는 페이지 입니다.");
return Util.msgAndBack("관리자만 접근할 수 있는 페이지 입니다.");
}
//세션에 로그인 회원 id 등록
session.setAttribute("loginedMemberId", existingMember.getId());
String msg = String.format("%s님 환영합니다.", existingMember.getNickname());
//return new ResultData("S-1", String.format("%s님 환영합니다.", existingMember.getNickname()));
return Util.msgAndReplace(msg, "../home/main");
}
@RequestMapping("/adm/member/doModify")
@ResponseBody
public ResultData doModify(@RequestParam Map<String, Object> param, HttpServletRequest req) {
if (param.isEmpty()) {
return new ResultData("F-2", "수정할 회원정보를 입력해주세요.");
}
int loginedMemberId = (int) req.getAttribute("loginedMemberId");
param.put("id", loginedMemberId);
return memberService.modifyMember(param);
}
}
<login.jsp>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="../part/head.jspf"%>
<script>
const LoginForm__checkAndSubmitDone = false;
function LoginForm__checkAndSubmit(form) {
if (LoginForm__checkAndSubmitDone) {
return;
}
form.loginId.value = form.loginId.value.trim();
if (form.loginId.value.length == 0) {
alert('로그인아이디를 입력해주세요.');
form.loginId.focus();
return;
}
if (form.loginPw.value.length == 0) {
alert('로그인비번을 입력해주세요.');
form.loginPw.focus();
return;
}
form.submit();
LoginForm__checkAndSubmitDone = true;
}
</script>
<section class="section-login">
<div
class="container mx-auto min-h-screen flex items-center justify-center">
<div class="w-full">
<div class="logo-bar flex justify-center mt-3">
<a href="#" class="logo"> <span><i
class="fas fa-people-arrows"></i></span> <span>UNTACT</span>
</a>
</div>
<form class="bg-white shadow-md rounded px-8 pt-6 pb-8 mt-4"
action="doLogin" method="POST"
onsubmit="LoginForm__checkAndSubmit(this); return false;">
<div class="flex flex-col mb-4 md:flex-row">
<div class="p-1 md:w-36 md:flex md:items-center">
<span>로그인아이디</span>
</div>
<div class="p-1 md:flex-grow">
<input
class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker"
autofocus="autofocus" type="text" placeholder="로그인 아이디를 입력해주세요."
name="loginId" maxlength="20" />
</div>
</div>
<div class="flex flex-col mb-4 md:flex-row">
<div class="p-1 md:w-36 md:flex md:items-center">
<span>로그인비번</span>
</div>
<div class="p-1 md:flex-grow">
<input
class="shadow appearance-none border border-red rounded w-full py-2 px-3 text-grey-darker"
autofocus="autofocus" type="password"
placeholder="로그인 비밀번호를 입력해주세요." name="loginPw" maxlength="20" />
</div>
</div>
<div class="flex flex-col mb-4 md:flex-row">
<div class="p-1 md:w-36 md:flex md:items-center">
<span>로그인</span>
</div>
<div class="p-1">
<input
class="bg-blue-500 hover:bg-blue-dark text-white font-bold py-2 px-4 rounded"
type="submit" value="로그인" />
</div>
</div>
</form>
</div>
</div>
</section>
<%@ include file="../part/foot.jspf"%>
<history.back(), location.replace() 도입>
/* Util.java */
public static String msgAndBack(String msg) {
StringBuilder sb = new StringBuilder();
sb.append("<script>");
sb.append("alert('" + msg + "');");
sb.append("history.back();");
sb.append("</script>");
return sb.toString();
}
public static String msgAndReplace(String msg, String url) {
StringBuilder sb = new StringBuilder();
sb.append("<script>");
sb.append("alert('" + msg + "');");
sb.append("location.replace('" + url + "');");
sb.append("</script>");
return sb.toString();
}
'JAVA > Spring & Vue APP 프로젝트(백엔드)' 카테고리의 다른 글
21.03.04 Untact프로젝트(파일업로드 ajax방식으로 처리, 파일 반복문 처리, 파일 저장까지) (0) | 2021.03.04 |
---|---|
21.03.02 Untact프로젝트(관리자 메인화면 구현 ~ 첨부파일 업로드 및 리스팅시 섬네일 노출까지) (0) | 2021.03.02 |
21.02.25~27 Untact프로젝트(회원가입~인터셉터 도입까지) (0) | 2021.02.27 |
21.02.24 Untact프로젝트(게시물 삭제, 수정, 현재날짜 적용 등) (0) | 2021.02.24 |
21.02.23 Untact프로젝트(개발환경 셋팅부터 게시물 추가까지 구현) (0) | 2021.02.23 |