Controller
package kr.or.ddit.controller.noticeboard.web;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import kr.or.ddit.ServiceResult;
import kr.or.ddit.controller.noticeboard.service.INoticeService;
import kr.or.ddit.vo.DDITMemberVO;
@Controller
@RequestMapping("/notice")
public class NoticeProfileController {
@Inject
private INoticeService noticeService;
**// 프로필로 이동 요청**
@RequestMapping(value="/profile.do", method = RequestMethod.GET)
public String noticeProfile(
HttpServletRequest req, RedirectAttributes ra, Model model
) {
String goPage = "";
HttpSession session = req.getSession();
DDITMemberVO sessionMember = (DDITMemberVO)session.getAttribute("SessionInfo");
if(sessionMember == null) {
ra.addFlashAttribute("message", "로그인 후 이용가능합니다");
return "redirect:/notice/login.do";
}
DDITMemberVO member = noticeService.selectMember(sessionMember);
if(member != null) {
model.addAttribute("member", member);
goPage = "notice/profile";
}else {
ra.addFlashAttribute("message", "로그인 후 이용가능합니다");
goPage = "redirect:/notice/login.do";
}
return goPage;
}
**// 프로필 수정하기 처리**
@RequestMapping(value="/profileUpdate.do", method = RequestMethod.POST)
public String noticeProfileUpload(
HttpServletRequest req,
DDITMemberVO memberVO, RedirectAttributes ra, Model model
) {
String goPage = "";
ServiceResult result = noticeService.profileUpdate(req, memberVO);
if(result.equals(ServiceResult.OK)) {
ra.addFlashAttribute("message", "회원정보 수정이 완료되었습니다");
goPage = "redirect:/notice/profile.do";
}else {
model.addAttribute("member", memberVO);
goPage = "notice/profile";
}
return goPage;
}
}
Service
package kr.or.ddit.controller.noticeboard.service;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.input.TaggedInputStream;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import kr.or.ddit.ServiceResult;
import kr.or.ddit.controller.noticeboard.web.TelegramSendController;
import kr.or.ddit.mapper.LoginMapper;
import kr.or.ddit.mapper.NoticeMapper;
import kr.or.ddit.mapper.ProfileMapper;
import kr.or.ddit.vo.DDITMemberVO;
import kr.or.ddit.vo.NoticeFileVO;
import kr.or.ddit.vo.NoticeVO;
import kr.or.ddit.vo.PaginationInfoVO;
@Service
public class NoticeServiceImpl implements INoticeService {
@Inject
private ProfileMapper profileMapper;
@Override
public DDITMemberVO selectMember(DDITMemberVO sessionMember) {
return profileMapper.selectMember(sessionMember);
}
@Override
public ServiceResult profileUpdate(HttpServletRequest req, DDITMemberVO memberVO) {
ServiceResult result = null;
// 사용자가 수정한 프로필 이미지 정보에 따라서 프로필 이미지 정보 값을 설정 후 memberVO에 셋팅해서 전달한다.
String uploadPath = req.getServletContext().getRealPath("/resources/profile");
File file = new File(uploadPath);
if(!file.exists()) {
file.mkdirs();
}
String proFileImg = "";
MultipartFile proFileImgFile = memberVO.getImgFile();
if(proFileImgFile.getOriginalFilename() != null && !proFileImgFile.getOriginalFilename().equals("")) {
String fileName = UUID.randomUUID().toString();
fileName += "_" + proFileImgFile.getOriginalFilename();
uploadPath += "/" + fileName;
try {
proFileImgFile.transferTo(new File(uploadPath));
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
} // 프로필 이미지 파일 복사
proFileImg = "/resources/profile/" + fileName;
}
// 선택한 프로필 이미지가 존재하지 않으면 "" 공백이 넘어가고
// 프로필 이미지가 존재하면 업로드 경로와 파일명으로 구성된 경로가 넘어간다.
memberVO.setMemProfileImg(proFileImg);
int status = profileMapper.profileUpdate(memberVO);
if(status > 0) {
result = ServiceResult.OK;
}else {
result = ServiceResult.FAILED;
}
return result;
}
}
Mapper
package kr.or.ddit.mapper;
import kr.or.ddit.vo.DDITMemberVO;
public interface ProfileMapper {
public DDITMemberVO selectMember(DDITMemberVO sessionMember);
public int profileUpdate(DDITMemberVO memberVO);
}
NoticeMapper (SQL)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<mapper namespace="kr.or.ddit.mapper.ProfileMapper">
**<!-- 프로필 정보 가져오기 쿼리 -->**
<select id="selectMember" parameterType="dditmemberVO" resultType="dditmemberVO">
select
mem_no, mem_id, mem_pw, mem_name,
mem_gender, mem_email, mem_phone,
mem_postcode, mem_address1, mem_address2,
mem_agree, mem_profileimg, mem_regdate
from dditmember
where mem_id = #{memId}
</select>
**<!-- 프로필 업데이트하는 쿼리 -->**
<update id="profileUpdate" parameterType="dditmemberVO">
update dditmember
set
mem_pw = #{memPw},
mem_name = #{memName},
mem_gender = #{memGender},
mem_email = #{memEmail},
mem_phone = #{memPhone},
mem_postcode = #{memPostCode},
mem_address1 = #{memAddress1},
mem_address2 = #{memAddress2}
<if test="memProfileImg != null and memProfileImg != ''">
, mem_profileimg = #{memProfileImg}
</if>
where mem_no = #{memNo}
</update>
</mapper>
JSP 페이지
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="<http://tiles.apache.org/tags-tiles>" prefix="tiles" %>
<%@ taglib uri="<http://java.sun.com/jsp/jstl/core>" prefix="c" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AdminLTE 3 | Simple Tables</title>
<link rel="stylesheet" href="<https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback>">
<link rel="stylesheet" href="${pageContext.request.contextPath }/resources/plugins/fontawesome-free/css/all.min.css">
<link rel="stylesheet" href="${pageContext.request.contextPath }/resources/dist/css/adminlte.min.css">
<script src="${pageContext.request.contextPath }/resources/plugins/jquery/jquery.min.js"></script>
<script src="${pageContext.request.contextPath }/resources/ckeditor/ckeditor.js"></script>
</head>
<c:if test="${not empty message }">
<script type="text/javascript">
alert("${message}");
<c:remove var="message" scope="request"/>
<c:remove var="message" scope="session"/>
</script>
</c:if>
<body class="hold-transition sidebar-mini">
<div class="wrapper">
<!-- header 영역 -->
<tiles:insertAttribute name="header"/>
<div class="content-wrapper">
<!-- content 영역 -->
<tiles:insertAttribute name="content"/>
</div>
<!-- footer 영역 -->
<tiles:insertAttribute name="footer"/>
<aside class="control-sidebar control-sidebar-dark">
</aside>
</div>
<script src="${pageContext.request.contextPath }/resources/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="${pageContext.request.contextPath }/resources/dist/js/adminlte.min.js"></script>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="<http://java.sun.com/jsp/jstl/core>" prefix="c" %>
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>Profile</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active">User Profile</li>
</ol>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<div class="card card-primary card-outline">
<div class="card-body box-profile">
<div class="text-center">
<img class="profile-user-img img-fluid img-circle" src="${member.memProfileImg }" alt="User profile picture">
</div>
<h3 class="profile-username text-center">${member.memName }</h3>
<p class="text-muted text-center">${member.memRegDate }</p>
<br />
<p class="text-muted text-center">작성한 게시물</p>
<ul class="list-group list-group-unbordered mb-3">
<li class="list-group-item">
<b>공지사항</b>
<a class="float-right">356</a>
</li>
<li class="list-group-item">
<b>자유게시판</b>
<a class="float-right">150</a>
</li>
</ul>
</div>
</div>
</div>
<div class="col-md-9">
<div class="card">
<div class="card-header p-2">
<ul class="nav nav-pills">
<li class="nav-item">
<a class="nav-link active" href="#settings" data-toggle="tab">내정보</a>
</li>
</ul>
</div>
<div class="card-body">
<div class="tab-content">
<div class="tab-pane active" id="settings">
<form class="form-horizontal" action="/notice/profileUpdate.do" method="post" id="profileUdtForm" enctype="multipart/form-data">
<input type="hidden" name="memNo" id="memNo" value="${member.memNo }">
<div class="form-group row">
<label for="memProfileImg" class="col-sm-2 col-form-label">프로필이미지</label>
<div class="row">
<a href="${member.memProfileImg }" target="_blank">
<img class="profile-user-img img-fluid img-circle" id="profileImg"
src="${member.memProfileImg }" alt="User profile picture"
style="width: 150px;">
</a>
</div>
</div>
<div class="form-group row">
<label for="memProfileImg" class="col-sm-2 col-form-label"></label>
<div class="col-md-10">
<br/>
<div class="custom-file">
<input type="file" class="custom-file-input" name="imgFile" id="imgFile" multiple="multiple">
<label class="custom-file-label" for="imgFile">프로필 이미지를 선택해주세요</label>
</div>
</div>
</div>
<div class="form-group row">
<label for="memId" class="col-sm-2 col-form-label">아이디</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="memId" name="memId" value="${member.memId }" placeholder="아이디를 입력해주세요." readonly="readonly">
</div>
</div>
<div class="form-group row">
<label for="memPw" class="col-sm-2 col-form-label">비밀번호</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="memPw" name="memPw" value="${member.memPw }" placeholder="아이디를 입력해주세요.">
</div>
</div>
<div class="form-group row">
<label for="memName" class="col-sm-2 col-form-label">이름</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="memName" name="memName" value="${member.memName }" placeholder="비밀번호를 입력해주세요.">
</div>
</div>
<div class="form-group row">
<label for="" class="col-sm-2 col-form-label">성별</label>
<div class="col-sm-10">
<div class="icheck-primary d-inline">
<c:if test="${member.memGender eq 'M' }">checked</c:if>
<input type="radio" id="memGenderM" name="memGender" value="M" <c:if test="${member.memGender eq 'M' }">checked</c:if>>
<label for="memGenderM">남자</label>
</div>
<div class="icheck-primary d-inline">
<input type="radio" id="memGenderF" name="memGender" value="F" <c:if test="${member.memGender eq 'F' }">checked</c:if>>
<label for="memGenderF">여자</label>
</div>
</div>
</div>
<div class="form-group row">
<label for="memEmail" class="col-sm-2 col-form-label">이메일</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="memEmail" name="memEmail" value="${member.memEmail }" placeholder="이메일을 입력해주세요.">
</div>
</div>
<div class="form-group row">
<label for="memPhone" class="col-sm-2 col-form-label">전화번호</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="memPhone" name="memPhone" value="${member.memPhone }" placeholder="전화번호를 입력해주세요.">
</div>
</div>
<div class="input-group mb-3">
<label for="" class="col-sm-2 col-form-label">주소</label>
<div class="col-sm-10">
<div class="input-group mb-3">
<input type="text" class="form-control" id="memPostCode" name="memPostCode" value="${member.memPostCode }" placeholder="우편번호를 입력해주세요">
<span class="input-group-append">
<button type="button" onclick="DaumPostcode()" class="btn btn-secondary btn-flat">우편번호 찾기</button>
</span>
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" id="memAddress1" name="memAddress1" value="${member.memAddress1 }" placeholder="주소를 입력해주세요">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" id="memAddress2" name="memAddress2" value="${member.memAddress2 }" placeholder="상세주소를 입력해주세요">
</div>
</div>
</div>
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button type="submit" class="btn btn-info">수정하기</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 다음 주소 API js 파일 -->
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script>
$(function(){
var imgFile = $("#imgFile");
// 프로필 이미지 선택
imgFile.on("change", function(evnet){
var file = event.target.files[0];
if(isImageFile(file)){
var reader = new FileReader();
reader.onload = function(e){
$("#profileImg").attr("src", e.target.result); // 해당 이미지 파일에 url 을 가져온다,
}
reader.readAsDataURL(file);
}else{ // 이미지 파일을 선택하지 않음
alert("이미지 파일을 선택해주세요");
$(this).val(null);
}
})
})
// 이미지 파일인지 체크 (확장자를 이용해서)
function isImageFile(file){
var ext = file.name.split(".").pop().toLowerCase(); // 파일명에서 확장자를 가져온다.
return ($.inArray(ext, ["jpg", "jpeg", "gif", "png"]) === -1) ? false : true;
}
//본 예제에서는 도로명 주소 표기 방식에 대한 법령에 따라, 내려오는 데이터를 조합하여 올바른 주소를 구성하는 방법을 설명합니다.
function DaumPostcode() {
new daum.Postcode({
oncomplete: function(data) {
// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
// 각 주소의 노출 규칙에 따라 주소를 조합한다.
// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
var addr = ''; // 주소 변수
var extraAddr = ''; // 참고항목 변수
//사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
addr = data.roadAddress;
} else { // 사용자가 지번 주소를 선택했을 경우(J)
addr = data.jibunAddress;
}
// 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
if(data.userSelectedType === 'R'){
// 법정동명이 있을 경우 추가한다. (법정리는 제외)
// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
extraAddr += data.bname;
}
// 건물명이 있고, 공동주택일 경우 추가한다.
if(data.buildingName !== '' && data.apartment === 'Y'){
extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
}
// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
if(extraAddr !== ''){
extraAddr = ' (' + extraAddr + ')';
}
}
// 우편번호와 주소 정보를 해당 필드에 넣는다.
document.getElementById('memPostCode').value = data.zonecode;
document.getElementById("memAddress1").value = addr;
// 커서를 상세주소 필드로 이동한다.
document.getElementById("memAddress2").focus();
}
}).open();
}
</script>
프로필 페이지로 들어가면 나의대한 정보가 잘 출력되는 것을 볼 수 있다.
