카테고리 없음

1.11 (ch15(tiles db파일 저장)-기본 세팅, 메인/ 회원가입 폼 출력)

쿠룽지 2024. 1. 13. 23:05
728x90
반응형

<복습>

 

ch14-Spring_tiles

tiles=화면을 include하는 방식이라 폭넓게 디자인을 만들어낼 수 있음 (규모가 큰 사이트에 적합)

 

<Spring tiles 설정하는 방법>

1. pom.xml

org.apache.tiles dependency

 

2. 자바코드기반설정

kr.spring.config
AppConfig

@Configuration + @Bean 어노테이션 사용

1) tilsconfigurer : def 파일 (.xml) 경로 지정

2) tilesviewresolver : tilesview가 실제로 레이아웃을 구성한 후 viewresolver가 자원을 낚아챔

 

AppConfig에서 TilesConfigurer가 tilesdef.xml 경로를 지정했기 때문에 xml파일에 구성할 레이아웃을 명시하면 됨

 


 

 

 

ch15목표 -> Spring boot + ui framework는 tiles + my sql 을 사용,

db연동 후 사이트 구현하기

 

 

 

<설정작업>

src/main/java

kr.spring.config 

AppConfig.java

package kr.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
//자바코드 기반 설정 클래스
@Configuration
public class AppConfig implements WebMvcConfigurer {
	@Bean
	public TilesConfigurer tilesConfigurer() {
		final TilesConfigurer configurer = new TilesConfigurer();
		//tilesdef.xml의 경로와 파일명 지정
		configurer.setDefinitions(new String[] {"/WEB-INF/tiles-def/main.xml"});
		configurer.setCheckRefresh(true);
		return configurer;
	}
	
	@Bean
	public TilesViewResolver tilesViewResolver() {
		final TilesViewResolver tilesViewResolver = new TilesViewResolver();
		
		tilesViewResolver.setViewClass(TilesView.class);
		return tilesViewResolver;
	}
}

configurer.setDefinitions(new String[] {"/WEB-INF/tiles-def/main.xml"});
첫 화면을 main으로 열거기 때문에 tilesdef를 main으로 수정 / xml 파일 생길 때마다 추가

 

 

 


 

 

 

<기본 데이터 셋팅>

1.
webapp
WEB-INF (folder)
tiles-def (folder)
ch14에서 tilesdef.xml 을 복붙해서 main.xml로 이름 변경하기


2.
webapp
sql (folder)
table.sql (file)

--회원관리
create table spmember(
 mem_num number not null,
 id varchar2(12) unique not null,
 nick_name varchar2(30),
 auth number(1) default 2 not null, --0:탈퇴회원,1:정지회원,2:일반회원,9:관리자
 constraint spmember_pk primary key (mem_num)
);

create table spmember_detail(
 mem_num number not null,
 au_id varchar2(36) unique, --자동로그인 시 들어갈 식별자(첫 입력 시 null이기 때문에 null 허용)
 name varchar2(30) not null,
 passwd varchar2(35) not null,
 phone varchar2(15) not null,
 email varchar2(50) not null,
 zipcode varchar2(5) not null,
 address1 varchar2(90) not null,
 address2 varchar2(90) not null,
 photo blob,
 photo_name varchar2(100),
 reg_date date default sysdate not null,
 modify_date date,
 constraint spmember_detail_pk primary key (mem_num),
 constraint spmember_detail_fk foreign key (mem_num) references spmember (mem_num)
);

create sequence spmember_seq;

 

 

 


 

 

 

spring 파일 저장 방법

1) 특정 경로에 저장

2) db에 저장

 

이번 프로젝트는 회원 프로필 사진-> db저장 / 그 외 파일은 특정 경로에 저장해서 수행

게시판 글쓰기 도 easywork editor (예-썸머노트 ,씨케이에디터 등) 사용할 것임 (태그를 넣지 않더라도 여러 기능을

넣을 수 있는 외부 라이브러리)

 

 

 

