Springboot

[SpringBoot] 12.코드 정리

Song hyun 2024. 8. 6. 17:30
728x90
반응형

 

 

(1) MainController

더보기

package cohttp://m.tenco.bank.controller;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import cohttp://m.tenco.bank.handler.Exception.DataDeliveryException;
import cohttp://m.tenco.bank.handler.Exception.RedirectException;
import cohttp://m.tenco.bank.handler.Exception.UnAuthorizedException;

@Controller // IoC의 대상(싱글톤 패턴으로 관리된다.)
// IoC = inversion of controll (=제어의 역전)
public class MainController {

// REST API 기반으로 주소 설계 가능

// 주소 설계
// http://localhost:8080/main-page
@GetMapping({"/main-page", "/index"})
public String mainPage() {
System.out.println("mainPage() 호출 확인");
// [JSP 파일 찾기(yml)] - 뷰 리졸버
// prefix: /WEB-INF/view/
//         main
// suffix: .jsp

// application.yml 에서 설정한 전위, 후위연산자를 통해 더욱 간단하게 사용이 가능하다.
return "main";
}

// todo - 삭제 예정
// 주소 설계
// http://localhost:8080/error-test1/true
// http://localhost:8080/error-test1/isError
@GetMapping("/error-test1")
public String errorData1() {
System.out.println("aaaaa");
if(true) {
throw new RedirectException("잘못된 요청입니다.", HttpStatus.NOT_FOUND);
}

return "main";
}

// http://localhost:8080/error-test2
@GetMapping("/error-test2")
public String errorData2() {
System.out.println("bbbb");
if(true) {
throw new DataDeliveryException("잘못된 데이터입니다.", HttpStatus.BAD_REQUEST);

return "main";
}

// http://localhost:8080/error-test2
@GetMapping("/error-test3")
public String errorData3() {
System.out.println("cccc");
if(true) {
throw new UnAuthorizedException("인증되지 않은 사용자입니다.", HttpStatus.UNAUTHORIZED);

return "main";
}
}

(2) Test1Controller

더보기

package cohttp://m.tenco.bank.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import cohttp://m.tenco.bank.handler.Exception.UnAuthorizedException;
import cohttp://m.tenco.bank.repository.model.User;

// Controller -> String (뷰리졸버 동작 --> JSP 파일 찾아서 렌더링 처리)
// RestController --> 데이터를 반환 처리 
@RestController // Controller + REST API
public class Test1Controller {

// 주소 설계
// http://localhost:8080/test1
// @ResponseBody
@GetMapping("/test1")
public User test1() {
// Gson -> JSON 형식으로 변환 -> String 응답 처리
try {
int result=10/0;
} catch (Exception e) {
throw new UnAuthorizedException("인증이 안 된 사용자입니다.", HttpStatus.UNAUTHORIZED);
}


return User.builder().username("길동").password("asd123").build();
}
}

(3) UserController

더보기

package cohttp://m.tenco.bank.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import cohttp://m.tenco.bank.dto.SignUpDTO;
import cohttp://m.tenco.bank.handler.Exception.DataDeliveryException;
import cohttp://m.tenco.bank.repository.interfaces.UserRepository;
import cohttp://m.tenco.bank.service.UserService;

@Controller // IoC의 대상(싱글톤 패턴으로 관리된다.) 
@RequestMapping("/user") // 대문 처리
public class UserController {

private UserService userService;

// DI 처리
@Autowired // 노란색 경고는 사용할 필요 없음 - 하지만 가독성을 위해서 선언해도 ok
public UserController(UserService service) {
this.userService=service;
}


/**
 * 회원 가입 페이지 요청
 * 주소 설계 : http://localhost:8080/user/sign-up
 * @return signUp.jsp
 */
@GetMapping("/sign-up")
public String signUpPage() {
// prefix: /WEB-INF/view
// suffix: .jsp
// return: user/signUp
return "user/signUp";
}

/**
 * 회원 가입 로직 처리 요청
 * 주소 설계 : http://localhost:8080/user/sign-up
 * @param dto
 * @return
 */
@PostMapping("/sign-up")
public String signUpProc(SignUpDTO dto) {
// controller에서 일반적인 코드 작업
// 1. 인증 검사 (여기서는 인증검사 불필요!)
// 2. 유효성 검사
if(dto.getUsername()==null || dto.getUsername().isEmpty()) {
throw new DataDeliveryException("username을 입력하세요", HttpStatus.BAD_REQUEST);
}

if(dto.getPassword()==null || dto.getPassword().isEmpty()) {
throw new DataDeliveryException("password을 입력하세요", HttpStatus.BAD_REQUEST);
}

if(dto.getFullname()==null || dto.getFullname().isEmpty()) {
throw new DataDeliveryException("fullname을 입력하세요", HttpStatus.BAD_REQUEST);
}

// 서비스 객체로 전달
userService.createUser(dto);

// 추후 수정 예정
return "redirect:/index";
}
}

 

(4) SignUpDTO

더보기

package cohttp://m.tenco.bank.dto;

import cohttp://m.tenco.bank.repository.model.User;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SignUpDTO {

private String username;
private String password;
private String fullname;

// 2단계 로직 - User Object 반환
public User toUser() {
return User.builder()
.username(this.username)
.password(this.password)
.fullname(this.fullname)
.build();
}


// todo - 추후 사진 업로드 기능 추가 에정

}

 

(5) DataDeliveryException

더보기

 

package com.tenco.bank.handler.Exception;

 

import org.springframework.http.HttpStatus;

 

public class DataDeliveryException extends RuntimeException {

 

private HttpStatus status;

 

public DataDeliveryException (String message, HttpStatus status) {

super(message);

this.status=status;

}

}

(6) RedirectException

더보기

package cohttp://m.tenco.bank.handler.Exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;

@Getter
// 에러 발생 시에 여러 페이지로 이동시킬 때 사용 예정
public class RedirectException extends RuntimeException{

private HttpStatus status;

// throw new RedirectException(???,???);
public RedirectException(String message,HttpStatus status) {
super(message);
this.status=status;
}
}

(7) UnAuthorizedException

더보기

package cohttp://m.tenco.bank.handler.Exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;

@Getter
public class UnAuthorizedException extends RuntimeException{

private HttpStatus status;

// throw new UnAuthorized Exception( , )
public UnAuthorizedException(String message,HttpStatus status) {
super(message);
this.status=status;
}
}

(8) GlobalControllException

더보기

package cohttp://m.tenco.bank.handler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cohttp://m.tenco.bank.handler.Exception.DataDeliveryException;
import cohttp://m.tenco.bank.handler.Exception.RedirectException;
import cohttp://m.tenco.bank.handler.Exception.UnAuthorizedException;

@ControllerAdvice // 해당 어노테이션을 통해 IoC의 대상이 된다. (=싱글톤 패턴으로 관리된다.) 
// -> HTML 렌더링 예외에 많이 사용
public class GlobalControllException {

/**
 * (개발 시에 많이 활용)
 * 모든 예외 클래스를 알 수 없기 때문에 
 * 로깅으로 확인 할 수 있도록 설정!
 * 
 * 로깅 처리에는 동기적 방식이 있다.
 * 동기적 방식(System.out.println)
 * 비동기적 방식(@slf4j)
 */

/*
 * // @ExceptionHandler => 설정해둔 예외 발생시 해당 메서드 동작하게끔 함
 * 
 * @ExceptionHandler(Exception.class ) public void exception(Exception e) {
 * System.out.println("------------------");
 * System.out.println(e.getClass().getName());
 * System.out.println(e.getMessage()); System.out.println("------------------");
 * }
 */


/**
 * Data로 예외를 내려주는 방법
 * @ResponseBody 활용
 * 브라우저에서 자바스크립트 코드로 동작하게 된다!
 * 
 * @param e
 * @return
 */
// 예외를 내릴 때 데이터를 내리고 싶다면 1. @RestControllerAdvice를 사용하면 된다.
// 단, @ControllerAdvice를 사용하고 있다면, @ResponseBody를 붙여 사용하면 된다.
@ResponseBody
@ExceptionHandler(DataDeliveryException.class)
public String dataDeliveryException(DataDeliveryException e) {
StringBuffer sb=new StringBuffer();
sb.append(" <script>");
sb.append(" alert('"+e.getMessage()+"');");
sb.append(" window.history.back()");
sb.append(" </script>");
return sb.toString();
}


@ResponseBody
@ExceptionHandler(UnAuthorizedException.class)
public String unAuthorizedException(UnAuthorizedException e) {
StringBuffer sb=new StringBuffer();
sb.append(" <script>");
sb.append(" alert('"+e.getMessage()+"');");
sb.append(" window.history.back()");
sb.append(" </script>");
return sb.toString();
}

/**
 * 에러 페이지로 이동 처리
 * JSP로 이동시 데이터를 담아서 보내는 방법
 * ModelAndView,Model 사용 가능
 * throw new RedirectException('페이지 없음',404);
 */
@ExceptionHandler(RedirectException.class)
public ModelAndView redirectException(RedirectException e) {
ModelAndView modelAndView=new ModelAndView("errorPage"); // 전위, 후위 연산자 사용
modelAndView.addObject("statusCode",e.getStatus().value());
modelAndView.addObject("message", e.getMessage());
return modelAndView; // 페이지 반환+데이터 내려줌
}

}

 

(9) UserService

더보기

package cohttp://m.tenco.bank.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cohttp://m.tenco.bank.dto.SignUpDTO;
import cohttp://m.tenco.bank.handler.Exception.DataDeliveryException;
import cohttp://m.tenco.bank.handler.Exception.RedirectException;
import cohttp://m.tenco.bank.repository.interfaces.UserRepository;
import cohttp://m.tenco.bank.repository.model.User;

@Service // 제어의 역전(IoC)의 대상이 된다. (싱글톤으로 관리되는 객체)
public class UserService {

// DI = 의존 주입 (Dependency Injection)
@Autowired // 자동으로 객체를 반환해, 메모리에 올린다.
private UserRepository userRepository;

