@PatchMapping("/{email}")
public Customer updateCustomer(@PathVariable String email, @RequestBody Customer customer) {
Customer existCustomer = customerRepository.findByEmail(email)
.orElseThrow(() -> new BusinessException("Email이 존재하지 않습니다", HttpStatus.NOT_FOUND));
if (customer.getName() != null)
existCustomer.setName(customer.getName());
if (customer.getAge() != 0)
existCustomer.setAge(customer.getAge());
return customerRepository.save(existCustomer);
}
customer
id - auto increment
name
email - unique
age
entryDate (DB에서 날짜를 어떻게 insert 하는지 확인)
create table customer(
id int(10) not null auto_increment primary key,
name varchar(100) not null,
email varchar(100) not null,
age int(10),
entryDate date,
UNIQUE KEY uk_name (email)
);
alter table customer add unique(id);
insert into customer(name, email, age, entryDate) values ('gildong', 'gildong@naver.com', 20, '2023-10-01');
insert into customer(name, email, age, entryDate) values ('dooly', 'dooly@google.com', 25, '2023-10-05');
insert into customer(name, email, age, entryDate) values ('huidong', 'huidong@google.com', 18, '2023-09-05');
insert into customer(name, email, age, entryDate) values ('micole', 'micole@naver.com', 28, '2022-10-10');
insert into customer(name, email, age, entryDate) values ('ddochi', 'ddochi@google.com', 20, '2023-05-05');
commit;
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.maven.spring</groupId>
<artifactId>MySpringFW</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>CustomerSpringWeb Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.2.25.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
<!-- scope : test라고 이름 지어진 폴더에만 적용 -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Hikari Connection Pooling -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<finalName>MySpringFW</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven
defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
spring-bean-customer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Properties file 정보 설정 -->
<context:property-placeholder location="classpath:value.properties"/>
<!-- DataSource 구현체인 HikariDataSource를 SpringBean으로 등록 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
p:driverClassName="${db.driverClass}"
p:jdbcUrl="${db.url}"
p:username="${db.username}"
p:password="${db.password}"
/>
</beans>
value.properties
db.driverClass=org.mariadb.jdbc.Driver
db.url=jdbc:mariadb://127.0.0.1:3306/boot_db?useUnicode=true&charaterEncoding=utf-8&useSSL=false&serverTimezone=UTC
db.username=boot
db.password=boot
myname=Spring
myprinter=printer
value1=JUnit
value2=AOP
value3=DI
printer1=stringPrinter
printer2=consolePrinter
CustomerDBTest.java
package myspring.customer;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring-beans-customer.xml")
public class CustomerDBTest {
@Autowired
DataSource dataSource;
@Test
public void conn() {
try {
Connection connection = dataSource.getConnection();
DatabaseMetaData metaData = connection.getMetaData();
System.out.println("DB Product Name : " + metaData.getDatabaseProductName()); //MariaDB
System.out.println("DB Driver : " + metaData.getDriverName()); // MariaDB Connector/J
System.out.println("DB URL : " + metaData.getURL()); // jdbc:mariadb://127.0.0.1/boot_db?user=boot&password=***&...
System.out.println("DB Username : " + metaData.getUserName()); // boot
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
CustomerVO.java
package myspring.customer.vo;
public class CustomerVO {
private Long id;
private String name;
private String email;
private int age;
private String entryDate;
// 기본생성자
public CustomerVO() {}
public CustomerVO(String name, String email, int age, String entryDate) {
this.name = name;
this.email = email;
this.age = age;
this.entryDate = entryDate;
}
// getter와 setter 생성
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEntryDate() {
return entryDate;
}
public void setEntryDate(String entryDate) {
this.entryDate = entryDate;
}
// toString 생성
@Override
public String toString() {
return "CustomerVO [id=" + id + ", name=" + name + ", email=" + email + ", age=" + age + ", entryDate="
+ entryDate + "]";
}
}
sqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- log4j2 설정 -->
<settings>
<setting name="defaultStatementTimeout" value="3"/>
<setting name="logImpl" value="LOG4J2"/>
</settings>
<typeAliases>
<!-- CustomerVO 설정 -->
<typeAlias alias="Customer" type="myspring.customer.vo.CustomerVO" />
</typeAliases>
</configuration>
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<File name="File" fileName="./logs/logfile.log" append="true">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-5level %logger{36} - %msg%n" />
</File>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="org.springframework" level="INFO" additivity="false" />
<Logger name="myspring" level="DEBUG" />
<Root level="DEBUG">
<AppenderRef ref="console" level="DEBUG" />
<AppenderRef ref="File" level="DEBUG" />
</Root>
</Loggers>
</Configuration>
selectCustomerById
select 쿼리문 생성selectCustomerList
select 쿼리문 생성<?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="customerNS">
<!-- 조회 쿼리는 id를 이용하여 실행 -->
<!-- parameter에 들어가는 값이 {value} 변수로 들어옴 -->
<select id="selectCustomerById" parameterType="string" resultType="Customer">
select * from customer where name=#{value}
</select>
<select id="selectCustomerList" resultType="Customer">
select * from customer order by id
</select>
</mapper>
sqlsessionfactory
setDataSource()
메서드의 인자로 hikaridatasource 들어옴setConfigLocation()
으로 MyBatisConfig(sqlMapConfig) 파일 연결setMapperLocations()
mapping (*Mapper) 파일 연결sqlsession
spring-beans-customer.xml
// 하단에 추가
<!-- Mybatis-spring의 SqlSessionFactoryBean을 SpringBean으로 등록 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
<property name="mapperLocations">
<list>
<value>classpath:mybatis/*Mapper.xml</value>
</list>
</property>
</bean>
<!-- SqlSessionTemplate -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
CustomerDBTest.java
package myspring.customer;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.customer.vo.CustomerVO;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring-beans-customer.xml")
public class CustomerDBTest {
@Autowired
SqlSession sqlSession;
@Test
public void session() {
CustomerVO customer = sqlSession.selectOne("customerNS.selectCustomerById", "dooly");
System.out.println(customer);
}
}
// CustomerMapper.xml
<mapper namespace="customerNS">
// CustomerDBTest.java
@Test
public void session() {
CustomerVO customer = sqlSession.selectOne("customerNS.selectCustomerById", "dooly");
System.out.println(customer);
}
CustomerMapper.java
package myspring.customer.dao.mapper;
import java.util.List;
import myspring.customer.vo.CustomerVO;
public interface CustomerMapper {
CustomerVO selectCustomerById(String id);
List<CustomerVO> selectCustomerList();
}
CustomerMapper.xml
// 변경 <mapper namespace="customerNS"> -> <mapper namespace="myspring.customer.dao.mapper.CustomerMapper">
<?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="myspring.customer.dao.mapper.CustomerMapper">
<!-- 조회 쿼리는 id를 이용하여 실행 -->
<!-- parameter에 들어가는 값이 {value} 변수로 들어옴 -->
<select id="selectCustomerById" parameterType="string" resultType="Customer">
select * from customer where name=#{value}
</select>
<select id="selectCustomerList" resultType="Customer">
select * from customer order by id
</select>
</mapper>
spring-beans-customer.xml
// 하단에 추가
<!-- Mybatis-Spring의 MapperScannerConfigurer을 SpringBean으로 등록 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 참조하는 것 없어서 bean id 없어도 됨 -->
<property name="basePackage" value="myspring.customer.dao.mapper" />
<property name="sqlSessionTemplateBeanName" value="sqlSession"/>
</bean>
CustomerDBTest.java
package myspring.customer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.customer.dao.mapper.CustomerMapper;
import myspring.customer.vo.CustomerVO;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring-beans-customer.xml")
public class CustomerDBTest {
@Autowired
CustomerMapper customerMapper;
@Test
public void mapper() {
// id가 메서드 이름이 되어 argument 전달
CustomerVO customer = customerMapper.selectCustomerById("dooly");
System.out.println(customer);
}
}
CustomerDao.java
package myspring.customer.dao;
import java.util.List;
import myspring.customer.vo.CustomerVO;
public interface CustomerDAO {
public List<CustomerVO> readAll();
public CustomerVO read(String id);
}
CustomerDaoImpl.java
package myspring.customer.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import myspring.customer.dao.mapper.CustomerMapper;
import myspring.customer.vo.CustomerVO;
@Repository("customerDao")
public class CustomerDaoImpl implements CustomerDao {
@Autowired
private CustomerMapper customerMapper;
@Override
public CustomerVO read(String id) {
CustomerVO user = customerMapper.selectCustomerById(id);
return user;
}
public List<CustomerVO> readAll() {
List<CustomerVO> userList = customerMapper.selectCustomerList();
return userList;
}
}
CustomerService.java
package myspring.customer.sevice;
import java.util.List;
import myspring.customer.vo.CustomerVO;
public interface CustomerService {
public List<CustomerVO> getCustomerList();
public CustomerVO getUser(String id);
}
CustomerServiceImpl.java
package myspring.customer.sevice;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import myspring.customer.dao.CustomerDao;
import myspring.customer.vo.CustomerVO;
@Service("customerService")
public class CustomerServiceImpl implements CustomerService {
@Autowired
CustomerDao customerdao;
public List<CustomerVO> getCustomerList() {
return customerdao.readAll();
}
@Override
public CustomerVO getUser(String id) {
return customerdao.read(id);
}
}
spring-beans-customer.xml
// 하단에 추가
<!-- DAO, Service에 해당하는 Bean을 Scanning -->
<context:component-scan base-package="myspring.customer" >
<!-- 하단의 myspring.customer에서 controller만 제외하고 scan -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
CustomerDBTest.java
package myspring.customer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.customer.dao.mapper.CustomerMapper;
import myspring.customer.sevice.CustomerService;
import myspring.customer.vo.CustomerVO;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring-beans-customer.xml")
public class CustomerDBTest {
@Autowired
CustomerService customerService;
@Test
public void service() {
CustomerVO customer = customerService.getUser("dooly");
System.out.println(customer);
}
}
contextLoadListener 추가
dispatcherservlet 추가
src/main/webapp/WEB-INF의 web.xml 수정
// 하단에 코드 추가
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-beans-customer.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-beans-customer.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>customer list</title>
</head>
<body>
<h1>고객 관리 메인</h1>
<ul>
<li><a href="customerList.do">Customer 리스트</a></li>
</ul>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>고객 상세정보</title>
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="text-center">고객 상세정보</h2>
<table class="table table-bordered table table-hover">
<tr><td>이름 :</td><td>${customer.name}</td></tr>
<tr><td>이메일 :</td><td>${customer.email}</td></tr>
<tr><td>나이 :</td><td>${customer.age}</td></tr>
<tr><td>등록일자 : </td><td>${customer.entryDate}</td></tr>
</table>
</div>
</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"%>
<html>
<head>
<title>고객 관리</title>
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="text-center">고객 목록</h2>
<table class="table table-bordered table table-hover">
<thead>
<tr>
<th> </th>
<th>이름</th>
<th>이메일</th>
<th>나이</th>
<th>등록일자</th>
<th> </th>
</tr>
</thead>
<tbody>
<c:forEach var="customer" items="${customerList}">
<tr>
<td>
<a href="getUser.do?id=${customer.name}">${customer.name}</a>
</td>
<td>${customer.name}</td>
<td>${customer.email}</td>
<td>${customer.age}</td>
<td>${customer.entryDate}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</body>
</html>
CustomerController.java
package myspring.customer.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import myspring.customer.sevice.CustomerService;
import myspring.customer.vo.CustomerVO;
@Controller
public class CustomerController {
@Autowired
private CustomerService customerService;
public CustomerController() {
System.out.println(this.getClass().getName() + "생성자 호출됨");
}
// db에서 가져오고 화면에 보이는 것도 함께 설정
// View와 Model을 한꺼번에 전달하는 방법
@RequestMapping("/customerList.do")
public ModelAndView customerList() {
// service 불러와서 리스트로 받기
// 뿌려줄 jsp 페이지를 ModelAndView 객체에 담음 (viewName=jsp파일 이름(jsp확장자 없이 이름만 기재), modelName=키값(forEach구문의 items), modelList=서비스에서 받아온 list 기재)
// key 값(customerList)과 일치하여 list 변수명 바꾸기
List<CustomerVO> customerVOList = customerService.getCustomerList();
// ModelAndView(viewName, keyName, valueObject)
return new ModelAndView("customerList", "customerList", customerVOList);
}
//getUser.do?id=dooly
// View와 Model을 분리해서 전달하는 방법
@RequestMapping("/getUser.do")
public String getUser(@RequestParam("id") String userId, Model model) {
// @requestparam을 이용하여 ?(쿼리 스트링) 다음의 id 값 가져올 수 있음
// 받아온 customerVO를 model에 담아줌
CustomerVO userVO = customerService.getUser(userId);
model.addAttribute("customer", userVO);
// 페이지 이름 return
return "customerInfo";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:component-scan base-package="myspring.customer">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- Spring MVC에 필요한 Bean들을 자동으로 등록해주는 태그-->
<mvc:annotation-driven />
<!-- DispatcherServlet의 변경된 url-pattern 때문에 필요한 태그 설정 -->
<mvc:default-servlet-handler/>
<!-- 아래 주석은 Controller에서 포워딩 되는 .jsp 확장자를 생략할 수 있다. -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- annotation-driven 태그에서 내부적으로 처리해주는 설정 -->
<!-- <bean id="jsonHttpMessageConverter" -->
<!-- class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> -->
<!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> -->
<!-- <property name="messageConverters"> -->
<!-- <list> -->
<!-- <ref bean="jsonHttpMessageConverter"/> -->
<!-- </list> -->
<!-- </property> -->
<!-- </bean> -->
</beans>
// 하단에 추가
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBConn {
public static void main(String[] args) {
final String driver = "org.mariadb.jdbc.Driver";
final String DB_IP = "localhost";
final String DB_PORT = "3306";
final String DB_NAME = "boot_db";
final String DB_URL =
"jdbc:mariadb://" + DB_IP + ":" + DB_PORT + "/" + DB_NAME;
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 1. Driver class Loading
Class.forName(driver);
System.out.println("DB_URL = " + DB_URL);
// 2. DB와 연결을 담당하는 Connection 객체 생성
conn = DriverManager.getConnection(DB_URL, "boot", "boot");
System.out.println("Connection className = " + conn.getClass().getName());
// Connection className = org.mariadb.jdbc.MariaDbConnection
if (conn != null) {
System.out.println("DB 접속 성공");
}
} catch (ClassNotFoundException e) { // class 예외 처리
System.out.println("드라이버 로드 실패");
e.printStackTrace();
} catch (SQLException e) { // getConnection 예외 처리
System.out.println("DB 접속 실패");
e.printStackTrace();
}
try {
String sql = "select * from users where userId = ?";
// 3. SQL문을 DB에게 전달해주는 역할을 하는 Statement 생성
pstmt = conn.prepareStatement(sql);
System.out.println("Statement Class Name = " + pstmt.getClass().getName());
// Statement Class Name = org.mariadb.jdbc.ClientSidePreparedStatement
pstmt.setString(1, "dooly"); // parameter index 1부터 시작, preapareStatement의 set변수타입 설정
// 4. SQL문 실행결과를 담는 역할을 하는 ResultSet 생성
rs = pstmt.executeQuery();
System.out.println("ResultSet Class Name = " + rs.getClass().getName());
// ResultSet Class Name = org.mariadb.jdbc.internal.com.read.resultset.SelectResultSet
String userId = null;
String name = null;
String gender = null;
String city = null;
while (rs.next()) { // 메모리의 ResultSet 접근 (다 읽으면 true -> false 출력 )
userId = rs.getString("userId"); // 컬럼명 변경 (컬럼 index도 가능)
name = rs.getString("name"); // getString : 해당 컬럼의 값 가져오기
gender = rs.getString("gender");
city = rs.getString("city");
System.out.print(userId);
System.out.print(name);
System.out.print(gender);
System.out.print(city);
System.out.println();
}
} catch (SQLException e) {
System.out.println("error: " + e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
package vo;
public class UserVO {
private int id;
private String UserId;
private String name;
private String gender;
private String city;
public UserVO() { // 기본 생성자
}
public UserVO(int id, String userId, String name, String gender, String city) { // argument 인자 받는 생성자
super();
this.id = id;
UserId = userId;
this.name = name;
this.gender = gender;
this.city = city;
}
public int getId() {
return id;
}
public String getUserId() {
return UserId;
}
public String getName() {
return name;
}
public String getGender() {
return gender;
}
public String getCity() {
return city;
}
@Override
public String toString() {
return "UserVO [id=" + id + ", UserId=" + UserId + ", name=" + name + ", gender=" + gender + ", city=" + city
+ "]";
}
}
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import vo.UserVO;
public class UserDAO {
private Connection connection;
public UserDAO(String driverClass, String url, String username, String password) {
// 1. Driver class Loading (1번만 실행 필요)
try {
Class.forName(driverClass);
// 2. DB와 연결을 담당하는 Connection 객체 생성
connection = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
}
public void connectionClose() { // // connection은 close 필요
try {
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// where 조건 조회
public UserVO getUser(String userId) {
PreparedStatement pStmt = null;
UserVO userVO = null;
String sql = "select * from users where userid = ?";
// 3. SQL문을 DB에게 전달해주는 역할을 하는 Statement 생성
try {
pStmt = connection.prepareStatement(sql);
pStmt.setString(1, userId);
ResultSet rs = pStmt.executeQuery();
if (rs.next()) {
userVO = new UserVO(rs.getInt("id"),
rs.getString("userId"),
rs.getString("name"),
rs.getString("gender"),
rs.getString("city"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (pStmt != null) pStmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return userVO;
}
// 목록 조회
public List<UserVO> getUserList() {
PreparedStatement pStmt = null;
List<UserVO> userList = new ArrayList<>();
String sql = "select * from users order by id";
try {
pStmt = connection.prepareStatement(sql);
ResultSet rs = pStmt.executeQuery();
while (rs.next()) {
UserVO userVO = new UserVO(rs.getInt("id"),
rs.getString("userId"),
rs.getString("name"),
rs.getString("gender"),
rs.getString("city"));
userList.add(userVO);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (pStmt != null) pStmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return userList;
}
}
package controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.UserDAO;
import vo.UserVO;
/**
* Servlet implementation class UserListServlet
*/
// @WebServlet("/userList")
public class UserListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
UserDAO userDao;
/**
* @see HttpServlet#HttpServlet()
*/
public UserListServlet() {
super();
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println(">> init");
String driver = config.getInitParameter("driverClass"); // org.mariadb.jdbc.Driver (web.xml의 param.value)
String url = config.getInitParameter("dbUrl");
String username = config.getInitParameter("dbUsername");
String password = config.getInitParameter("dbPassword");
System.out.println(driver);
System.out.println(url);
System.out.println(username);
System.out.println(password);
userDao = new UserDAO(driver, url, username, password);
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(">> doGet");
// response(응답) 데이터를 utf-8로 인코딩
response.setContentType("text/html; charset=UTF-8");
// response.getWriter() : 응답에 대한 string 생성
response.getWriter().append("Served at: ").append(request.getContextPath());
// UserDAO를 호출해서 DB 데이터를 가져오기
List<UserVO> userList = userDao.getUserList();
// Request 객체에 userList를 저장하기
request.setAttribute("users", userList); // key : users, value : userList
// RequestDispatcher 생성하기
RequestDispatcher dispatcher = request.getRequestDispatcher("userList.jsp"); //userList.jsp 포워딩 필요
// userList.jsp 페이지로 포워딩하기
dispatcher.forward(request, response); // 전달 받은 인자값 그대로 forward
}
@Override
public void destroy() {
System.out.println(">> destroy");
super.destroy();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>MyDynamicWe</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>UserListServlet</servlet-name>
<servlet-class>controller.UserListServlet</servlet-class>
<init-param>
<param-name>driverClass</param-name>
<param-value>org.mariadb.jdbc.Driver</param-value>
</init-param>
<init-param>
<param-name>dbUrl</param-name>
<param-value>jdbc:mariadb://localhost:3306/boot_db</param-value>
</init-param>
<init-param>
<param-name>dbUsername</param-name>
<param-value>boot</param-value>
</init-param>
<init-param>
<param-name>dbPassword</param-name>
<param-value>boot</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>UserListServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Main Page</title>
</head>
<body>
<h1>사용자 관리</h1>
<ul>
<li><a href="userList.do" >사용자 목록</a></li>
</ul>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>사용자 리스트</h2>
<%-- ${users} --%>
<table border="1">
<tr>
<th>ID</th>
<th>UserId</th>
<th>Name</th>
<th>Gender</th>
<th>City</th>
</tr>
<c:forEach var="user" items="${users}">
<%-- user는 UserVO를 의미 --%>
<tr>
<td>${user.id}</td>
<td>${user.userId}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.city}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="userDaoImpl" class="myspring.di.strategy1.dao.UserDaoImpl"></bean>
<bean id="userServiceImpl" class="myspring.di.strategy1.service.UserServiceImpl">
<property name="userdao" ref="userDaoImpl"></property>
</bean>
</beans>
package myspring.di.strategy1;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import myspring.di.strategy1.dao.UserDao;
import myspring.di.strategy1.service.UserService;
public class UserServiceTest {
BeanFactory factory;
@BeforeEach
void conn() {
factory = new GenericXmlApplicationContext("classpath:service-beans-strategy1.xml");
}
@Test
public void serviceTest() {
UserDao userDao = factory.getBean("userDaoImpl",UserDao.class);
UserService userService = factory.getBean("userServiceImpl",UserService.class);
assertEquals(2, userService.getUserList().size());
}
}
package myspring.di.strategy1;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.GenericXmlApplicationContext;
import myspring.di.strategy1.dao.UserDao;
import myspring.di.strategy1.service.UserService;
public class UserXmlTest {
@Test
void user() {
BeanFactory factory = new GenericXmlApplicationContext("classpath:spring-bean-configuration.xml");
UserService service = factory.getBean("userService", UserService.class);
System.out.println("get User List = " + service.getUserList());
assertEquals("dooly", service.getUser(1).getUserId());
UserDao dao = factory.getBean("userDao", UserDao.class);
System.out.println("read All = " + dao.readAll());
assertEquals("dooly", dao.read(1).getUserId());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="myspring.di.strategy2"></context:component-scan>
</beans>
package myspring.di.strategy2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.di.strategy2.service.UserService;
import myspring.di.strategy2.dao.UserDao;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "file:src/main/resources/service-beans-strategy2.xml")
public class UserServiceTest {
@Autowired
UserService userService;
@Autowired
UserDao userDao;
@Test
public void serviceTest() {
assertEquals(2, userService.getUserList().size());
}
}
package myspring.di.strategy2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.di.strategy2.dao.UserDao;
import myspring.di.strategy2.service.UserService;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "classpath:spring-bean-configuration2.xml")
public class UserXmlTest {
@Autowired
@Qualifier("userService")
UserService service;
@Autowired
@Qualifier("userDao")
UserDao dao;
@Test
void user() {
System.out.println("get User List = " + service.getUserList());
assertEquals("dooly", service.getUser(1).getUserId());
System.out.println("read All = " + dao.readAll());
assertEquals("dooly", dao.read(1).getUserId());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="userDao" class="myspring.di.strategy1.dao.UserDaoImpl" />
<bean id="userService" class="myspring.di.strategy1.service.UserServiceImpl" >
<!-- property는 setter -->
<property name="userDao" ref="userDao"/>
</bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="userDao" class="myspring.di.strategy1.dao.UserDaoImpl" />
<bean id="userService" class="myspring.di.strategy1.service.UserServiceImpl" >
<!-- property는 setter -->
<property name="userDao" ref="userDao"/>
</bean>
</beans>
package myspring.di.strategy3;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"myspring.di.strategy3"})
public class SpringBeanConfiguration {
}
package myspring.di.strategy3.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import myspring.di.strategy1.dao.UserDao;
import myspring.di.strategy1.dao.UserDaoImpl;
import myspring.di.strategy1.service.UserService;
import myspring.di.strategy1.service.UserServiceImpl;
@Configuration
public class ServiceBeanConfig {
@Bean
UserDao userDao() {
return new UserDaoImpl();
}
@Bean
UserService userService() {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserdao(userDao());
return userService;
}
}
package myspring.di.strategy3.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"myspring.di.strategy2"})
public class ServiceConfig {
}
package myspring.di.strategy3;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.di.strategy2.service.UserService;
import myspring.di.strategy2.dao.UserDao;
import myspring.di.strategy3.config.ServiceConfig;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ServiceConfig.class)
public class UserServiceTest {
@Autowired
UserService userService;
@Autowired
UserDao userDao;
@Test
public void serviceTest() {
assertEquals(2, userService.getUserList().size());
}
}
package myspring.di.strategy3;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import myspring.di.strategy3.dao.UserDao;
import myspring.di.strategy3.service.UserService;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = SpringBeanConfiguration.class, loader = AnnotationConfigContextLoader.class)
public class UserXmlTest {
@Autowired
UserService service;
@Autowired
UserDao dao;
@Test
void user() {
System.out.println("get User List = " + service.getUserList());
assertEquals("dooly", service.getUser(1).getUserId());
System.out.println("read All = " + dao.readAll());
assertEquals("dooly", dao.read(1).getUserId());
}
}
package myspring.di.strategy3;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import myspring.di.strategy1.dao.UserDao;
import myspring.di.strategy1.service.UserService;
import myspring.di.strategy3.config.ServiceBeanConfig;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ServiceBeanConfig.class)
public class UserServiceBeanTest {
@Autowired
UserService userService;
@Autowired
UserDao userDao;
@Test
public void serviceTest() {
assertEquals(2, userService.getUserList().size());
}
}
package myspring.di.strategy*.dao;
import java.util.List;
import myspring.user.vo.UserVO;
public interface UserDao {
public List<UserVO> readAll();
public UserVO read(int id);
}
package myspring.di.strategy*.dao;
import java.util.Arrays;
import java.util.List;
import myspring.user.vo.UserVO;
@Component("userDao")
public class UserDaoImpl implements UserDao {
List<UserVO> userList;
public UserDaoImpl() {
userList = Arrays.asList(
new UserVO(1L,"gildong", "홍길동", "남", "마곡"),
new UserVO(2L,"dooly", "둘리", "남", "마곡나루"));
}
@Override
public UserVO read(int index) {
return userList.get(index);
}
@Override
public List<UserVO> readAll() {
return userList;
}
}
package myspring.di.strategy*.service;
import java.util.List;
import myspring.user.vo.UserVO;
public interface UserService {
public List<UserVO> getUserList();
public UserVO getUser(int index);
}
package myspring.di.strategy*.service;
import java.util.List;
import myspring.di.strategy1.dao.UserDao;
import myspring.user.vo.UserVO;
@Component("userService")
public class UserServiceImpl implements UserService {
UserDao userdao;
public void setUserdao(UserDao userdao) {
this.userdao = userdao;
}
public List<UserVO> getUserList() {
return userdao.readAll();
}
@Override
public UserVO getUser(int index) {
return userdao.read(index);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Properties file 정보 설정 -->
<context:property-placeholder location="classpath:value.properties"/>
<!-- DataSource 구현체인 HikariDataSource를 SpringBean으로 등록 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
p:driverClassName="${db.driverClass}"
p:jdbcUrl="${db.url}"
p:username="${db.username}"
p:password="${db.password}"
/>
<!-- Mybatis-spring의 SqlSessionFactoryBean을 SpringBean으로 등록 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
<property name="mapperLocations">
<list>
<value>classpath:mybatis/*Mapper.xml</value>
</list>
</property>
</bean>
<!-- SqlSession으로 sql 실행 -->
<!-- SqlSessionFactory를 통해 취득한 SqlSession을 실행중인 트랜잭션에 할당함 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
<!-- Mybatis-Spring의 MapperScannerConfigurer을 SpringBean으로 등록 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 참조하는 것 없어서 bean id 없어도 됨 -->
<property name="basePackage" value="myspring.customer.dao.mapper" />
<property name="sqlSessionTemplateBeanName" value="sqlSession"/>
</bean>
<!-- DAO, Service에 해당하는 Bean을 Scanning -->
<context:component-scan base-package="myspring.customer" >
<!-- 하단의 myspring.customer에서 controller만 제외하고 scan -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
db.driverClass=org.mariadb.jdbc.Driver
db.url=jdbc:mariadb://127.0.0.1:3306/boot_db?useUnicode=true&charaterEncoding=utf-8&useSSL=false&serverTimezone=UTC
db.username=boot
db.password=boot
myname=Spring
myprinter=printer
value1=JUnit
value2=AOP
value3=DI
printer1=stringPrinter
printer2=consolePrinter
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<File name="File" fileName="./logs/logfile.log" append="true">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-5level %logger{36} - %msg%n" />
</File>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="org.springframework" level="INFO" additivity="false" />
<Logger name="myspring" level="DEBUG" />
<Root level="DEBUG">
<AppenderRef ref="console" level="DEBUG" />
<AppenderRef ref="File" level="DEBUG" />
</Root>
</Loggers>
</Configuration>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:component-scan base-package="myspring.customer">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- Spring MVC에 필요한 Bean들을 자동으로 등록해주는 태그-->
<mvc:annotation-driven />
<!-- DispatcherServlet의 변경된 url-pattern 때문에 필요한 태그 설정 -->
<mvc:default-servlet-handler/>
<!-- 아래 주석은 Controller에서 포워딩 되는 .jsp 확장자를 생략할 수 있다. -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- annotation-driven 태그에서 내부적으로 처리해주는 설정 -->
<!-- <bean id="jsonHttpMessageConverter" -->
<!-- class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> -->
<!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> -->
<!-- <property name="messageConverters"> -->
<!-- <list> -->
<!-- <ref bean="jsonHttpMessageConverter"/> -->
<!-- </list> -->
<!-- </property> -->
<!-- </bean> -->
</beans>
<?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="myspring.customer.dao.mapper.CustomerMapper">
<!-- 조회 쿼리는 id를 이용하여 실행 -->
<!-- parameter에 들어가는 값이 {value} 변수로 들어옴 -->
<select id="selectCustomerById" parameterType="string" resultType="Customer">
select * from customer where name=#{value}
</select>
<select id="selectCustomerList" resultType="Customer">
select * from customer order by id
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- log4j2 설정 -->
<settings>
<setting name="defaultStatementTimeout" value="3"/>
<setting name="logImpl" value="LOG4J2"/>
</settings>
<typeAliases>
<!-- CustomerVO 설정 -->
<typeAlias alias="Customer" type="myspring.customer.vo.CustomerVO" />
</typeAliases>
</configuration>
package myspring.customer.vo;
public class CustomerVO {
private Long id;
private String name;
private String email;
private int age;
private String entryDate;
// 기본생성자
public CustomerVO() {}
public CustomerVO(String name, String email, int age, String entryDate) {
this.name = name;
this.email = email;
this.age = age;
this.entryDate = entryDate;
}
public CustomerVO(Long id, String name, String email, int age, String entryDate) {
this(name, email, age, entryDate);
this.id = id;
}
// getter와 setter 생성
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEntryDate() {
return entryDate;
}
public void setEntryDate(String entryDate) {
this.entryDate = entryDate;
}
// toString 생성
@Override
public String toString() {
return "CustomerVO [id=" + id + ", name=" + name + ", email=" + email + ", age=" + age + ", entryDate="
+ entryDate + "]";
}
}
package myspring.customer.dao;
import java.util.List;
import myspring.customer.vo.CustomerVO;
public interface CustomerDao {
public List<CustomerVO> readAll();
public CustomerVO read(String id);
}
package myspring.customer.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import myspring.customer.dao.mapper.CustomerMapper;
import myspring.customer.vo.CustomerVO;
@Repository("customerDao")
public class CustomerDaoImpl implements CustomerDao {
@Autowired
private CustomerMapper customerMapper;
@Override
public CustomerVO read(String id) {
CustomerVO user = customerMapper.selectCustomerById(id);
return user;
}
public List<CustomerVO> readAll() {
List<CustomerVO> userList = customerMapper.selectCustomerList();
return userList;
}
}
package myspring.customer.dao.mapper;
import java.util.List;
import myspring.customer.vo.CustomerVO;
public interface CustomerMapper {
CustomerVO selectCustomerById(String id);
List<CustomerVO> selectCustomerList();
}
package myspring.customer.sevice;
import java.util.List;
import myspring.customer.vo.CustomerVO;
public interface CustomerService {
public List<CustomerVO> getCustomerList();
public CustomerVO getUser(String id);
}
package myspring.customer.sevice;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import myspring.customer.dao.CustomerDao;
import myspring.customer.vo.CustomerVO;
@Service("customerService")
public class CustomerServiceImpl implements CustomerService {
@Autowired
CustomerDao customerdao;
public List<CustomerVO> getCustomerList() {
return customerdao.readAll();
}
@Override
public CustomerVO getUser(String id) {
return customerdao.read(id);
}
}
package myspring.customer.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import myspring.customer.sevice.CustomerService;
import myspring.customer.vo.CustomerVO;
@Controller
public class CustomerController {
@Autowired
private CustomerService customerService;
public CustomerController() {
System.out.println(this.getClass().getName() + "생성자 호출됨");
}
// db에서 가져오고 화면에 보이는 것도 함께 설정
// View와 Model을 한꺼번에 전달하는 방법
@RequestMapping("/customerList.do")
public ModelAndView customerList() {
// service 불러와서 리스트로 받기
// 뿌려줄 jsp 페이지를 ModelAndView 객체에 담음 (viewName=jsp파일 이름(jsp확장자 없이 이름만 기재), modelName=키값(forEach구문의 items), modelList=서비스에서 받아온 list 기재)
// key 값(customerList)과 일치하여 list 변수명 바꾸기
List<CustomerVO> customerVOList = customerService.getCustomerList();
// ModelAndView(viewName, keyName, valueObject)
return new ModelAndView("customerList", "customerList", customerVOList);
}
//getUser.do?id=dooly
// View와 Model을 분리해서 전달하는 방법
@RequestMapping("/getUser.do")
public String getUser(@RequestParam("id") String userId, Model model) {
// @requestparam을 이용하여 ?(쿼리 스트링) 다음의 id 값 가져올 수 있음
// 받아온 customerVO를 model에 담아줌
CustomerVO userVO = customerService.getUser(userId);
model.addAttribute("customer", userVO);
// 페이지 이름 return
return "customerInfo";
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>CustomerSpringWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-beans-customer.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>customer list</title>
</head>
<body>
<h1>고객 관리 메인</h1>
<ul>
<li><a href="customerList.do">고객 리스트</a></li>
</ul>
</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"%>
<html>
<head>
<title>고객 관리</title>
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="text-center">고객 목록</h2>
<table class="table table-bordered table table-hover">
<thead>
<tr>
<th> </th>
<th>이름</th>
<th>이메일</th>
<th>나이</th>
<th>등록일자</th>
<th> </th>
</tr>
</thead>
<tbody>
<c:forEach var="customer" items="${customerList}">
<tr>
<td>
<a href="getUser.do?id=${customer.name}">${customer.name}</a>
</td>
<td>${customer.name}</td>
<td>${customer.email}</td>
<td>${customer.age}</td>
<td>${customer.entryDate}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>고객 상세정보</title>
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="text-center">고객 상세정보</h2>
<table class="table table-bordered table table-hover">
<tr><td>이름 :</td><td>${customer.name}</td></tr>
<tr><td>이메일 :</td><td>${customer.email}</td></tr>
<tr><td>나이 :</td><td>${customer.age}</td></tr>
<tr><td>등록일자 : </td><td>${customer.entryDate}</td></tr>
</table>
</div>
</body>
</html>
package com.mission.mymission.repository;
import com.mission.mymission.entity.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface CustomerRepository extends JpaRepository<Customer, Long> {
// < Entity 클래스, PK값 >
// Insert, Delete, Select만 존재
// select * from account where username = 'spring'
Optional<Customer> findByEmail(String email);
List<Customer> findByName(String name);
}
package com.mission.mymission.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import java.time.LocalDateTime;
@Entity
@Table(name = "customer")
@Getter @Setter
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
private int age;
@Column(updatable = false)
@CreationTimestamp
private LocalDateTime entryDate = LocalDateTime.now();
}
package com.mission.mymission.controller;
import com.mission.mymission.entity.Customer;
import com.mission.mymission.exception.BusinessException;
import com.mission.mymission.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private CustomerRepository customerRepository;
@PostMapping
public Customer create(@RequestBody Customer customer) {
return customerRepository.save(customer);
}
@GetMapping
public List<Customer> getCustomers() {
return customerRepository.findAll();
}
@GetMapping("/{id}")
public Customer getCustomer(@PathVariable Long id) {
Optional<Customer> optionalCustomer = customerRepository.findById(id);
Customer customer = optionalCustomer.orElseThrow(() -> new BusinessException("Customer Not Found", HttpStatus.NOT_FOUND));
return customer;
}
@GetMapping("/email/{email}")
public Customer getCustomerByEmail(@PathVariable String email) {
return customerRepository.findByEmail(email)
.orElseThrow(() -> new BusinessException("Email이 존재하지 않습니다", HttpStatus.NOT_FOUND));
}
@GetMapping("/name/{name}")
public List<Customer> getCustomerByName(@PathVariable String name) {
return customerRepository.findByName(name);
}
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteUser(@PathVariable Long id) {
Customer customer = customerRepository.findById(id)
.orElseThrow(() -> new BusinessException("Customer Not Found", HttpStatus.NOT_FOUND));
customerRepository.delete(customer);
return ResponseEntity.ok(id + " User가 삭제 되었습니다");
}
}
# 서버 포트 설정
#server.port=8087
# 스프링 유니코드 작성
# (applcation-prod/test.properties에서 설정)
myboot.name=\uc2a4\ud504\ub9c1
myboot.fullName=${myboot.name} Boot
spring.datasource.url=jdbc:mariadb://127.0.0.1:3306/boot_db
spring.datasource.username=boot
spring.datasource.password=boot
spring.datasource.driverClassName=org.mariadb.jdbc.Driver
# JPA를 사용한 데이터베이스 초기화
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
# DB Dialect 설정
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
package com.mission.mymission;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyMissionApplication {
public static void main(String[] args) {
// SpringApplication.run(MySpringBoot3Application.class, args);
SpringApplication application = new SpringApplication(MyMissionApplication.class);
// WebApplication Type을 변경하기 위한 목적
application.setWebApplicationType(WebApplicationType.SERVLET);
// None : 더이상 WebApplication이 아님
application.run(args);
}
}
package com.mission.mymission.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
@Getter
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String message;
private HttpStatus httpStatus;
public BusinessException(String message) {
//417
this(message, HttpStatus.EXPECTATION_FAILED);
}
public BusinessException(String message, HttpStatus httpStatus) {
this.message = message;
this.httpStatus = httpStatus;
}
}
package com.mission.mymission.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
@Getter
public class SystemException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String message;
private HttpStatus httpStatus;
private Throwable throwable;
public SystemException(Exception e) {
this(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
public SystemException(String message) {
this(message, HttpStatus.INTERNAL_SERVER_ERROR);
}
public SystemException(String message, Throwable t) {
this.message = message;
this.throwable =t;
}
public SystemException(Throwable t) {
this.throwable = t;
}
public SystemException(String message, HttpStatus httpStatus) {
this.message = message;
this.httpStatus = httpStatus;
}
public Throwable getThrowable() {
return this.throwable;
}
}
package com.mission.mymission.advice;
import com.mission.mymission.exception.BusinessException;
import com.mission.mymission.exception.SystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class DefaultExceptionAdvice {
private final Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionAdvice.class);
@ExceptionHandler(BusinessException.class)
protected ResponseEntity<Object> handleException(BusinessException e) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("message", "[안내] " + e.getMessage());
result.put("httpStatus", e.getHttpStatus().value());
return new ResponseEntity<>(result, e.getHttpStatus());
}
@ExceptionHandler(SystemException.class)
protected ResponseEntity<Object> handleException(SystemException e) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("message", "[시스템 오류] " + e.getMessage());
result.put("httpStatus", e.getHttpStatus().value());
return new ResponseEntity<>(result, e.getHttpStatus());
}
//숫자타입의 값에 문자열타입의 값을 입력으로 받았을때 발생하는 오류
@ExceptionHandler(HttpMessageNotReadableException.class)
protected ResponseEntity<Object> handleException(HttpMessageNotReadableException e) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("message", e.getMessage());
result.put("httpStatus", HttpStatus.BAD_REQUEST.value());
return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(Exception.class)
protected ResponseEntity<Object> handleException(Exception e) {
Map<String, Object> result = new HashMap<String, Object>();
ResponseEntity<Object> ret = null;
if (e instanceof BusinessException) {
BusinessException b = (BusinessException) e;
result.put("message", "[안내]\n" + e.getMessage());
result.put("httpStatus", b.getHttpStatus().value());
} else if ( e instanceof SystemException) {
SystemException s = (SystemException)e;
result.put("message", "[시스템 오류]\n" + s.getMessage());
result.put("httpStatus", s.getHttpStatus().value());
ret = new ResponseEntity<>(result, s.getHttpStatus());
LOGGER.error(s.getMessage(), s);
} else {
String msg = "예상치 못한 문제가 발생했습니다.\n관리자에게 연락 하시기 바랍니다.";
result.put("message", msg);
result.put("httpStatus", HttpStatus.INTERNAL_SERVER_ERROR.value());
ret = new ResponseEntity<>(result, HttpStatus.INTERNAL_SERVER_ERROR);
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
return ret;
}
}