본문 바로가기
개발 공부 Today I Learned

[국비 63일차 TIL] spring 조회수, 좋아요 버튼, myinfo, 이메일 인증

by 개발자신입 2024. 2. 22.
반응형

20240222 

조회수 올리기
좋아요 버튼
myinfo
이메일 인증번호 보내기


BoardService.java

	public BoardDTO detail(int no) { 
		// 2024-02-22 psd 요구사항 확인
		// 조회수 올리기 (로그인 했으면 조회수 증가)
		if(util.getSession().getAttribute("mid") != null) {
			// DTO 만들기 : 아이디, 비번
			BoardDTO dto = new BoardDTO();
			dto.setBoard_no(no);
			dto.setMid((String) util.getSession().getAttribute("mid")); // if문으로 다시 물어보기
                   
		}
		// 컨트롤러에는 int reNo, 서비스에는 int no (데이터 타입을 확인해야함)
		return boardDAO.detail(no); 
	}

 

countUP 메소드 생성

-> countUP()을 BoardDAO에 create (그냥 만드는건가...?)

BoardDAO.java

countUP은 return이 없음

	public void countUP(BoardDTO dto) {
		sqlSession.insert("board.countUP", dto);
	}

 

-> countUP()을 board-mapper.xml에 insert문으로

board-mapper.xml

	<insert id="countUP" parameterType="boardDTO">
		INSERT INTO visitcount (board_no, mno) 
		VALUSE (${board_no}, (SELECT mno FROM member WHERE mid=#{mid}))
	</insert>

 

->  BoardService if문boardDAO.countUP(dto); 추가 

BoardService.java

	public BoardDTO detail(int no) { 
		// 2024-02-22 psd 요구사항 확인
		// 조회수 올리기 (로그인 했으면 조회수 증가)
		if(util.getSession().getAttribute("mid") != null) {
			// DTO 만들기 : 아이디, 비번
			BoardDTO dto = new BoardDTO();
			dto.setBoard_no(no);
			dto.setMid((String) util.getSession().getAttribute("mid")); // if문으로 읽었는지 다시 물어보기
			boardDAO.countUP(dto); // 다이나믹 코드..? 
		}
		return boardDAO.detail(no); 
	}

 

board-mapper.xml

	<!-- 2024-02-22 -->
   <insert id="countUP" parameterType="boardDTO">
      <selectKey keyProperty="board_count" resultType="Integer" order="BEFORE">
         SELECT count(*)
         FROM visitcount
         WHERE board_no=#{board_no} AND mno=(SELECT mno FROM member WHERE mid=#{mid})
      </selectKey>
      <if test="board_count == 0">      
         INSERT INTO visitcount (board_no, mno) 
         VALUES (#{board_no}, (SELECT mno FROM member WHERE mid=#{mid}))
      </if>
      <if test="board_count != 0">      
         SELECT count(*) FROM dual
      </if>
   </insert>
</mapper>

 

BoardDTO.java

board_write, mid 추가

import lombok.Data;

@Data
public class BoardDTO {
	private int board_no, board_count, comment;
	private String board_title, mname, board_write, board_date, board_content, board_ip, mid;
}

좋아요 버튼 만들기


detail.jsp

ip, date, like 앞에 아이콘 이미지 넣어주기.

<div class="text-end">
	<div>
    	<img alt="ip" src="./assets/img/ip-address.png"> ${c.cip } | 
        <img alt="date" src="./assets/img/clocky.png"> ${c.cdate } | 
	<img alt="like" src="./assets/img/likey.png" onclick="like(${c.no })"> ${c.clike }
    </div>
</div>

 

like() function

클릭하면 alert 팝업 뜨도록 Swal.fire();

function like(cno){
	Swal.fire("좋아요", "하트하트", "success");
	setTimeout(function(){
		location.href="./likeUp?no=${detail.board_no}&cno="+cno;
	}, 2000);
}

 

Util.java

	// 2024-02-22  숫자인지 검사하는 메소드
	public boolean intCheck(String str) {
	      try {
	          Integer.parseInt(str);
	          return true;
	       } catch (Exception e) {
	          return false;
	       }
	    }

	public int str2Int2(String str) {
		return Integer.parseInt(str.replaceAll("[^0-9]", ""));
	  }

BoardController.java

		// 2024-02-22 요구사항 확인 psd
		// return값이 오면 다시 내 글로 돌아가기
        
		@GetMapping("/likeUp")
		public String likeUp(@RequestParam("no") String no, @RequestParam("cno") String cno) { // CommentDTO에 있음: 글 no, 댓글 cno
			System.out.println(no);
			System.out.println(cno);
			if(util.intCheck(no) && util.intCheck(cno)) {
				CommentDTO dto = new CommentDTO();
				dto.setBoard_no(util.str2Int(no));
				dto.setNo(util.str2Int(cno));
				
				boardService.likeUp(dto);
							
				return "redirect:/detail?no="+dto.getBoard_no();
			} else {
				return "redirect:/error";
			}
		}

 

likeUp() 메소드 생성

-> likeUp() 만들기  : BoardService, BoardDAO

 

BoardService.java

	public int likeUp(CommentDTO dto) {
		return boardDAO.liekUp(dto);
	}

BoardDAO.java

	public int liekUp(CommentDTO dto) {
		return sqlSession.update("board.likeUp", dto);
	}

board-mapper.xml

   <update id="likeUp" parameterType="commentDTO">
		UPDATE comment SET clike = clike + 1 WHERE cno=#{no}
   </update>

 


마이페이지, 이메일, 인증번호


menu.jsp

@${sessionScope.mid} : /myInfo@로그인아이디

 

 

@PathVariable 이란?

REST API에서 URI에 변수가 들어가는걸 실무에서 많이 볼 수 있다.

예를 들면, 아래 URI에서 밑줄 친 부분이 @PathVariable로 처리해줄 수 있는 부분이다.

localhost:8080/api/user/1234

bugs.co.kr/album/4062464

 

<li class="nav-item"><a class="nav-link" href="./myInfo@${sessionScope.mid }">${sessionScope.mname } 님</a></li>

 

pom.xml

이메일 보낼 수 있는 코드 추가해서 다운받기

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-email -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-email</artifactId>
    <version>1.5</version>
</dependency>

 

LoginController.java

	// http://172.30.1.150/myInfo@test6
	@GetMapping("/myInfo@{id}") // @뒤 id를 경로 변수로 씀
	public String myInfo(@PathVariable("id") String id) {
		// System.out.println("id : "+id); 
		return "myinfo";
	}

 

-> myinfo.jsp 생성

myinfo.jsp

인증번호 이메일로 발송하기와 버튼 form 만들기

	<!-- LOGIN -->
	<section class="page-section" id="my-info">
		<div class="d-flex justify-content-center">
			<div class="text-center">
				<div>
					등록한 email로 인증번호가 발송되었습니다.
					email을 확인 후 인증번호를 입력하세요.
					<form action="">
						<input type="number" name="number">
						<button>인증하기</button>
					</form>
				</div>			
			</div>
		</div>
	</section>

 

LoginController.java

simpleEmail.setFrom(emailAddr, name); 이 부분에서 throws EmailException 설정해야함.

	// http://172.30.1.150/myInfo@test6
	@GetMapping("/myInfo@{id}") // @뒤 id를 경로 변수로 씀
	public String myInfo(@PathVariable("id") String id) throws EmailException {
//		System.out.println("id : "+id); 
		
		// 메일 보내기..
		String emailAddr = "아이디@outlook.kr"; // 이메일 주소
		String name = "보내는 사람 이름"; 
		String passwd = "비번";
		String hostName = "smtp-mail.outlook.com";
		int port = 587;
		
		SimpleEmail simpleEmail = new SimpleEmail();  // 전송할 메일
		simpleEmail.setCharset("UTF-8");
		simpleEmail.setDebug(true);
		simpleEmail.setHostName(hostName); // 보내는 서버 설정 = 고정
		simpleEmail.setAuthentication(emailAddr, passwd); // 보내는 사람 인증 = 고정
		simpleEmail.setSmtpPort(port); // 사용할 port번호
		simpleEmail.setStartTLSEnabled(true); // 인증방법 = 고정
		simpleEmail.setFrom(emailAddr, name); // 보내는 사람 email, 이름
		simpleEmail.addTo("받는사람@메일.com"); // 받는사람
		simpleEmail.setSubject("15번 페이지 인증번호입니다."); // 제목
		simpleEmail.setMsg("인증번호는 [2077] 입니다."); // 내용 text
		simpleEmail.send();
		
		return "myinfo";
	}
}

Util.java

메일 보내는 서식 Util.java로 옮기기

	// 메일보내기 
	public void sendEmail(String email, String key) throws EmailException {
		
		String emailAddr = "------@outlook.kr"; // 이메일 주소
		String name = "보내는 사람 이름"; 
		String passwd = "";
		String hostName = "smtp-mail.outlook.com";
		int port = 587;
		
		SimpleEmail simpleEmail = new SimpleEmail();  // 전송할 메인
		simpleEmail.setCharset("UTF-8");
		simpleEmail.setDebug(true);
		simpleEmail.setHostName(hostName); // 보내는 서버 설정 = 고정
		simpleEmail.setAuthentication(emailAddr, passwd); // 보내는 사람 인증 = 고정
		simpleEmail.setSmtpPort(port); // 사용할 port번호
		simpleEmail.setStartTLSEnabled(true); // 인증방법 = 고정
		simpleEmail.setFrom(emailAddr, name); // 보내는 사람 email, 이름
		simpleEmail.addTo(email); // 받는사람
		simpleEmail.setSubject("15번 사이트 인증번호입니다!"); // 제목
		simpleEmail.setMsg("인증번호는 [" + key + "] 입니다."); // 내용 text
		simpleEmail.send();
	}

 

 

-> LoginController에 적었던 메일 보내기 서식을 util에 저장한 후 불러서 사용

 

util.sendEmail("가입한 사람의 email", "인증번호");

	@GetMapping("/myInfo@{id}") // @뒤 id를 경로 변수로 씀
	public String myInfo(@PathVariable("id") String id) throws EmailException {
		
		util.sendEmail("가입한 사람의 email", "인증번호");
		return "myinfo";
	}
}

 

-> Util (내꺼) import 하기

	@Autowired
	private Util util;

 

LoginController.java

메일 보내기 코드를 util로 옮긴 후의 코드임.

util.sendEmail(email, key); 이거만 불러오면 되므로 간단해짐..

	@Autowired
	private Util util;


	// http://172.30.1.150/myInfo@test6
	@GetMapping("/myInfo@{id}") // @뒤 id를 경로 변수로 씀
	public String myInfo(@PathVariable("id") String id) throws EmailException {

		String email = loginService.getEmail((String) util.getSession().getAttribute("mid"));
		
		util.sendEmail("이메일주소", "인증번호");
		return "myinfo";
	}

 

getEmail 메소드 생성

-> getEmail을 LoginService, LoginDAO에 만들어주기

 

LoginService.java

- 서비스에 만들어 둔 getEmail은 나중에 Rest로 옮김.

	public String getEmail(String email) {
		return loginDAO.getEmail(email);
	}

LoginDAO.java

public String getEmail(String id){
	return sqlSession.selectOne("login.getEmail", id);
}

login-mapper.xml

<select id="getEmail" parameterType="String" resultType="String">
	SELECT memail FROM member WHERE mid=#{id}
</select>

 

LoginController.java

	@GetMapping("/myInfo@{id}") // @뒤 id를 경로 변수로 씀
	public String myInfo(@PathVariable("id") String id) throws EmailException {
		
		String email = loginService.getEmail((String) util.getSession().getAttribute("mid"));
		String key = util.createKey();
		util.sendEmail(email, "인증번호");
		return "myinfo";
	}
}