 @Autowired //어노테이션으로 대체 가능!
 //생성자 의존 주입 - DI (IoC와 DI는 묶음이다.)
 public UserService(UserRepository userRepository) {
this.userRepository=userRepository;
}


/**
 * 
 * 회원 등록 서비스 기능
 * 트랜잭션 처리 필수!
 * @param dto
 */
@Transactional // 트랜잭션 처리는 반드시 습관화
public void createUser(SignUpDTO dto) {
int result = 0;

try {
result = userRepository.insert(dto.toUser());
} catch (DataAccessException e) {
throw new DataDeliveryException("잘못된 처리입니다.", HttpStatus.INTERNAL_SERVER_ERROR);
} catch (Exception e) {
throw new RedirectException("알 수 없는 오류입니다.", HttpStatus.SERVICE_UNAVAILABLE);
}

if(result!=1) {
throw new DataDeliveryException("회원가입 실패", HttpStatus.INTERNAL_SERVER_ERROR);
}

}
}

 

(10) AccountRepository

더보기

package cohttp://m.tenco.bank.repository.interfaces;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import cohttp://m.tenco.bank.repository.model.Account;

// AccountRepository 인터페이스와 account.xml 파일을 매칭시킨다.
@Mapper
public interface AccountRepository {
public int insert(Account account);
public int updateById(Account account);
public int deleteById(Integer id);

// 고민! - 계좌 조회 
// -> 한 사람의 유저는 여러 개의 계좌 번호를 가질 수 있다.
// 유저:계좌 -->1:N

// 두 개 이상의 파라미터 값을 받을 경우 @Param이 필수로 쓰인다.
public List<Account> findByUserId(@Param("userId") Integer principalId);

// -> 하나의 account id 값으로 계좌 정보 조회 기능
public Account findByNumber(@Param("number") String id);
}

(11) HistoryRepository

더보기

package cohttp://m.tenco.bank.repository.interfaces;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import cohttp://m.tenco.bank.repository.model.History;

// HistoryRepository, history.xml 파일을 매칭시킨다.
@Mapper
public interface HistoryRepository {
public int insert(History history);
public int updatebyid(History history);
public int deleteById(Integer id);

// 거래 내역 조회
public History findById(Integer id);
public List<History> findAll();

// 코드 추가 예정 - 모델을 반드시 1:1 엔티티에 매핑을 시킬 필요는 없다.
// 조인 쿼리, 서브 쿼리
}

(12) UserRepository

더보기

package cohttp://m.tenco.bank.repository.interfaces;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import cohttp://m.tenco.bank.repository.model.User;

// MyBatis 설정 확인

// UserRepository 인터페이스와 user.xml 파일을 매칭시킨다.
@Mapper // 반드시 선언해야 동작한다.
public interface UserRepository {

public int insert(User user);
public int updateById(User user);
public int deleteById(Integer id);
public User findById(Integer id);
public List<User> findAll();
}

 

(13) Account

더보기

package cohttp://m.tenco.bank.repository.model;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Account {

private Integer id;
private String number;
private String password;
private Long balance;
private Integer userId;
private Timestamp createdAt;

// 출금 기능
public void withdraw(Long amount) {
// 방어적 코드 작성
this.balance-=amount;
}

// 입금 기능
public void deposit(Long amount) {
this.balance+=amount;
}

// 패스워드 체크 기능
// 잔액 여부 확인
// 세션-ID 확인 : 계좌 소유자 확인 기능

}