초기 메인화면 (tiles)

views (folder)
main (folder)
main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 내용 시작 -->
<div class="page-main">
	<h1>메인 페이지</h1>
</div>
<!-- 내용 끝 -->

 

 

 

 

 

header 부분

views
template (folder)
header.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 상단 시작 -->
<h2 class="align-center">SpringPage</h2>
<div class="align-right">
	<c:if test="${!empty user}">
	<a href="${pageContext.request.contextPath}/member/myPage">MY페이지</a>
	</c:if>
	
	<c:if test="${!empty user}">
	<a href="${pageContext.request.contextPath}/member/logout">로그아웃</a>
	</c:if>
	
	<c:if test="${empty user}">
	<a href="${pageContext.request.contextPath}/member/registerUser">회원가입</a>
	<a href="${pageContext.request.contextPath}/member/login">로그인</a>
	</c:if>
	
	<c:if test="${empty user || user.auth != 9}">
	<a href="${pageContext.request.contextPath}/main/main">홈으로</a>
	</c:if>
	
	<c:if test="${!empty user && user.auth == 9}">
	<a href="${pageContext.request.contextPath}/main/admin">관리자</a>
	</c:if>
</div>
<!-- 상단 끝 -->

1.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

조건문 기재 시 core 명시

 

2.

읽어오는 정보가 많기 때문에 자바빈 객체를 통째로 저장해서 정보를 읽어오는 방식으로 작성했음

자바빈 = user

 

3.

${pageContext.request.contextPath}
경로 지정시 다른 경로인 파일을 지정할 때 contextpath를 명시했는데 같은 경로였을 때에도 명시 가능

에러도 안나고 같은 파일이면 그냥 자동으로 생략된다고 함 그래서 경로 지정 시 contextpaht를 쓰는게 안전

4. /member/myPage (확장자 명시 없이 경로 지정)
지금까지 list.do 식으로 지정했는데 요즘은 확장자 없이 명시하는 경우가 많다고 함
그래서 이번 프로젝트는 확장자 없이 경로 지정해볼 것

 

 

 

 

footer 부분

views
template (folder)
footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 하단 시작 -->
<div class="align-center">
	&copy; SpringPage
</div>
<!-- 하단 끝 -->

 

 

 

 

 

 

레이아웃 페이지 (일반 회원자 페이지)

template
layout_basic.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><tiles:getAsString name="title"/></title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/layout.css">
</head>
<body>
<div id="main">
	<div id="main_header">
		<tiles:insertAttribute name="header"/>
	</div>
	<div id="main_body">
		<tiles:insertAttribute name="body"/>
	</div>
	<div id="main_footer">
		<tiles:insertAttribute name="footer"/>
	</div>
</div>
</body>
</html>

여기서 tiles들을 합치기 때문에 layout 페이지에서는 taglib를 tiles로 줬음

title, header, body, footer 는 각 페이지 이름

 

 

 

 


 

 

 

 

스타일 시트는 resources > static 폴더 안에 들어감

보통 js파일, css, 이미지 파일 등을 넣음

 

src/main/resources
static
css (folder)

layout.css

 

 

스타일 설정 생략 ..

 

 

 

 


 

 

 

레이아웃 매핑 설정

tiles-def

main.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>
    <definition name="main" template="/WEB-INF/views/template/layout_basic.jsp">
    	<put-attribute name="title" value="SpringPage"/>
    	<put-attribute name="header" value="/WEB-INF/views/template/header.jsp"/>
    	<put-attribute name="body" value="/WEB-INF/views/main/main.jsp"/>
    	<put-attribute name="footer" value="/WEB-INF/views/template/footer.jsp"/>
    </definition>
    
</tiles-definitions>

getAsString인 title을 제외하고 모두 경로를 넣어줌

 

 

 

 


 

 

 

 

컨트롤러에서 호출하기

