Spring 마이 페이지 | [자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기 380 개의 새로운 답변이 업데이트되었습니다.

당신은 주제를 찾고 있습니까 “spring 마이 페이지 – [자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: you.tfvp.org/blog. 바로 아래에서 답을 찾을 수 있습니다. 작성자 Tartaglia_타르탈리아 TV 이(가) 작성한 기사에는 조회수 1,379회 및 좋아요 14개 개의 좋아요가 있습니다.

spring 마이 페이지 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 [자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기 – spring 마이 페이지 주제에 대한 세부정보를 참조하세요

*자바 웹을 다루는 기술 도서 보기 소개
http://bit.ly/2RAEwMR

* 자바 웹을 다루는 기술 저자 카페
https://cafe.naver.com/spring4shoppingmall

spring 마이 페이지 주제에 대한 자세한 내용은 여기를 참조하세요.

[spring/java] 웹사이트 만들기 5 – 회원정보 수정 / 마이페이지 …

먼저 이메일 인증된 아이디를 통해 로그인을 하면 마이페이지로 이동할 수 있는 링크가 생긴다. 링크로 이동하면 session에 설정된 회원의 현재 정보를 …

+ 자세한 내용은 여기를 클릭하십시오

Source: m.blog.naver.com

Date Published: 9/6/2021

View: 3662

[스프링] 마이페이지 구현 – 회원 활동로그와 작성한 게시글,댓글 …

이번엔 마이페이지로 이동해서 , 그곳에서 회원 활동로그와 작성한 게시글,댓글,스크랩 목록을 볼 수 있도록 구현했다.

+ 여기에 자세히 보기

Source: kimfk567.tistory.com

Date Published: 4/22/2021

View: 1837

Spring boot 마이페이지!(1) with AuthenticationPrincipal

이제 마이페이지를 만들건대. 간단하게. 내 정보. 비밀번호변경. 이메일 인증 서비스를 구현해볼 것이다! 컨트롤러에서. controller.java.

+ 여기에 더 보기

Source: cordingmonster.tistory.com

Date Published: 6/19/2021

View: 9223

[Spring Boot/JPA] #3 View와 Controller 제작 : 마이페이지 …

Spring MVC 구현, 로그인한 사용자의 마이페이지 구현, Spring Security를 통해 현재 사용자 정보 얻기, Paging 구현.

+ 여기에 보기

Source: prod.velog.io

Date Published: 10/8/2022

View: 6965

JAVA / SPRING 프로젝트 삼삼하개(3) 마이페이지(개인/업체 …

팀프로젝트가 끝나고 되돌아보는 시간 (3) 마이페이지(개인/업체) 내 작성글, 작성댓글 조회 구현 내 작성글, 작성댓글을 불러오는 페이지를 작업 …

+ 여기에 보기

Source: recoderr.tistory.com

Date Published: 11/29/2022

View: 3167

[스프링SPRING] 회원정보조회, 회원정보수정, 회원정보삭제

info.jsp 뷰 페이지 생성 …

마이페이지

+ 여기에 표시

Source: sowon-dev.github.io

Date Published: 4/3/2022

View: 91

[Final Project] 마이페이지 기능 구현 정리 – 히앤님의 세상

마이페이지 /쉐프페이지 CRUD. 정보count – 숫자 세기 완료 / 단, 별점 없으면 에러남. 회원정보출력 – 세션scope로 잘 가져옴 / 업데이트가 늦음 …

+ 여기에 표시

Source: heannim-world.tistory.com

Date Published: 11/27/2022

View: 1163

[Spring] 쇼핑몰 프로젝트(4)_마이페이지(개인정보, 정보 수정 …

[Spring] 쇼핑몰 프로젝트(4)_마이페이지(개인정보, 정보 수정), 회원 탈퇴. youngna 2020. 9. 19. 21:16. <개인 정보 확인>. 개인정보는 Controller까지만 작성해된다 …

+ 여기에 자세히 보기

Source: na0-coding.tistory.com

Date Published: 6/1/2022

View: 963

Day95 – [Jquery]마이페이지 구현(테이블 JOIN) – 일상

마이페이지를 구현할 때, 마이페이지 에는 내가 쓴 글을 같이 확인 하기 … 개발 환경은 Spring , oracle, Lombok, myBatis, Tiles View Template 를 …

+ 여기에 더 보기

Source: rsorry.tistory.com

Date Published: 6/16/2021

View: 7881

주제와 관련된 이미지 spring 마이 페이지

주제와 관련된 더 많은 사진을 참조하십시오 [자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

[자바 웹을 다루는 기술]  31.11 마이 페이지 구현하기
[자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기

주제에 대한 기사 평가 spring 마이 페이지

  • Author: Tartaglia_타르탈리아 TV
  • Views: 조회수 1,379회
  • Likes: 좋아요 14개
  • Date Published: 2019. 6. 11.
  • Video Url link: https://www.youtube.com/watch?v=IkyhROSMwQA

[spring/java] 웹사이트 만들기 5 – 회원정보 수정 / 마이페이지(my page)

spring/java를 이용하여 마이페이지를 구현하려고 하는 내용은 다음과 같다. 먼저 이메일 인증된 아이디를 통해 로그인을 하면 마이페이지로 이동할 수 있는 링크가 생긴다. 링크로 이동하면 session에 설정된 회원의 현재 정보를 보여준다. 정보를 수정하거나 비밀번호를 변경 후 버튼을 클릭하면 데이터베이스의 회원 정보를 수정한 후 session을 재설정하는 방식을 이용하도록 하겠다.

그러면 먼저 index 페이지에 로그인이 되었을 때 마이페이지 링크를 추가한다.

[스프링] 마이페이지 구현 – 회원 활동로그와 작성한 게시글,댓글,스크랩 목록

728×90

이번엔 마이페이지로 이동해서 , 그곳에서 회원 활동로그와 작성한 게시글,댓글,스크랩 목록을 볼 수 있도록 구현했다.

OKKY 사이트처럼 다른사람도 그 정보를 닉네임을 클릭하는 등의 행위를 통해서 볼 수 있도록 만들었다.

다른 커뮤니티처럼 내 정보는 따로 검색을 하거나 등을 제외하면 나만 볼 수 있도록 할까… 생각을 했지만

IT커뮤니티이니 만큼 (?) 이상한 짓을 못하도록 그냥 모든 정보를 회원들이 서로 볼 수 있도록 만들었다.

실제로 나도 OKKY 커뮤니티를 사용하면서 다른 커뮤니티들과 다른 그런 정보공개?가 처음에는 낯설었지만

꽤나 괜찮다는 생각을 받기도 했다.

단, 너무 행동에 조심하게? 되는 부분에 대해 게시글과 댓글을 삭제하면 활동로그가 아예 삭제되도록 구현해서

해당 부분을 보완했다.

일단 해당 기능 또한 검색을 해도 따로 힌트나 도움이 될 만한 정보가 나오진 않았다.

그래서 내 생각대로 만들었는데 , 부족한 실력이다보니 꽤나 하드코딩이 된 것 같아서 마음이 아프다,,,

이전 이전 01 슬라이드쇼 2장

먼저 okky의 마이페이지 디자인을 따라서 구현해봤고 (허접함 주의)

해당페이지에서 최근활동, 게시물 , 스크랩을 클릭했을때

주소창에서 회원의 PR은 유지되면서 뒤의 주소창에 변화가 일어나는 부분을 보고,

get 방식으로 회원PR받으며, PR기준으로 select문을 구별해서 구현하면 되겠구나하는 생각이 들었다.

구현 로직을 먼저 설명하자면

회원의 활동로그를 저장 할 테이블을 생성

글작성,좋아요,싫어요,DEV,댓글작성,채택 등의 행위를 할 때 insert 되도록 코드 추가

반대로 글삭제,좋아요취소,싫어요취소 등의 행위를 할 때에는 따로 기록을 남기지 않기 위해 delete 되도록 추가

insert시에는 활동로그 테이블에 카테고리별로 구분되어 어떤 활동을 했는지 기록됨

활동로그 테이블과 게시판 테이블 , 댓글테이블을 join을 해서 List로 출력

뷰에서 List의 카테고리 컬럼을 기준으로 if문을 통해 출력 될 문장을 나눠줌

내 게시글, 내 댓글 , 내 스크랩을 출력하기 위해 select문을 위와 동일하게 List로 가져와서 출력

활동로그 , 게시글 , 댓글 , 스크랩은 get 방식을 사용해서 주소창에서 “/주소?select=” 로 나눠주고

어떤 회원의 프로필을 볼 건지는 “/주소?select=# &memberId=#”으로 나눠준다.

결과

‘1234’회원의 활동기록이다.

아직 추가적으로 디자인을 좀 더 깔끔하게 가꾸고 , 페이징 기능을 추가해야하지만 1차적으로 필요한 기능은 구현됐다.

주소창 부분에 select=log ( 활동기록 ) , memberId=1234 (회원PR) 로 나누어서 출력한다.

활동기록 테이블 생성

create table MP_LOG ( LOGNO number not null, MEMBER_ID varchar2(50) not null, bno number, rno number, questionid varchar2(50), categori number , logdate date default sysdate, constraint log_pk PRIMARY key (LOGNO), constraint log_fk FOREIGN key (MEMBER_ID) references MP_MEMBER(MEMBER_ID) on delete cascade );

LogNO

Member_ID ( 회원PR )

Bno ( 게시글PR )

Rno ( 댓글PR )

Questionid (채택받은 사람의 id인데 설계시에는 추가했지만 구현하고보니 rno를 기준으로 join하면 값이 나오기 때문에 생략해도 무방함)

Categori ( 어떤 활동인지 나누는 기준 )

logDate ( 정렬용 활동기록 시간)

회원 ID가 삭제되면 같이 정보가 삭제되도록 delete cascade를 해줬다.

Mapper.xml

insert into MP_LOG (LOGNO , MEMBER_ID,BNO,RNO,QUESTIONID,CATEGORI) values ((SELECT NVL(MAX(LOGNO), 0) + 1 FROM MP_LOG), #{memberId}, #{bno} , #{rno, jdbcType=INTEGER} , #{questionId, jdbcType=VARCHAR},#{categori})

먼저 insert이다

게시글 작성등의 활동에는 rno가 들어가지 않기 때문에 jdbcType을 사용해서 null값을 허용해주자.

(mybatis 사용시 insert에 null값이 들어가면 nullpoint에러 발생)

delete from MP_LOG where MEMBER_ID = #{memberId} and BNO = #{bno} and CATEGORI = #{categori} delete from MP_LOG where MEMBER_ID = #{memberId} and RNO = #{rno} and CATEGORI = #{categori}

게시글 삭제 , 게시글 추천 취소 , 댓글 삭제 , 댓글 추천 취소 등에 들어갈 delete 문이다.

게시글PR , 댓글PR기준이기 때문에 두개의 delete문을 만들어줬다.

로그 테이블에 회원PR을 기준 , BNO에 해당하는 게시글의 활동(Categori로 구분)을 삭제한다.

글 작성은 bno로 구분되고 ,

글 추천 등의 행위는 회원당 1번으로 제한했기 때문에 카테고리를 기준으로 삭제해도 문제가 없다.

Mapper를 작성했으니 VO를 작성해서 편하게 파라미터를 받아보자.

public class LogVO { private String memberId; private int bno; private int rno; private String questionId; private int categori; private Date logdate; private BoardVO boardVO; private ReplyVO replyVO; //getter&setter 생성 }

jojn 쿼리때에 사용 할 게시판VO와 댓글VO도 추가해준다.

이제 글작성 , 글삭제 등의 로직에 활동기록 테이블에 insert되도록 추가해준다.

이때 난 service에 넣어줬는데 처음에 잘 못 된 설계와 구현방법으로 인해 controller에서

service에 구현해야 할 항목들을 그냥 Controller에서 구현했다.

후에 로직을 여러가지 추가하려고 하니 결합성이 강해져서 고생이 늘어버렸다.

앞으론 Controller에선 파라미터를 받고 , 간단한 구분정도만 해주기로 하고

Service에서 컨트롤러에서 받은 파라미터로 로직을 작성하도록 할 예정이다.

(Controller에서 로직을 작성하는 바람에 받은 매개변수를 두,세번씩 선언하는 등 코드도 길어지고 복잡해졌다)

ServiceImpl

이전 이전 012 글작성엔 insert 글삭제엔 delete (카테고리 1)

1. 게시글 작성

2. 게시글 좋아요

3.게시글 싫어요

4.게시글 dev

5.게시글 스크랩

insert bno

6.댓글 작성

7.댓글 좋아요

8.댓글 싫어요

9.댓글 dev

insert rno

10. 채택

bno rno 채택한사람ID 채택받은사람ID

11.채택받음

bno rno 채택받은사람ID

insert questionId

1.게시글 삭제

2.게시글좋아요취소

3.게시글싫어요취소

4.게시글 dev취소

5.게시글스크랩 취소

deletelog

6.댓글삭제

7.댓글좋아요취소

8.댓글싫어요취소

9.댓글dev취소

deleteReplyLog

이런게 11가지의 카테고리의 로직에 insert와 delete를 추가하면서 22번의 코드를 작성했고 ,

파라미터의 잘못된 설계로 경로를 여러번 수정하고 , 추가하는 등 꽤나 시간이 걸렸다.

여려운 작업은 아니였지만 시간이 참 오래걸렸다.

insert, delete 로직에 logVO 객체를 가져와서 set으로 값을 넣어줬다.

만약 추가하고 싶은 활동로직이 있다면 카테고리를 새로 구분해서 해당 기능로직에 추가해주면 되겠다.

(로그인 기록 , 프로필 사진 변경 , 닉네임 변경기록 등등등)

이제 회원의 활동로직 사이에 테이블에 insert , delete가 제대로 되도록 구현했다면

select로 값을 뷰에 뿌려주면 된다.

Mapper.xml

일단 5개의 쿼리문들에 필요한 파라미터는 오직 memberId ( 회원PR ) 이다.

해당 파라미터를 받아오는 방식은 뒤에 작성하겠다.

첫번째 memberInfo 는

회원의 프로필사진 , 닉네임 , 좋아요Point , 개발Point 를 가져와서

회원의 프로필을 작성하는데에 사용한다.

2~5는 활동기록 , 작성한게시글 , 댓글 , 스크랩한 게시글 이다.

join을 이용한 간단한 select문이기 때문에 따로 설명은 생략하겠다.

Controller

@RequestMapping(value=”/board/mypageView”, method=RequestMethod.GET) public String mypageView(String select,String memberId,Model model) throws Exception{ logger.info(“select”+select); model.addAttribute(“info”,service.memberInfo(memberId)); model.addAttribute(“memberId”, memberId); if(select.equals(“log”)) { model.addAttribute(“log”,service.memberLog(memberId)); }else if(select.equals(“write”)) { model.addAttribute(“write”,service.memberWrite(memberId)); }else if(select.equals(“scrap”)) { model.addAttribute(“scrap”, service.memberScrap(memberId)); }else if(select.equals(“reply”)) { model.addAttribute(“reply”, service.memberReply(memberId)); } return “/board/mypageView”; }

일단

마이페이지 뷰인 mypageView를 호출하면 get방식으로 받는다.

매개변수를 @RequestParam을 통해 select , memberId 를 받아준다 ( 생략 )

프로필을 위한 info , 페이지 내에서 카테고리 이동을 위한 memberId를 model을 이용, 뷰로 데이터를 보내주고

if문으로 select값에 따라 해당 값에 맞는 쿼리를 구분해서 List를 뷰로 보내주도록 한다.

뷰에선 forEach문을 사용하기 때문에 log , write , scrap , reply List들의 코드를 작성해도 데이터 값이 없으면

출력되지 않는다. ( 해당되는 데이터값만 출력됨 )

이제 뷰단 출력인데 , 모자란 실력으로 엄청난 하드코딩을 해버렸으니 난해함에 주의바란다. ( 스승님이 있었으면,,,)

mypageView.jsp

일단 버튼을 만들어준다.

사용자는 본인의 마이페이지 버튼 클릭이나, 닉네임을 클릭해서 해당 페이지에 접속이 가능한데,

그때 자동적으로 memberId값을 가져오게 된다.

그래서 다른 버튼을 누를때 memberId를 매개변수로 받고 , 다시 뷰로 전송해주면서 memberId값을 유지했다.

(컨트롤러의 model.addAttribute(memberId) )

#${log.bno} 게시글을 작성 했습니다. #${log.bno} 게시글을 추천 했습니다. #${log.bno} 게시글을 반대 했습니다. #${log.bno} 게시글을 DEV 했습니다. #${log.bno} 게시글을 스크랩 했습니다. #${log.bno} 게시글에 #${log.rno} 댓글을 작성 했습니다. #${log.bno} 게시글에 #${log.rno} 댓글을 추천 했습니다. #${log.bno} 게시글에 #${log.rno} 댓글을 반대 했습니다. #${log.bno} 게시글에 #${log.rno} 댓글을 DEV 했습니다. #${log.bno} 질문글에 #${log.rno} 댓글 답변자 ${log.questionId}님을 채택 했습니다. #${log.bno} 질문글에 #${log.rno} 댓글이 채택 되었습니다.
${log.boardVO.title} ${log.boardVO.writer}

활동기록의 부분이다 ( select = log )

if문을 이용해 log.categori로 카테고리 값을 가져오고 , 카테고리값을 이용해서 문장을 바꿔준다.

#${write.bno} 게시글을 작성 했습니다.
${write.title} ${write.writer}

작성한 게시글 부분이다. 카테고리가 필요 없기 때문에 간단하게 작성이 가능하다.

댓글과 , 스크랩의 경우도 이와 같기 때문에 생략한다.

결과

이전 이전 0123 슬라이드쇼 4장

‘1234’ 회원의 활동로그 ‘1234’ 회원의 작성한 게시글 ‘2222’ 회원의 활동로그 ‘2222’ 회원의 작성한 게시글

(주소창의 get방식을 이용해서 해당 기능을 구현)

구현하면서 여러번 중복된 값이 DB에 올라갔기 때문에 , 결과가 조금 이상할 수 있지만 제대로 구분됨.

프로필 사진은 아직 구현 안했기 때문에 , 모두 같은 것임 ( 구현예정 )

이번엔 마이페이지를 구현했다.

아직 페이징도 추가해야하고 디자인도 다듬어야하지만 구현완료이다.

프로필 사진은 일단 나중에 구현해야지 하고 미뤄뒀는데 지금와서는 큰 짐이 되었다.. (반성…)

회원 프로필 사진 입력 , 수정을 구현하고 목록,상세내용,마이페이지,댓글 등등.. 추가해야 할 곳이 참 많다..

미리 구현했으면 흐름대로 할 수 있었을 텐데 했던거 또하고 또하고..

프로젝트 코드가 늘어날 수록 노가다가 늘어나고 있다.

참 설계와 일 분담의 중요성을 느끼게 되는 요즘이다.

취업을 해서 실제로 서비스를 구현하게 된다면 , 꼭 이런 효율성에 대한 부분을 생각하며 일해서 작업시간을 단축하고

코드를 가독성이 좋게 작성할 수 있도록 힘써야 겠다.. ( 머리가 나쁘면 몸이 고생 ㅜ)

앞으로 구현 할 목록

마이페이지

프로필사진

관리자페이지

채팅 , 알림기능 ( 소켓이용 )

오픈 API를 이용한 구글로그인 , 지도 이용

728×90

Spring boot 마이페이지!(1) with AuthenticationPrincipal

이제 마이페이지를 만들건대

간단하게

내 정보

비밀번호변경

이메일 인증 서비스를 구현해볼 것이다!

컨트롤러에서

controller.java

@GetMapping(“/mypage”)

/auth/를 빼고 작성해준다 왜냐면

로그인 시에만 들어올 수 있게 해 주기 위해서 이다

@AuthenticationPrincipal principaldetail principaldetail

로그인을 성공했다면

여기에서 로그인한 사용자 정보를 꺼내 쓸 수 있다

역시 스프링이 자체적으로 제공하는 기능이다

편리하고 보안성 있다

그리고 model에 uservo를 통으로 넘겨주고

html에서 사용해준다

mypage.html

놀랍게도 thymealf에서

함수까지 그대로 저렇게 사용이 가능하다

모든 게 제대로 출력된다

물론 시간제한도 만들고 해야 하지만

일단 완벽하게는 아니더라도

80프로 정도는 만들어보는 게 더 좋다고 생각한다

물론 나중에 부족한 공부도 꼭 해한다

현재 ajax 같은 경우도 복수 요청도 가능할 것이고

그로 인해 치명적인 속도 저하 및 버그도 분명 있을 것이다

하지만 일단 좀 더 큼직하게 공부를 해보자

이제 이메일 인증부터 구현하러 가 보자!

[Spring Boot/JPA] #3 View와 Controller 제작 : 마이페이지 만들기 (1)

개인적으로 시작한 개발이며, 틀린 점이나 부족한 부분이 많을 수 있으니 보완할 사항이나 질문은 댓글로 남겨주세요!

개발 환경

Database : mysql community Server 8.0.23

language : Java 11

Framework : Spring

IDE : IntelliJ ultimate ver.

OS : MS Win10 64bit

컨트롤러와 뷰 개발

지난 번 기본적인 서비스에 대한 개발을 했으니 필요한 뷰와 컨트롤러를 만들었고,

나는 로그인 이후 마이페이지를 맡기로 했다.

기본적인 URI를

~/mypage/me : 닉네임 또는 이메일 변경 / 정보 표시

~/mypage/contents : 내가 쓴 게시글

~/mypage/comments : 내가 쓴 댓글

~/mypage/scrap : 내가 스크랩한 글

~/mypage/password : 비밀번호 변경

로 정했다.

mypage/me

우선 제일 기본이 되는 페이지인 /mypage/me의 뷰를 만들었다.

JSP에 대해 잘 알지 못하는 관계로 진입장벽이 그나마 낮은 Thymeleaf(View Template)을 사용했다.

mypage/me.html

< html xmlns: th = " http://www.thymeleaf.org " > < head th: replace = " fragments/header :: header " /> < body > < div th: replace = " fragments/nav :: fragment-nav " > < th: block th: insert = " fragments/mypage-body :: mypage-body " /> < div class = " col-lg-4 " > < div class = " useredit " > < div class = " fa-user " > 개인정보 수정 < form role = " form " th: action = " @{/mypage/me} " th: object = " ${memberForm} " method = " post " > < div class = " form-group " > < label th: for = " name " > 닉네임 < input type = " text " th: field = " *{name} " class = " form-control " placeholder = " 닉네임을 입력하세요 " th: class = " ${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control' " > < p th: if = " ${#fields.hasErrors('name')} " th: errors = " *{name} " > Incorrect input < div class = " form-group " > < label th: for = " email " > 이메일 < input type = " email " th: field = " *{email} " class = " form-control " placeholder = " None " th: class = " ${#fields.hasErrors('email')}? 'form-control fieldError' : 'form-control' " > < p th: if = " ${#fields.hasErrors('email')} " th: errors = " *{email} " > Incorrect input < button type = " submit " class = " btn btn-primary " > 수정 < br />

controller/MemberForm

@Getter @Setter public class MemberForm { @NotEmpty ( message = “닉네임은 필수입니다.” ) private String name ; @NotEmpty ( message = “이메일은 필수입니다.” ) private String email ; }

회원 정보 수정 DTO인 memberForm을 넘겨 받아, 그 안의 변수인 name과 string을 각 입력 field로 사용한다. 수정 button을 눌렀을 때 form과 함께 HTTP post 메서드로 요청할 주소를

뷰를 열심히 뚝딱뚝딱 만들었으니 이를 보여주고 post요청을 처리할 컨트롤러가 필요하다.

controller/MyPageController

@GetMapping ( “/mypage/me” ) public String myPageHome ( Model model , @AuthenticationPrincipal Member currentMember ) { List < Category > categoryList = categoryService . findAll ( ) ; MemberForm memberForm = new MemberForm ( ) ; memberForm . setName ( currentMember . getUsername ( ) ) ; memberForm . setEmail ( currentMember . getEmail ( ) ) ; model . addAttribute ( “categoryList” , categoryList ) ; model . addAttribute ( “memberForm” , memberForm ) ; return “mypage/me” ; }

category에 대한 정보는 모든 뷰에 공통으로 들어가는 side-bar fragments에서 사용되는 것이므로 추후에 설명하도록 한다.

“/mypage/me”의 URL로 Get요청으로 들어올 경우 위에서 만든 뷰를 보여줘야 한다.

해당 뷰에는 개인정보를 수정할 Form이 필요하므로 MemberForm을 새로 생성해주고 현재 로그인한 정보를 @AuthenticationPrincipal을 통해 접근하여 set한 후 model에 Attribute로 추가시켜준다.

Form의 field를 set하는 이유는 빈칸의 form이 아닌 현재 사용자의 정보를 담게 하고 싶어서이다.

@AuthenticationPrincipal

Spring Security에서 현재 로그인한 사용자 정보를 Session에서 조회할 수 있도록 제공한다. @AuthenticationPrincipal을 통해 UserDetails를 구현한 구현체인 Member 클래스를 반환한다. UserDetails를 구현해야하는 이유는, Spring Security가 UserDetailsService를 구현한 구현체의 오버라이딩된 메서드인 loadUserByUsername()을 통해 현재 사용자를 리턴하기 때문이다.

service/MemberServiceImpl

@Override public UserDetails loadUserByUsername ( String username ) throws UsernameNotFoundException { Member memberEntity = memberRepository . findByUsername ( username ) . orElseThrow ( ( ) -> new UsernameNotFoundException ( username ) ) ; List < GrantedAuthority > authorities = new ArrayList < > ( ) ; if ( ( “admin” ) . equals ( username ) ) { authorities . add ( new SimpleGrantedAuthority ( MemberRole . ADMIN . getValue ( ) ) ) ; } else { authorities . add ( new SimpleGrantedAuthority ( MemberRole . USER . getValue ( ) ) ) ; } return new Member ( username , memberEntity . getPassword ( ) , memberEntity . getEmail ( ) , authorities ) ; }

이 메서드는 반드시 오버라이딩해야하는 메서드인데 리턴 타입이 UserDetails이다.

회원의 Role에 맞는 권한을 부여하고 새 Member 객체를 리턴한다. 여기서 Member가 UserDetails를 구현한 구현체이므로 Member를 리턴할 수 있다. UserDetails를 구현한 구현체가 여러 개라면 new User 또는 new UserDetails라고 하는 게 낫겠으나, 우리는 구현체가 Member 클래스 하나 뿐이므로 Member를 리턴하도록 하였다.

돌아와서

Get 요청을 받아 해당 뷰를 보여주는 컨트롤러를 만들었으니 Form을 받아 Post 요청을 처리하는 컨트롤러도 만들어야 한다.

controller/MyPageController

@PostMapping ( “/mypage/me” ) public String userEdit ( MemberForm form , BindingResult result , @AuthenticationPrincipal Member currentMember ) { if ( result . hasErrors ( ) ) { return “redirect:/mypage/me” ; } memberService . updateInfo ( currentMember . getUsername ( ) , form . getName ( ) , form . getEmail ( ) ) ; currentMember . setUsername ( form . getName ( ) ) ; currentMember . setEmail ( form . getEmail ( ) ) ; return “redirect:/mypage/me” ; }

service/MemberSerivceImple

@Transactional @Override public Long updateInfo ( String username , String newName , String email ) { Member member = memberRepository . findByUsername ( username ) . orElseThrow ( ( ) -> new UsernameNotFoundException ( username ) ) ; member . setUsername ( newName ) ; member . setEmail ( email ) ; return member . getId ( ) ; }

memberService의 updateInfo를 호출해 DB의 username과 email을 변경한다. JPA 변경 감지를 통해 수정한다. JPA 변경 감지는 자세한 공부를 위해 다른 포스트에서 설명해야할 것 같다.

그리고 컨트롤러에서 현재 로그인한 사용자의 username과 email도 바꿔줘야 한다.

@AuthenticationPrincipal을 통해 사용자를 리턴받을 때 Session에 있는 username을 통해 검색을 하는데, 그게 바뀌지 않을 경우 아무리 getUsername을 해봐야 update 이전의 username을 뱉어낸다.(DB에는 update되어 있지만 Session에는 update되지 않은 정보가 남아 있다.)

이게 맞는 방법인지는 모르겠다. Session update에 대해 더 찾아봐야겠다.

currentMember의 userName을 set한 경우/하지 않은 경우를 테스트 해보면

원래 닉네임이 ddd11이고 ddd22로 변경

set한 경우

GetMapping된 컨트롤러에서 memberForm의 기본 정보를 현재 사용자 정보로 설정해주므로 이렇게 변경된 닉네임이 나오는 게 맞다.

set을 안 한 경우

아무리 변경해봐야 얘는 안 바뀐다.

mypage/contents

mypage/contents.html

< html xmlns: th = " http://www.thymeleaf.org " > < head th: replace = " fragments/header :: header " /> < body > < div th: replace = " fragments/nav :: fragment-nav " > < th: block th: insert = " fragments/mypage-body :: mypage-body " /> < div class = " container d-flex mt-5 " > < table class = " box shadow table " > < thead > < tr > < td class = " h4 " colspan = " 6 " > 내가 쓴 글 < tr > < th style =" width : 10% " > 번호 < th style =" width : 50% " > 제목 < th style =" width : 10% " > 이름 < th style =" width : 10% " > 추천 < th style =" width : 10% " > 날짜 < th style =" width : 10% " > 조회 < tbody > < tr th: each = " post: ${posts} " > < td style =" width : 10% " th: text = " ${post.id} " > < td style =" width : 10% " > < a th: href = " @{/content/{postId}(postId=${post.id},prev=1,prev_content='/board/'+${post.category.id})} " th: text = " ${post.title} " > < td style =" width : 10% " th: text = " ${post.member.username} " > 익명 < td style =" width : 10% " th: text = " ${post.likes} " > 추천 < td style =" width : 10% " th: text = " ${#temporals.format(post.createDate, 'HH:mm')} " > 날짜 < td style =" width : 10% " th: text = " ${post.visit} " > 조회 < div class = " container " > < nav aria-label = " Page navigation example " > < ul class = " pagination justify-content-center " th: with = " start=${T(Math).floor(posts.number/10)*10 + 1}, last=(${start + 9 < posts.totalPages ? start + 9 : posts.totalPages}) " > < li class = " page-item " > < a th: href = " @{/contents/(page=1)} " aria-label = " First " > < span aria-hidden = " true " > First < li class = " page-item " th: class = " ${posts.first} ? 'disabled' " > < a th: href = " ${posts.first} ? '#' : @{/contents/(page=${posts.number})} " aria-label = " Previous " > < span aria-hidden = " true " > < < li class = " page-item " th: each = " page: ${#numbers.sequence(start, last)} " th: class = " ${page == posts.number + 1} ? 'active' " > < a th: text = " ${page} " th: href = " @{/contents/(page=${page})} " > < li class = " page-item " th: class = " ${posts.last} ? 'disabled' " > < a th: href = " ${posts.last} ? '#' : @{/contents/(page=${posts.number+2})} " aria-label = " Next " > < span aria-hidden = " true " > > < li class = " page-item " > < a th: href = " @{/contents/(page=${posts.totalPages})} " aria-label = " Last " > < span aria-hidden = " true " > Last

아래와 같이 나온다. 임의로 게시글을 여러개 만들었다. 테이블을 만들어 Thymeleaf 문법을 사용해 반복문으로 td를 만들게 했다.

html의 class=”container”인 div는 page에 관한 태그들인데, First, Last 1, 2 …를 나타내기 위함이다.

controller/MyPageController

@GetMapping ( “/mypage/contents” ) public String myContents ( Model model , @AuthenticationPrincipal Member currentMember , @PageableDefault Pageable pageable ) { Member member = memberService . findByUsername ( currentMember . getUsername ( ) ) . orElseThrow ( ( ) -> new UsernameNotFoundException ( currentMember . getUsername ( ) ) ) ; Page < Post > posts = postService . getPostListByMember ( member , pageable ) ; List < Category > categoryList = categoryService . findAll ( ) ; model . addAttribute ( “categoryList” , categoryList ) ; model . addAttribute ( “posts” , posts ) ; return “mypage/contents” ; }

새로운 어노테이션인 @PageableDefault … JPA는 어렵다. Paging에 관련된 어노테이션이다. 컨트롤러는 간단하게 페이징한 목록을 model에 추가해 뷰를 리턴하는 구조이다.

여기서 눈여겨볼 것은 @PageableDefault, 페이징에 대해 열심히 구글링 해보면서 여러 페이징 방법이 있지만 가장 편하게? 할 수 있는 방법 같다.

이 방법을 사용하지 않고서 할 수 있는 방법은 VO를 만들고, 페이지에 해당하는 select SQL 쿼리를 날려 얻는 방법이 있다. 이는 데이터베이스마다 페이징 쿼리가 다를 수 있고 여러 요구 사항을 만족하기 어려울 수 있다. SQL이 아닌 java 코드 관점에서 DB를 접근하기 위해 Spring Data JPA를 사용하는 것이고 이를 이용하면 비즈니스 로직에 더욱 집중할 수 있기에 이 방법을 선택했다.

@PageableDefault

JPA에서 제공하는 Paging을 위한 어노테이션이다. Pageable 인터페이스를 구현한 구현체를 파라미터로 받는다.

@Documented @Retention ( RetentionPolicy . RUNTIME ) @Target ( ElementType . PARAMETER ) public @interface PageableDefault { int value ( ) default 10 ; int size ( ) default 10 ; int page ( ) default 0 ; String [ ] sort ( ) default { } ; Direction direction ( ) default Direction . ASC ; }

Client로부터 쿼리스트링을 통해 페이징 정보가 주어지지 않는다면 PageDefault에 이 디폴트 값으로 설정된다.

디폴트 값이 아닌 원하는 값을 지정해주고 싶다면 @PageableDefault(page = 1, size = 20) 과 같이 파라미터로 넣어주면 된다.

나는 서비스의 메서드에서 값을 설정해주었는데, 이 방법보다는 파라미터로 넣어주는 것이 이후의 유지보수에도 효율적일 것 같다는 생각이 든다.

service/PostServiceImple

@Override public Page < Post > getPostListByMember ( Member member , Pageable pageable ) { int page = ( pageable . getPageNumber ( ) == 0 ) ? 0 : ( pageable . getPageNumber ( ) – 1 ) ; pageable = PageRequest . of ( page , 10 , Sort . by ( “id” ) . descending ( ) ) ; return postRepository . findByMember ( member , pageable ) ; }

Page 인터페이스를 AbstractPageRequest라는 추상클래스가 구현하고, 이 추상클래스를 PageRequest라는 클래스가 상속받는 구조로 되어있다.

PageRequest.of()를 통해 새로운 PageRequest를 생성하여 리턴받는다.

postRepository 수정

@Repository public interface PostRepository extends JpaRepository < Post , Long > { public List < Post > findByMember ( Member member ) ; public List < Post > findByCategory ( Category category ) ; Page < Post > findByMember ( Member member , Pageable pageable ) ; }

JpaRepository는 Page를 리턴 타입으로 갖고, Pageable을 파라미터로 받는 메서드를 만들어주면 알아서 해당 Pageable의 정보를 갖고 Paging해서 리턴한다. 이는 JpaRepository 인터페이스가 PagingAndSoringRepository 인터페이스를 상속받고 있기 때문이다.

쓰다보니 너무 길어져

다음에 myPage/comments와 password에 대한 글을 포스팅해야겠다…

JAVA / SPRING 프로젝트 삼삼하개(3) 마이페이지(개인/업체) 내 작성글, 작성댓글 조회 구현

팀프로젝트가 끝나고 되돌아보는 시간 (3) 마이페이지(개인/업체) 내 작성글, 작성댓글 조회 구현

내 작성글, 작성댓글을 불러오는 페이지를 작업하면서 돌이킬수 없는 후회가 생겼습니다.

바로 테이블 설정..

구성 당시에는 먼 미래를 생각하며 각게시판을 카테고리화해서 구성하면 데이터가 많이 쌓였을때 성능저하가 생기지 않을까? 라는 의문으로 프로젝트를 구성할때 각 게시판 테이블을 따로 만들었는데(심지어 필드명도 다 다르게..)

우리는 빌드하여 프로젝트로만 활용할 뿐 실제 배포 및 운영은 계획이 없었기에 고려하지 않아도 되는 상황인데다가

검색 기능이나 이렇게 한번에 조회하는 페이지를 구현할때 불필요하게 동일한 코드를 여러번 적게끔 만들었습니다

이미 거의 막바지에 다와서 수정하면서 생긴 문제이기도 하고 고치게되면 한둘도 아니고 팀원 모두가 본인이 작성한 코드를 다 수정해야되었기에 그대로 적용하게 되었습니다

작성글 / 작성댓글 탭은 input type = radio 로 구현하였고,

데이터는 한번에 불러온 후 자바스크립트로 5개만 보이고 나머지는 숨김 처리하여 더보기 클릭시 5개씩 추가로 보이게 했습니다.

Controller (각 게시판별로 게시글, 댓글 데이터 가져오기)

@RequestMapping(value = “/cominfo_list.me”) public String cominfo_list(HttpSession session, Model model) { String email = (String)session.getAttribute(“email”); ArrayList b_listal = memberSV.getWriteList1(email); if(b_listal != null ) { model.addAttribute(“b_listal”, b_listal); } ArrayList c_listal = memberSV.getWriteComment1(email); if(c_listal != null ) { model.addAttribute(“c_listal”, c_listal); } ArrayList b_listfd = memberSV.getWriteList2(email); if(b_listfd != null ) { model.addAttribute(“b_listfd”, b_listfd); } ArrayList c_listfd = memberSV.getWriteComment2(email); if(c_listfd != null ) { model.addAttribute(“c_listfd”, c_listfd); } ArrayList b_listfa = memberSV.getWriteList3(email); if(b_listfa != null ) { model.addAttribute(“b_listfa”, b_listfa); } ArrayList c_listfa = memberSV.getWriteComment3(email); if(c_listfa != null ) { model.addAttribute(“c_listfa”, c_listfa); } ArrayList b_listah = memberSV.getWriteList4(email); if(b_listah != null ) { model.addAttribute(“b_listah”, b_listah); } ArrayList c_listah = memberSV.getWriteComment4(email); if(c_listah != null ) { model.addAttribute(“c_listah”, c_listah); } ArrayList b_listco = memberSV.getWriteList5(email); if(b_listco != null ) { model.addAttribute(“b_listco”, b_listco); } ArrayList c_listco = memberSV.getWriteComment5(email); if(c_listco != null ) { model.addAttribute(“c_listco”, c_listco); } ArrayList b_listp = memberSV.getWriteList6(email); if(b_listp != null ) { model.addAttribute(“b_listp”, b_listp); } ArrayList c_listp = memberSV.getWriteComment6(email); if(c_listp != null ) { model.addAttribute(“c_listp”, c_listp); } ArrayList b_listm = memberSV.getWriteList7(email); if(b_listm != null ) { model.addAttribute(“b_listm”, b_listm); } ArrayList c_listm = memberSV.getWriteComment7(email); if(c_listm != null ) { model.addAttribute(“c_listm”, c_listm); } return “YM/cominfo_write”; }

Mapper (Mybatis)

from절에 서브쿼리를 사용하여 여러테이블에 있는 데이터를 한번에 조회할수 있었지만,

테이블을 따로 식별할 수 없어 Sevice단에서 메소드로 구분지었습니다.

cominfo_write.jsp (작성글/작성댓글 관리)

if(boardlist_m.size() != 0){%>

실종게시판(<%=boardlist_m.size() %>)
아이디 ${memVO.user }
<% for(BoardlistVO b_list : boardlist_m){ %>

<% } %>

글번호 제목 작성일
<%=b_list.getNum() %> <%=b_list.getSubject() %> <%=b_list.getWrite_date() %>

<% }} else{%>

작성글이 없습니다.

<% } %>

각 게시판별로 테이블이 따로이고 필드명도 다 다르다보니 mapper에서도 for문을 돌릴래도 불가하여,

테이블 별로 데이터를 조회하여 ArrayList 타입으로 가져왔습니다.

** 나중에 네이버 카페의 작성글/작성댓글을 보며 게시판별로 조회하진 않는다는 것을 알게되었습니다.

게시판의 성격이 중요하지 않다면 따로 구분하여 조회하지 않고 한번에 조회해도 좋을것 같다는 생각이 들었고,

아니면 미리보기 성격으로 작성글관리 페이지에서 글제목을 클릭하면 아래로 슬라이딩되면서 글 내용의 일부를 확인 할 수 있다던가

하는 기능을 넣어보는것도 좋을 것 같습니다.

[스프링SPRING] 회원정보조회, 회원정보수정, 회원정보삭제

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

(value = “/info” , method = RequestMethod.GET)

public void infoGET (HttpSession session, Model model) throws Exception {

String id = (String) session.getAttribute( “id” );

l.info( “C: 회원정보보기 GET의 아이디 ” +id);

MemberVO vo = service.readMember(id);

model.addAttribute( “memVO” , vo);

l.info( “C: 회원정보보기 GET의 VO ” + vo);

}

(value= “/update” , method = RequestMethod.GET)

public String updateGET (HttpSession session, Model model) throws Exception {

model.addAttribute( “memVO” , service.readMember((String)session.getAttribute( “id” )));

return “/member/updateForm” ;

}

(value= “/update” , method = RequestMethod.POST)

public String updatePOST (MemberVO vo) throws Exception {

l.info( “C: 회원정보수정 입력페이지 POST” );

service.updateMember(vo);

return “/member/main” ;

}

(value = “/delete” , method = RequestMethod.GET)

public String deleteGET (HttpSession session) throws Exception {

l.info( “C: 회원정보 삭제 GET” );

String id = (String) session.getAttribute( “id” );

if (id == null ) {

return “redirect:/member/main” ;

}

return “/member/deleteForm” ;

}

(value = “/delete” , method = RequestMethod.POST)

public String deletePOST (MemberVO vo, HttpSession session) throws Exception {

l.info( “C: 회원정보 삭제 POST” );

l.info( “C: deleteForm전달정보 ” +vo);

service.deleteMember(vo);

session.invalidate();

return “redirect:/member/main” ;

}

[Final Project] 마이페이지 기능 구현 정리

– 클래스 목록 resultmap

public class ClassVO { //이거 추가 private ClassPayInfoVO payinfo;

– MypageChefmapper.xml

-MypageChefDAOInter

package kr.co.ikosmo.mvc.dao; import java.util.List; import java.util.Map; import kr.co.ikosmo.mvc.vo.ClassVO; import kr.co.ikosmo.mvc.vo.Recipe_infoVO; public interface MypageChefDAOInter { //——————– //(쉐프)레시피 목록 – 페이징 //——————– public List getList(Map map); //페이징 처리 public int getTotalCount();//페이징 카운트 //—————– //(쉐프)클래스 목록 출력 //—————– public List getClassList(int mem_no);//클래스 리스트 //————————— //(쉐프)가 수강중인 클래스 목록 출력 //————————— public List getClassList_std(int mem_no);//쉐프가 수강중인 클래스 리스트 //———————– //(쉐프)statistic 숫자 카운트 //———————– public int getMyRecipeCount(Map map); //내 레시피 갯수 public int getMyReviewCount(Map map); //내 레시피에 달린 리뷰 갯수 public int getMyClassCount(Map map); //쉐프가 수강중인 클래스 갯수 public int getMyClientCount(Map map); //내가 진행중인 클래스를 듣는 고객의 수 public int getMyScrapCount(Map map); //스크랩한 레시피 갯수 public int getMyStarAvgCount(Map map); //내가 쓴 레시피의 별점 평균 }

– MypageChefDAOImple

package kr.co.ikosmo.mvc.dao; import java.util.List; import java.util.Map; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import kr.co.ikosmo.mvc.vo.ClassVO; import kr.co.ikosmo.mvc.vo.Recipe_infoVO; @Repository public class MypageChefDAOImple implements MypageChefDAOInter{ @Autowired private SqlSessionTemplate ss; //——————– //(쉐프)레시피 목록 – 페이징 //——————– @Override public List getList(Map map){ //nowPage등으로 연산이 된 start,end return ss.selectList(“mppc.listc”,map); } @Override public int getTotalCount() {//전체 데이터를 기준으로 페이지를 나눌것이기 때문에.. return ss.selectOne(“mppc.totalCountc”); } //—————– //(쉐프)클래스 목록 출력 //—————– @Override public List getClassList(int mem_no) { //클래스 리스트 출력 return ss.selectList(“mppc.classlistC”, mem_no); } //————————— //(쉐프)가 수강중인 클래스 목록 출력 //————————— public List getClassList_std(int mem_no) {//쉐프가 수강중인 클래스 리스트 return ss.selectList(“mppc.classlist_std”, mem_no); } //———————– //(쉐프)statistic 숫자 카운트 //———————– @Override public int getMyRecipeCount(Map map) { //내 레시피 갯수 return ss.selectOne(“mppc.myRecipeCount”, map); } @Override public int getMyReviewCount(Map map) { //내 레시피에 달린 리뷰 갯수 return ss.selectOne(“mppc.myReviewCount”, map); } @Override public int getMyClassCount(Map map) { //쉐프가 수강중인 클래스 갯수 return ss.selectOne(“mppc.myClassCount”, map); } @Override public int getMyClientCount(Map map) { //내가 진행중인 클래스를 듣는 고객의 수 return ss.selectOne(“mppc.myClientCount”, map); } @Override public int getMyScrapCount(Map map) { //스크랩한 레시피 갯수 return ss.selectOne(“mppc.myScrapCount”, map); } @Override public int getMyStarAvgCount(Map map) { //내가 쓴 레시피의 별점 평균 return ss.selectOne(“mppc.myStarAvgCount”, map); } }

– MypageChefController

[Spring] 쇼핑몰 프로젝트(4)

<개인 정보 확인>

개인정보는 Controller까지만 작성해된다.

왜냐면 이미 로그인한 session에 로그인한 user의 회원가입 정보가 담겨있기 때문이다.

<정보 수정>

정보 수정 또한, 기존의 데이터를 수정하는 것이기 때문에 session을 가져와 session.setAttribute(“member”, m);처럼 수정한 새로운 정보를 member에 담아준다. jsp에서는 ${member.userId}이런 식으로 값을 출력

<회원 탈퇴>

수정할때는 session을 받아오고 밑에서 따로 꺼내왔는데 매개변수에 @SessionAttribute(“member”) Member m을 사용해서 한번에 session 꺼내와서 담기 가능하다.

@SessionAttribute는 HttpSession에 저장되어있는 값을 Handler의 매개변수에 맵핑해주는 어노테이션이다.

이번에는 마이페이지를 구현해보도록 하겠습니다.

마이페이지를 구현할 때, 마이페이지 에는 내가 쓴 글을 같이 확인 하기 위해서 테이블의 Join 을 한번 해보도록 할 겁니다.

마이페이지 구현

위 처럼 확인 할 수 있도록 할 건데요

먼저 테이블의 JOIN 이 있다는 걸 알아야 합니다.

즉. User 의 개인정보를 가지고 있는 테이블, 게시판에 대한 테이블 을 JOIN 합니다.

그러려면 JOIN 에 대한 기본 지식을 알고 있어야 합니다. LEFT OUTER JOIN, INNER JOIN 등등…

JOIN 은 이런 식으로 수행하면 되는데요

두 테이블의 병합 이기 때문에, 값을 받아주는 곳에서 문제가 생깁니다.

바로, 유저는 1개지만, 게시판에 대한 정보가 여러개가 될 수 있겠죠?

즉. 1 : N 의 관계가 되어 버립니다.

그래서 값을 가지고 나올 때, 1 의 관계를 가지는 UserVO 에 N 의 관계를 가지는 FreeBoardVO 를 List 로 추가 합니다.

※ Lombok 을 사용 중 ( setter, getter, 생성자 자동 생성 )

그러면, 문제는 List 로 들어가는 게시판에 대한 정보를 어떻게 넣어주냐 는 것인데요

resultMap 을 이용하면 됩니다.

resultMap 을 이용하면, 각각의 변수를 의 property, column 을 통해서 데이터를 넣어주어야 합니다.

이 때, 게시판에 대한 정보는 List 로 되어 있기 때문에, 한번 더 resultMap 을 이용해서 타고 들어 갑니다.

이렇게 완료했다면, 가지고 나온 데이터를 컨트롤러에서 저장한 후 , 화면에서 뿌려주면 됩니다.

키워드에 대한 정보 spring 마이 페이지

다음은 Bing에서 spring 마이 페이지 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 [자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기

  • jsp무료강좌
  • spring무료강좌
  • 스프링 기반 쇼핑몰
  • 도서 쇼핑몰
[자바 #웹을 #다루는 #기술] # #31.11 #마이 #페이지 #구현하기


YouTube에서 spring 마이 페이지 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 [자바 웹을 다루는 기술] 31.11 마이 페이지 구현하기 | spring 마이 페이지, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

Leave a Comment