createKey 생성

-> createKey을 Util에 생성 : 인증번호를 랜덤으로 보내기 위해.

	public String createKey() {
		Random r = new Random();
		r.setSeed(System.currentTimeMillis());
		String key = r.nextInt(10) + "" + r.nextInt(10) + r.nextInt(10) + r.nextInt(10);
		return key;
	}

 

-> createKey 생성 후에 컨트롤러에서 변수명 변경하기

LoginController.java

util.sendEmail 변수 변경 : util.sendEmail(email, key);

 

-> DB에 key 생성 (mkey)

`mkey` VARCHAR(10) NULL DEFAULT NULL COLLATE

 

LoginController.java

	@GetMapping("/myInfo@{id}") // @뒤 id를 경로 변수로 씀
	public String myInfo(@PathVariable("id") String id) throws EmailException {
//		System.out.println("id : "+id); 
		
		// 로그인 여부 확인하기
		if(util.getSession().getAttribute("mid") != null) {
			
			// 인증 요청하기 = Ajax용으로 빼두기
			// loginService.myInfo();
			
			return "myinfo";
		} else {
			return "redirect:/login?error=error";
		}
	}
}

 

myinfo.jsp

	<!-- LOGIN -->
	<section class="page-section" id="my-info">
		<div class="d-flex justify-content-center">
			<div class="text-center">
			
				<button onclick="emailAuth()">인증번호 요청하기 😱</button>
				
				<div>
					등록한 email로 인증번호가 발송되었습니다.<p>
					email을 확인 후 인증번호를 입력하세요.
					<form action="">
						<input type="number" name="number">
						<button>인증하기</button>
					</form>
				</div>			
			</div>
		</div>
	</section>

 

 