src/main/java
kr.spring.main.controller (package)
MainController (class)

package kr.spring.main.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class MainController {
	//초기화
	@RequestMapping("/")
	public String init(HttpSession session) {
		//관리자로 로그인하면 관리자 메인으로 이동 처리
		
		return "redirect:/main/main";
	}
	
	//메인호출
	@RequestMapping("/main/main")
	public String main(Model model) {
		
		log.debug("<<메인 실행>>");
		
		return "main"; //tiles설정명
	}
}

1.

@Slf4j
lombok기능을 이용해서 로그대상 지정
(lombok에서 로그대상 지정할 때 어노테이션을 지원해주기 때문에 따로 명시할 필요 x)

 

2.

그냥 메인 호출만 하면 root를 호출하기 때문에 redirect를 넣어줘야함

 

3.

인자값을 HttpSession으로 넣어서 session에서 관리자(auth==9)인지, 아닌지 판단 후 

일반회원 > main 관리자 > admin 페이지로 각각 redirect시킬 예정임 (일단 페이지 호출되는지 확인 후)

 

 

 


 

 

 

 

 

회원가입 위해 VO생성

kr.spring.member.vo
MemberVO

package kr.spring.member.vo;

import java.io.IOException;
import java.sql.Date;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.springframework.web.multipart.MultipartFile;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
//ToString이 재정의될 때 photo의 값을 반환하지 않음
@ToString(exclude = {"photo"})
public class MemberVO {
	private int mem_num;
	@Pattern(regexp="^[A-Za-z0-9]{4,12}$") //[리스트]{min,max값}
	private String id;
	private String nick_name;
	private int auth;
	private String auto; // 자동로그인 시 사용하기 위해 (추가)
	private String au_id;
	@NotBlank
	private String name;
	@Pattern(regexp="^[A-Za-z0-9]{4,12}$")
	private String passwd;
	@NotBlank
	private String phone;
	@Email
	@NotBlank
	private String email;
	@Size(min=5,max=5)
	private String zipcode;
	@NotBlank
	private String address1;
	@NotEmpty
	private String address2;
	private byte[] photo;
	private String photo_name;
	private Date reg_date;
	private Date modify_date;
	private String now_passwd; //비밀번호 변경 시 사용하기 위해 (추가)
	
	/*=====================
	 * 비밀번호 일치 여부 체크 메서드
	  =====================*/
	public boolean isCheckedPassword(String userPasswd) {
		if(auth > 1 && passwd.equals(userPasswd)) { //0,1(탈퇴,정지)는 진입 자체를 막기위해
			return true;
		}
		return false;
	}
	
	/*=====================
	 * 이미지 BLOB 처리 메서드
	  =====================*/
	//(주의)폼에서 파일 업로드 파라미터네임은 반드시 upload로 지정해야 함
	public void setUpload(MultipartFile upload) throws IOException {
		//MultipartFile -> byte[]
		setPhoto(upload.getBytes());
		//파일명 지정
		setPhoto_name(upload.getOriginalFilename());
	}
	
}

1.

private byte[] photo;

파일 db 저장 시 --> blob 지정 해야함 // 이때 마이바티스가 넣기 위해선 byte배열로 지정해야함 (multipart x)

 

2.

getter/ setter/ toString 도 어노테이션을 이용하여 자동으로 명시되게 함

**주의: byte[]은 byte단위로 가지고 있기 때문에 가지고 있는걸 다 바이트로 변환해서 3~400개를 다 출력시킴

그래서 byte 배열은 toString시 배제하는 게 좋음 (속도 문제 발생)
--> @ToString(exclude = {"photo"})

 

3.

setPhoto(upload.getBytes());

파일처리 구문은 무조건 IOException 발생 가능성이 있기 때문에 try~catch문을 넣어줘야함

근데 이건 메서드기 때문에 throws로 처리 ==> add throws declation을 눌러서 throws를 해줌

 

 

 


 

 

 

 