(14) history

더보기

package cohttp://m.tenco.bank.repository.model;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class History {
private Integer id;
private Long amount;
private Long wBalance;
private Long dBalance;
private Integer wAccountId;
private Integer dAccountId;
private Timestamp createdAt;
}

(15) User

더보기

package cohttp://m.tenco.bank.repository.model;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class User {
private Integer id;
private String username;
private String password;
private String fullname;
private Timestamp createdAt;
}

 

 

(16) UserService

더보기

package cohttp://m.tenco.bank.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cohttp://m.tenco.bank.dto.SignUpDTO;
import cohttp://m.tenco.bank.handler.Exception.DataDeliveryException;
import cohttp://m.tenco.bank.handler.Exception.RedirectException;
import cohttp://m.tenco.bank.repository.interfaces.UserRepository;
import cohttp://m.tenco.bank.repository.model.User;

@Service // 제어의 역전(IoC)의 대상이 된다. (싱글톤으로 관리되는 객체)
public class UserService {

// DI = 의존 주입 (Dependency Injection)
@Autowired // 자동으로 객체를 반환해, 메모리에 올린다.
private UserRepository userRepository;

 @Autowired //어노테이션으로 대체 가능!
 //생성자 의존 주입 - DI (IoC와 DI는 묶음이다.)
 public UserService(UserRepository userRepository) {
this.userRepository=userRepository;
}


/**
 * 
 * 회원 등록 서비스 기능
 * 트랜잭션 처리 필수!
 * @param dto
 */
@Transactional // 트랜잭션 처리는 반드시 습관화
public void createUser(SignUpDTO dto) {
int result = 0;

try {
result = userRepository.insert(dto.toUser());
} catch (DataAccessException e) {
throw new DataDeliveryException("잘못된 처리입니다.", HttpStatus.INTERNAL_SERVER_ERROR);
} catch (Exception e) {
throw new RedirectException("알 수 없는 오류입니다.", HttpStatus.SERVICE_UNAVAILABLE);
}

if(result!=1) {
throw new DataDeliveryException("회원가입 실패", HttpStatus.INTERNAL_SERVER_ERROR);
}

}
}

 