emailAuth() 메소드 생성

-> 버튼 emailAuth() function 만들어주기 (Ajax사용을 위해 jQuery 스크립트 추가하기)

 

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
	crossorigin="anonymous" referrerpolicy="no-referrer">
</script>
<script type="text/javascript">
function emailAuth(){
	$.ajax({
		url : './emailAuth',
		type : 'post',
		dataType : 'text',
		success : function(result){
			if(result == 1){
				Swal.fire("전송했습니다.", "결과 : " + result, "success");
			} else {
				Swal.fire("긴급상황", "문제가 발생했습니다.", "Info");
			}
		},
		error : function(request, status, error){
				Swal.fire("훠우~", "문제가 발생했네요~" + error, "Error");
		}
	});
}

</script>

-> Ajax 용도 코드(비동기 통신 코드)는 RestFullController.java에 입력해주기.

 

* 여기에서부터 갑자기 Rest로 넘어감. 기존에 썼던 코드도 Rest로 옮긴 것들이 많다. 


RestFullController.java

	@PostMapping("/emailAuth")
	public @ResponseBody int emailAuth() {
		return 1;
	}

 

@Controller 를 @RestController 로 변경하기 => @ResponseBody를 빼고 동작 하게 함.

 

RestService.java

RestFullController에 RestService 생성하기 -> class파일까지 생성