dao 인터페이스 생성

kr.spring.member.dao

MemberMapper (interface)

package kr.spring.member.dao;

import org.apache.ibatis.annotations.Mapper;

import kr.spring.member.vo.MemberVO;

@Mapper
public interface MemberMapper {
	//회원관리 - 사용자
	public int selectMem_num(); //pk 구하기
	public void insertMember(MemberVO member);
	public void insertMember_detail(MemberVO member);
	public MemberVO selectCheckMember(String id);
	public MemberVO selectMember(int mem_num);//한건의 레코드 반환
	public void updateMember(MemberVO member);
	public void updateMember_detail(MemberVO member);
	public void updatePassword(MemberVO member);
	public void deleteMember(int mem_num);
	public void deleteMember_detail(int mem_num);
	
	//회원관리 - 관리자
	
}

메서드 당 1개의 sql문을 수행하기 때문에 dao interface에서 지정한 메서드를 xml에서 sql문을 넣고, 

service에서 기능 수행을 위해 한번에 묶어서 처리하는 식으로 수행함

 

 

 

 

dao xml 파일 셋팅 (interface파일과 이름 동일)

kr.spring.member.dao

MemberMapper.xml

<?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="kr.spring.member.dao.MemberMapper">
	
</mapper>

 

 

 

 

 

 

Service 인터페이스 파일 생성

kr.spring.member.service
MemberService (interface)

package kr.spring.member.service;

import kr.spring.member.vo.MemberVO;

public interface MemberService {
	//회원관리 - 사용자
	public void insertMember(MemberVO member);
	public MemberVO selectCheckMember(String id);
	public MemberVO selectMember(int mem_num);//한건의 레코드 반환
	public void updateMember(MemberVO member);
	public void updatePassword(MemberVO member);
	public void deleteMember(int mem_num);
	
	//회원관리 - 관리자
}

service 파일에서는 dao.interface에서 명시한 메서드를 묶어서 한번에 처리하기 때문에 몇가지 지웠음

insertMember -> select mem_num / insert member_detail 같이 처리
updateMember -> updateMember_detail 같이 처리
deleteMember -> deleteMember_detail 같이 처리

 

 

 

 

 

Service 구현 파일

MemberServiceImpl (class)

package kr.spring.member.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import kr.spring.member.dao.MemberMapper;
import kr.spring.member.vo.MemberVO;

@Service
@Transactional
public class MemberServiceImpl implements MemberService{
	@Autowired
	private MemberMapper memberMapper;

	@Override
	public void insertMember(MemberVO member) {
		// TODO Auto-generated method stub
	}