(17) data.sql

더보기

insert into user_tb(username, password, fullname, created_at)
values('길동', '1234', '고', now());

insert into user_tb(username, password, fullname, created_at)
values('둘리', '1234', '애기공룡', now());

insert into user_tb(username, password, fullname, created_at)
values('마이', '1234', '콜', now());


insert into account_tb
(number, password, balance, user_id, created_at)
values('1111', '1234', 1300, 1, now());        

insert into account_tb
(number, password, balance, user_id, created_at)
values('2222', '1234', 1100, 2, now());        

insert into account_tb
(number, password, balance, user_id, created_at)
values('3333', '1234', 0, 3, now());        


insert into history_tb(amount, w_balance, d_balance, w_account_id, d_account_id, created_at)
values(100, 900, 1100, 1, 2, now());

insert into history_tb(amount, w_balance, d_balance, w_account_id, d_account_id, created_at)
values(100, 800, null, 1, null, now());

insert into history_tb(amount, w_balance, d_balance, w_account_id, d_account_id, created_at)
values(500, null, 1300, null, 1, now());

(18) table.sql

더보기

create table user_tb(
id int auto_increment primary key, 
    username varchar(50) not null unique, 
password varchar(100) not null, 
fullname varchar(50) not null, 
    created_at timestamp not null default now()
); 

create table account_tb(
id int auto_increment primary key, 
    number varchar(30) not null unique, 
    password varchar(30) not null, 
    balance bigint not null comment '계좌잔액', 
    created_at timestamp not null default now(), 
user_id int 
);