@Autowired
private RestService restService;

 

RestFullController.java

전체코드

@RestController
public class RestFullController {
	
	@Autowired
	private BoardService boardService;
	
	@Autowired
	private RestService restService; // 없어서 생성함

	@Autowired
	private Util util;
	
	@PostMapping("/restDetail")
	public BoardDTO restDetail(@Param("no") int no) { // 결과는 body에 출력해 (view를 안 보여주게)
		BoardDTO detail = boardService.detail(no); // detail에 담겨서 옵니다.
		return detail;
	}
	
	@PostMapping("/emailAuth")
	public int emailAuth() {
		return restService.sendEmail(); // ajax로 버튼 눌렀을 때 여기 옴. -> 서비스에서 기능 만들어주기
	}

}

 

RestService.java

LoginService에서 getEmail 메소드 가져옴.

@Service
public class RestService {

	@Autowired
	private Util util;
	
	public int sendEmail() {
		if(util.getSession().getAttribute("mid") != null) {
			return 1;
		} else {
			return 0;
		}
	}
	// 로그인서비스에서 가져옴
	public String getEmail(String email) {
		return restDAO.getEmail(email); // 사용자 이메일 알아오는 작업?
	}

}

 

-> getEmail을 RestDAO에 생성

RestDAO.java

LoginDAO에서 getEmail 메소드 옮겨옴.

	public String getEmail(String id) {
		return sqlSession.selectOne("login.getEmail", id);
	}

 

-> RestDAO 생성 후, 서비스에 @autowired로 RestDAO 받기

RestService.java

@Service
public class RestService {

	@Autowired
	private Util util;
	
	@Autowired
	private RestDAO restDAO;

MemberDTO.java

새로 생성해주기

@Data
public class MemberDTO {
	private int mno, mgrade, mcount;
	private String mid, mpw, mname, mdate, memail, mkey;
}

RestService.java

	public int sendEmail() {
		if(util.getSession().getAttribute("mid") != null) {
			// 메일 발송 + key 데이터베이스 저장
			String email = getEmail((String) util.getSession().getAttribute("mid"));
			String key = util.createKey();
			
			MemberDTO dto = new MemberDTO();
			dto.setMemail(email);
			dto.setMkey(key);
			dto.setMid((String) util.getSession().getAttribute("mid"));
			restDAO.setkey(dto); // db에 키 저장
			
			return 1;
		} else {
			return 0;
		}
	}

 

-> setkey를 RestDAO에 생성

	public int setKey(MemberDTO dto) {
		return sqlSession.update("rest.setKey", dto);
	}

mybatis-config.xml

<typeAlias type="org.-----.dto.MemberDTO" alias="memberDTO"/>

 

rest-mapper.xml

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="rest">

	<!-- 2024-02-22 -->
	<select id="getEmail" parameterType="String" resultType="String">
		SELECT memail FROM member WHERE mid=#{id} 
	</select>
	
	<update id="setKey" parameterType="memberDTO">
		UPDATE member SET mkey=#{mkey} AND mid=#{mid} AND memail=#{memail}
	</update>
    
</mapper>

 

반응형

댓글