	@Override
	public MemberVO selectCheckMember(String id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public MemberVO selectMember(int mem_num) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void updateMember(MemberVO member) {
		// TODO Auto-generated method stub
	}

	@Override
	public void updatePassword(MemberVO member) {
		// TODO Auto-generated method stub
	}

	@Override
	public void deleteMember(int mem_num) {
		// TODO Auto-generated method stub
	}
}

<과정 정리>
1.
@Service
@Transactional

2.
@Autowired > MemberMapper

3.
implements MemberService

 

 

 

 

 

 

 

 

Controller 생성

kr.spring.member.controller
MemberController

package kr.spring.member.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;

import kr.spring.member.service.MemberService;
import kr.spring.member.vo.MemberVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class MemberController {
	@Autowired
	private MemberService memberService;
	
	/*=======================
	 * 자바빈(VO) 초기화
	 *======================= */
	@ModelAttribute
	public MemberVO initCommand() {
		return new MemberVO();
	}
	
	/*=======================
	 * 회원가입
	 *======================= */
	//회원가입 폼 호출
	@GetMapping("/member/registerUser")
	public String form() {
		return "memberRegister"; //tiles설정명 (/등의 경로가 없기 때문에 jsp가 아니라는 걸 알 수 있음)
	}
	
}

컨트롤러마다 커스텀 태그가 자바빈을 찾기 때문에 자바빈은 꼭 생성해야함 (초기화)

 

 

 


 

 

 

 

VO 생성했기 때문에 main 페이지 redirect 부분 수정

(관리자/ 일반 회원 다르게)

MainController

//초기화 (대문페이지)
@RequestMapping("/")
public String init(HttpSession session) {
    MemberVO user = (MemberVO)session.getAttribute("user");
    //관리자로 로그인하면 관리자 메인으로 이동 처리
    if(user!=null && user.getAuth() == 9) {
        return "redirect:/main/admin";
    }
    return "redirect:/main/main";
}

1.
MemberVO user = (MemberVO)session.getAttribute("user");
user라는 이름으로 memberVO 저장

 

 

 


 

 

 

 

 

<회원가입 폼 출력하기>

views
member (folder)
memberRegister.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- 내용 시작 -->
<div class="page-main">
	<h2>회원가입</h2>
	<form:form action="registerUser" id="member_register" modelAttribute="memberVO">
		<form:errors element="div" cssClass="error-color"/>
		<ul>
			<li>
				<form:label path="id">아이디</form:label>
				<form:input path="id" placeholder="영문,숫자만 4~12자" autocomplete="off"/>
				<input type="button" id="confirmId" value="ID중복체크" class="default-btn">
				<span id="message_id"></span>
				<form:errors path="id" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="name">이름</form:label>
				<form:input path="name"/>
				<form:errors path="name" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="nick_name">별명</form:label>
				<form:input path="nick_name"/>
			</li>
			<li>
				<form:label path="passwd">비밀번호</form:label>
				<form:password path="passwd"/>
				<form:errors path="passwd" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="phone">전화번호</form:label>
				<form:input path="phone"/>
				<form:errors path="phone" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="email">이메일</form:label>
				<form:input path="email"/>
				<form:errors path="email" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="zipcode">우편번호</form:label>
				<form:input path="zipcode"/>
				<form:errors path="zipcode" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="address1">주소</form:label>
				<form:input path="address1"/>
				<form:errors path="address1" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="address2">상세주소</form:label>
				<form:input path="address2"/>
				<form:errors path="address2" cssClass="error-color"/>
			</li>
		</ul>
		<div class="align-center">
			<form:button class="default-btn">전송</form:button>
			<input type="button" value="홈으로" class="default-btn" onclick="location.href='${pageContext.request.contextPath}/main/main'">
		</div>
	</form:form>
</div>
<!-- 내용 끝 -->

 

 

 

 

 

 

 

설정파일에서 페이지 레이아웃 매핑

tiles-def
member.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>
    <definition name="memberRegister" extends="main">
    	<put-attribute name="title" value="회원가입"/>
    	<put-attribute name="body" value="/WEB-INF/views/member/memberRegister.jsp"/>
    </definition>
   
</tiles-definitions>

main을 상속받고 바뀐 값 (title, body) 만 기재

 

 

 

 

자바코드 기반 설정

kr.spring.config

AppConfig.java

package kr.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
//자바코드 기반 설정 클래스
@Configuration
public class AppConfig implements WebMvcConfigurer {
	@Bean
	public TilesConfigurer tilesConfigurer() {
		final TilesConfigurer configurer = new TilesConfigurer();
		//tilesdef.xml의 경로와 파일명 지정
		configurer.setDefinitions(new String[] {"/WEB-INF/tiles-def/main.xml",
        	"/WEB-INF/tiles-def/member.xml"});
		configurer.setCheckRefresh(true);
		return configurer;
	}
	
	@Bean
	public TilesViewResolver tilesViewResolver() {
		final TilesViewResolver tilesViewResolver = new TilesViewResolver();
		
		tilesViewResolver.setViewClass(TilesView.class);
		return tilesViewResolver;
	}
}

main.xml 만 있던 definitions에 member.xml 설정파일도 추가

 

 

 

728x90
반응형