create table history_tb(
id int auto_increment primary key comment '거래내역 ID',
amount bigint not null comment '거래금액',
    w_account_id int comment '출금 계좌 ID',
    d_account_id int comment '입금 계좌 ID',
    w_balance bigint comment '출금 요청 후 계좌 잔액',
    d_balance bigint comment '입금 요청 후 계좌 잔액', 
    created_at timestamp not null default now() 
);

 

(19) account.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="com.tenco.bank.repository.interfaces.AccountRepository">

 

<!-- 반드시! 세미콜론을 제거해야 한다. -->

<!-- User-insert() 기능 구현하기 -->

<!-- id는 매칭되어있는 인터페이스의 메서드 명과 같아야 한다. -->

<insert id="insert">

insert into account_tb(number, password,balance,user_id,created_at)

values ( #{number}, #{password}, #{balance}, #{userId}, now() )

</insert>

 

 

<update id="updateById">

update account_tb set password = #{password},

balance = #{balance},

user_id = #{userId},

created_a = #{createdAt}

</update>

 

 

<delete id="deleteById">

delete account_tb where id = #{id}

</delete>

 

 

<select id="findByUserId" resultType="com.tenco.bank.repository.model.Account">

select account_tb where user_id = #{userId}

</select>

 

 

<select id="findByNumber" resultType="com.tenco.bank.repository.model.Account">

select account_tb where number = #{number}

</select>

 

</mapper>

(20) history.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="com.tenco.bank.repository.interfaces.HistoryRepository">

 

<insert id="insert">

insert into history_tb(amount, w_account_id, d_account_id,w_balance,d_balance)

values(#{amount}, #{wAccountId}, #{dAccountId}, #{wBalance}, #{dBalance})

</insert>

 

 

<update id="updatebyid">

update history_tb set amount = #{amount},

w_account_id = #{wAccountId},

d_account_id = #{dAccountId},

w_balance = #{wBalance},

d_balance = #{dBalance}

where id = #{id}

</update>

 

 

<delete id="deleteById">

delete history_tb where id = #{id}

</delete>

 

 

<select id="findById" resultType="com.tenco.bank.repository.model.History">

select * from history_tb where id = #{id}

</select>

 

 

<select id="findAll" resultType="com.tenco.bank.repository.model.History">

select * from history_tb

</select>

 

 

</mapper>

(21) user.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="com.tenco.bank.repository.interfaces.UserRepository">

 

<!-- 반드시! 세미콜론을 제거해야 한다. -->

<!-- User-insert() 기능 구현하기 -->

<!-- id는 매칭되어있는 인터페이스의 메서드 명과 같아야 한다. -->

<insert id="insert">

insert into user_tb(username, password, fullname)

values( #{username}, #{password}, #{fullname})

</insert>

 

 

<update id="updateById">

update user_tb set username = #{username},

password = #{password},

fullname = #{fullname}

where id = #{id}

</update>

 

 

<delete id="deleteById">

delete from user_tb where id = #{id}

</delete>

 

 

<select id="findById" resultType="com.tenco.bank.repository.model.User">

select * from user_tb where id = #{id}

</select>

 

 

<select id="findAll" resultType="com.tenco.bank.repository.model.User">

select * from user_tb

</select>

 

 

</mapper>

 

(22) common.css

더보기

@charset "UTF-8";

 

body{

height: 100vh;

margin: 0;

}

.m--flex-container {

display: flex;

flex-direction: column;

height: 100%;

}

.m--container {

flex: 1;

}

.m--banner-imgs {

background-image: url(https://picsum.photos/600);

width: 100%;

background-size: cover;

background-position: center;

}

 

.m--profile {

background-image: url(https://picsum.photos/id/1/350);

width: 100%;

height: 200px;

background-size: cover;

background-position: center;

}

(23) index.html

더보기

<!DOCTYPE html>

<html lang="en">

<head>

<title>Bootstrap 4 Website Example</title>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="css/common.css">

<link rel="stylesheet"

href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">

<script

src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js"></script>

<script

src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>

<script

src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>

<style>

 

</style>

</head>

<body>

<div class="m--flex-container">

<div class="m--container">

<div class="jumbotron text-center" style="margin-bottom: 0">

<h1>My First Bootstrap 4 Page</h1>

<p>Resize this responsive page to see the effect!</p>

</div>

 

<nav class="navbar navbar-expand-sm bg-dark navbar-dark">

<a class="navbar-brand" href="#">Navbar</a>

<button class="navbar-toggler" type="button" data-toggle="collapse"

data-target="#collapsibleNavbar">

<span class="navbar-toggler-icon"></span>

</button>

<div class="collapse navbar-collapse" id="collapsibleNavbar">

<ul class="navbar-nav">

<li class="nav-item"><a class="nav-link" href="#">Link</a></li>

<li class="nav-item"><a class="nav-link" href="#">Link</a></li>

<li class="nav-item"><a class="nav-link" href="#">Link</a></li>

</ul>

</div>

</nav>

 

<div class="container" style="margin-top: 30px">

<div class="row">

<div class="col-sm-4"></div>

<div class="col-sm-8">

<h2>TITLE HEADING</h2>

 

</div>

</div>

</div>

</div>

<div class="jumbotron text-center" style="margin-bottom: 0">

<p>Footer</p>

</div>

</div>

</body>

</html>

 

(24) footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!-- START OF FOOTER.JSP -->
		<div class="jumbotron text-center" style="margin-bottom: 0">
			<p>Footer</p>
		</div>

  </div>
  </div>
</body>
</html>
<!-- END OF FOOTER.JSP -->

(25) header.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<title>myBank</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/common.css">
<link rel="stylesheet"
	href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script
	src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js"></script>
<script
	src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script
	src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>


	<div class="m--flex-container">
		<div class="m--container">

			<div class="jumbotron text-center m--banner-imgs"
				style="margin-bottom: 0">
				<h1>My Bank</h1>
				<p>MyBatis를 활용한 Springboot 앱 만들어보기</p>
	</div>
	<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
		<a class="navbar-brand" href="#">Navbar</a>
		<button class="navbar-toggler" type="button" data-toggle="collapse"
			data-target="#collapsibleNavbar">
			<span class="navbar-toggler-icon"></span>
		</button>
		<div class="collapse navbar-collapse" id="collapsibleNavbar">
			<ul class="navbar-nav">
				<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
				<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
				<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
			</ul>
		</div>
	</nav>

	<div class="container" style="margin-top: 30px">
		<div class="row">
			<div class="col-sm-4">
				<h2>About Me</h2>
				<h5>Photo of me:</h5>
				<div class="m--profile"></div>
				<p>코린이 개발을 위한 뱅크 앱</p>
				<h3>Some Links</h3>
				<p>Lorem ipsum dolor sit ame.</p>
				<ul class="nav nav-pills flex-column">
					<li class="nav-item"><a class="nav-link active" href="#">Active</a>
					</li>
					<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
					<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
					<li class="nav-item"><a class="nav-link disabled" href="#">Disabled</a>
					</li>
				</ul>
				<hr class="d-sm-none">
			</div>
			<!-- END OF HEADER.JSP -->

 

(26) signUp.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>회원가입 페이지</h1>
</body>
</html>

(27) errorPage.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${statusCode} Error - Page not Found</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<style type="text/css">
	body{
		display:flex;
		justify-content: center;
		align-items: center;
		height: 100vh;
	}
	.error--message{
		text-align: center;
		margin-bottom: 20px;
	}
</style>
</head>
<body>
	<div class="container">
		<div class="text-center">
			<h1>${statusCode}</h1>
			<p class="error-message">Page Not Found</p>
			<p>${message}</p>
			<a href="/index" class="btn btn-primary">Go To Home Page</a>
		</div>
	</div>
	
</body>
</html>

(28) main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
       <!-- header.jsp -->
    <%@ include file="/WEB-INF/view/layout/header.jsp" %>

    <!-- START OF CONTENT.JSP(XXX.JSP) -->
    <div class="col-sm-8">
      <h2>TITLE HEADING</h2>
      <h5>Title description, Dec 7, 2017</h5>
      <div class="fakeimg">Fake Image</div>
      <p>Some text..</p>
      <p>Sunt in culpa qui officia deserunt mollit anim id est laborum consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
      <br>
      <h2>TITLE HEADING</h2>
      <h5>Title description, Sep 2, 2017</h5>
      <div class="fakeimg">Fake Image</div>
      <p>Some text..</p>
      <p>Sunt in culpa qui officia deserunt mollit anim id est laborum consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
    </div>
  </div>
</div>
<!-- END OF CONTENT.JSP(XXX.JSP) -->

<!-- footer.jsp -->
    <%@ include file="/WEB-INF/view/layout/footer.jsp" %>
728x90
반응형