1. 컨트롤러 (Controller)
- 역할: 클라이언트 요청을 수신하고, 요청을 처리하기 위해 적절한 서비스를 호출하며, 결과를 반환합니다.
2. 서비스 (Service)
- 역할: 비즈니스 로직을 처리하며, 필요 시 DAO(Data Access Object)를 호출합니다.
- 인터페이스를 사용하여 추상화하고, 구현체를 통해 비즈니스 로직을 제공합니다.
3. DAO (Data Access Object)
- 역할: 데이터베이스와의 상호작용을 담당하며, 데이터 조회 및 조작 작업을 수행합니다.
- 주로 Spring의 @Repository를 사용하여 구현합니다.
4. 실행 흐름
- 클라이언트가 특정 URL로 요청을 보냄
- 해당 요청이 Controller로 전달됨.
- Controller 는 Service를 호출하여 비즈니스 로직 처리 요청.
- Service 는 Dao를 호출하여 데이터베이스에서 필요한 데이터를 가져옴.
- 데이터를 받아서 비즈니스 로직을 적용한 후 Controller에 반환.
- Controller는 데이터를 View로 전달하거나, JSON 등의 형태로 응답을 반환.
DB연결에 필요한 라이브러리(pom.xml의 dependency에 추가)
MyBatis 포함
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<!-- Spring-jdbc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Spring-test -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Common-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- DB MyBatis 연결시 필요 -->
<!-- MyBatis 3.4.1 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- MyBatis-Spring -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
root-context.xml
db연결 정보
& 기호를 사용할 수 없어서 & 를 사용하였습니다
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- DB 연결 정보 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<!-- & :: & 기호 -->
<property name="url" value="jdbc:mysql://localhost:3306/board?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false" />
<property name="username" value="tester" />
<property name="password" value="1234" />
</bean>
</beans>
run as를 하였을 때 밑의 오류가 발생하였습니다. path 가 겹쳐서 발생하는 문제였습니다
왼쪽 하단의 연결된 톰캣 서버를 더블 클릭하고 Modules를 클릭하면 path를 확인할 수 있습니다
현재 사용하지 않을 springMVC1을 클릭하여 remove하고 저장하면 문제없이 동작합니다
Mybatis 연결
<!-- mybatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" /><!-- 위의 db연결 bean을 참조 -->
<property name="configLocation" value="classpath:mybatis_config.xml"/> <!-- MyBatis의 전역 설정 파일 경로를 지정 -->
<property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml" /><!-- 실행해야 하는 sql들의 모음(매퍼) 위치 -->
</bean>
속성 설명
dataSource
- 데이터베이스 연결에 필요한 DataSource를 참조합니다.
- Spring의 다른 Bean에서 정의된 DataSource를 연결하여 사용합니다.
- 예를 들어, HikariCP나 Apache DBCP를 사용하여 DataSource를 정의합니다.
configLocation
- MyBatis의 전역 설정 파일 경로를 지정합니다.
- 이 설정 파일에는 MyBatis 동작 방식을 정의합니다.
- 주요 설정 항목:
- mapUnderscoreToCamelCase: DB 컬럼명(예: user_id)을 자동으로 CamelCase(예: userId)로 매핑.
- 예시 파일 (mybatis_config.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>
<!-- vo 별칭 지정 -->
<typeAliases>
<!-- 별칭 지정시 반드시 클래스부터 선언 후 별칭 지정! -->
<typeAlias type="edu.springboard.vo.UserVO" alias="userVO"/>
</typeAliases>
</configuration>
mapperLocations
- Mapper XML 파일의 위치를 지정합니다.
- Mapper 파일은 SQL 문장이 포함된 XML 파일입니다.
- 설정에서 classpath:mappers/**/*Mapper.xml은 Maven/Gradle 프로젝트의 resources 디렉터리 내 mappers 폴더 아래 모든 서브 디렉터리의 Mapper.xml 파일을 포함합니다.
- 예시 매퍼 파일 (UserMapper.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="edu.springboard.mapper.userMapper">
<select id="selectLogin" parameterType="String" resultType="java.util.Map">
SELECT userid as username
, name
, password
, enabled
, authority
from user
WHERE userid = #{value}
</select>
<insert id="insert" parameterType="java.util.Map">
insert into user(userid
, password
, name
,enabled
, authority)
values(#{userid}
, #{password}
,#{name}
,1
,#{authority})
</insert>
</mapper>
parameterType="String": 파라미터로 전달되는 값이 String 타입임을 지정.
resultType="java.util.Map": 결과를 Map으로 반환하며, 컬럼명이 키(username, name, password 등), 컬럼 값이 값으로 매핑됩니다.
#{value}: 동적 SQL 바인딩으로, 메서드에 전달된 인자를 SQL 쿼리의 userid 값으로 대체.
쿼리를 실행하는 객체
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
SqlSessionTemplate은 MyBatis와 Spring의 기능을 연결해주는 핵심 객체입니다.
이를 통해 SQL 실행, 트랜잭션 관리, 그리고 Mapper 연동이 원활하게 이루어질 수 있습니다.
SqlSessionFactory는 SQL 세션 생성 및 Mapper XML과의 매핑을 처리합니다.
home.jsp의 <%@ page session="false" %>
세션을 사용하지 못하게 되니 지우거나 주석처리해야한다
회원가입
폴더구조
servlet-context.xml에 밑의 두줄 추가
<context:component-scan base-package="edu.springboard.service" />
<context:component-scan base-package="edu.springboard.dao" />
mybatis_config.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>
<!-- vo 별칭 지정 -->
<typeAliases>
<typeAlias type="edu.springboard.vo.UserVO" alias="userVO"/>
</typeAliases>
</configuration>
UserMapper.xml
parameterType #{} 타입
mybatis_config.xml 에서 userVO라는 이름으로 별칭을 지었기 때문에 userVO
만약 별칭을 사용하지 않을 경우 패키지명부터 전체를 써주면 된다
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="edu.springboard.mapper.userMapper">
<!-- namespace : 별칭. 다른 매퍼와 겹치지만 않으면 된다 -->
<insert id="userInsert" parameterType="userVO">
INSERT INTO user(
uid,
upw,
uname,
uphone,
uemail
) VALUES(
#{uid},
#{upw},
#{uname},
#{uphone},
#{uemail}
)
</insert>
</mapper>
UserVO
package edu.springboard.vo;
public class UserVO {
private int uno;
private String uid;
private String upw;
private String uname;
private String uphone;
private String uemail;
private String rdate;
private String ustate;
private String uauthor;
public int getUno() { return uno; }
public String getUid() { return uid; }
public String getUpw() { return upw; }
public String getUname() { return uname; }
public String getUphone() { return uphone; }
public String getUemail() { return uemail; }
public String getRdate() { return rdate; }
public String getUstate() { return ustate; }
public String getUauthor() { return uauthor;}
public void setUno(int uno) { this.uno = uno; }
public void setUid(String uid) { this.uid = uid; }
public void setUpw(String upw) { this.upw = upw; }
public void setUname(String uname) { this.uname = uname; }
public void setUphone(String uphone) { this.uphone = uphone; }
public void setUemail(String uemail) { this.uemail = uemail; }
public void setRdate(String rdate) { this.rdate = rdate; }
public void setUstate(String ustate) { this.ustate = ustate; }
public void setUauthor(String uauthor) { this.uauthor = uauthor;}
}
UserService 인터페이스
package edu.springboard.service;
import edu.springboard.vo.UserVO;
public interface UserService {
public int insert(UserVO userVO); //추상메소드
}
UserServiceImpl
package edu.springboard.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import edu.springboard.dao.UserDAO;
import edu.springboard.vo.UserVO;
@Service //업무로직을 담당하는 구현 객체를 스프링이 생성하여 관리
public class UserServiceImpl implements UserService {
@Autowired
public UserDAO userDAO;
@Override
public int insert(UserVO userVO) {
int result = 0;
result = userDAO.insert(userVO);
return result;
}
}
UserDAO
sqlSession으로 insert할때 안에 들어가는 값은
첫번째 UserMapper namespace.쿼리id
두번째 userVO
package edu.springboard.dao;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import edu.springboard.vo.UserVO;
@Repository
public class UserDAO {
@Autowired
public SqlSession sqlSession;
public int insert(UserVO userVO) {
int result = 0;
//UserMapper namespace.쿼리id
result = sqlSession.insert("edu.springboard.mapper.userMapper.userInsert",userVO);
return result;
}
}
UserController
package edu.springboard.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import edu.springboard.service.UserService;
import edu.springboard.vo.UserVO;
@Controller
public class UserController {
//UserController 생성시 userService 의존 자동 주입
@Autowired
public UserService userService;
@RequestMapping(value="/join.do", method = RequestMethod.GET)
public String join() {
return "user/join";
}
@RequestMapping(value="/join.do", method = RequestMethod.POST)
public String join(UserVO userVO) {
int result = userService.insert(userVO);
if(result > 0) {
System.out.println("회원등록완료");
}else {
System.out.println("회원등록실패");
}
return "redirect:/";
}
}
회원정보수정
UserController
@RequestMapping(value="/user/modify.do", method = RequestMethod.POST)
public String modify(UserVO userVO) {
int result = userService.update(userVO);
if(result > 0) {
System.out.println("회원정보수정완료");
return "redirect:/";
}else {
System.out.println("회원정보수정실패");
return "redirect:modify.do";
}
}
UserService
package edu.springboard.service;
import edu.springboard.vo.UserVO;
public interface UserService {
public int insert(UserVO userVO); //추상메소드
public int update(UserVO userVO); //추상메소드
}
UserServiceImpl
@Override
public int update(UserVO userVO) {
return userDAO.update(userVO);
}
UserDAO
public int update(UserVO userVO) {
return sqlSession.update("edu.springboard.mapper.userMapper.userUpdate",userVO);
}
UserMapper
<update id="userUpdate" parameterType="userVO">
UPDATE user
SET uname=#{uname},
uphone=#{uphone},
uemail=#{uemail}
WHERE uid=#{uid}
</update>
modify.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원정보수정하기</title>
<style>
th{text-align:right;}
button{
width: 300px;
height: 40px;
background-color: royalblue;
color:white;
font-weight: bold;
border: 1px solid white;
border-radius: 5px;
cursor:pointer;
font-size: 18px;
}
input[type="text"],input[type="password"] {
outline:none;
height: 30px;
border: 1px solid #EEEEEE;
border-radius: 5px;
}
</style>
</head>
<body>
<a href="<%= request.getContextPath() %>">home으로 돌아가기</a>
<h2>회원정보수정하기</h2><hr>
<form action="modify.do" method="post">
<table>
<tr>
<th>수정할 아이디 : </th>
<td><input type="text" name="uid" id="uid"></td>
</tr>
<tr>
<td colspan="2">수정 정보 입력</td>
</tr>
<tr>
<th>이름 : </th>
<td><input type="text" name="uname" id="uname"></td>
</tr>
<tr>
<th>연락처 : </th>
<td><input type="text" name="uphone" id="uphone"></td>
</tr>
<tr>
<th>이메일 : </th>
<td><input type="text" name="uemail" id="uemail"></td>
</tr>
</table>
<br>
<button>수정하기</button>
</form>
</body>
</html>
로그인
UserController
@RequestMapping(value="/login.do", method = RequestMethod.GET)
public String login() {
return "user/login";
}
@RequestMapping(value="/login.do", method = RequestMethod.POST)
public String login(UserVO userVO, HttpServletRequest request) {
UserVO user = userService.selectbyLogin(userVO);
if(user != null) {
System.out.println("로그인완료");
HttpSession session = request.getSession();
session.setAttribute("loginUser", user);
return "redirect:/";
}else {
System.out.println("로그인실패");
return "redirect:login.do";
}
}
UserService
package edu.springboard.service;
import edu.springboard.vo.UserVO;
public interface UserService {
public int insert(UserVO userVO); //추상메소드
public int update(UserVO userVO); //추상메소드
public UserVO selectbyLogin(UserVO userVO);
}
UserServiceImpl
@Override
public UserVO selectbyLogin(UserVO userVO) {
return userDAO.selectbyLogin(userVO);
}
UserDAO
public UserVO selectbyLogin(UserVO userVO) {
return sqlSession.selectOne("edu.springboard.mapper.userMapper.selectUserByLogin",userVO);
}
userMapper
<select id="selectUserByLogin" parameterType="userVO" resultType="userVO">
SELECT uno,uid,uauthor,ustate
FROM user
WHERE uid=#{uid} and upw=#{upw}
</select>
home.jsp
<%@ 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>Home</title>
<meta charset="UTF-8">
</head>
<body>
<h1>게시판 시스템 만들기</h1><hr>
<!-- 로그인 X -->
<c:if test="${empty loginUser}">
<a href="join.do">회원가입</a><br>
<a href="login.do">로그인</a><br>
</c:if>
<!-- 로그인 O -->
<c:if test="${not empty loginUser}">
<p>${loginUser.uid}님 환영합니다 </p>
<a href="user/modify.do">회원정보수정</a><br>
</c:if>
</body>
</html>
회원목록출력하기
UserController
@RequestMapping(value="/user/list.do")
public String userList(Model model, HttpServletRequest request) {
//권한체크 : 로그인된 회원 권한이 관리자인지
HttpSession session = request.getSession();
if(session.getAttribute("loginUser") == null
||
!((UserVO)session.getAttribute("loginUser")).getUauthor().equals("A")) {
return "redirect:/";
}
//비지니스 로직 : DB에 있는 전체 회원 목록 데이터 가져오기
List<UserVO> userList = userService.selectAll();
//모델 객체 사용하여 조회 데이터 화면으로 포워딩
model.addAttribute("userList", userList);
return "user/list";
}
UserService
package edu.springboard.service;
import java.util.List;
import edu.springboard.vo.UserVO;
public interface UserService {
public int insert(UserVO userVO); //추상메소드
public int update(UserVO userVO); //추상메소드
public UserVO selectbyLogin(UserVO userVO);
public List<UserVO> selectAll();
}
UserServiceImpl
@Override
public List<UserVO> selectAll() {
return userDAO.selectAll();
}
UserDAO
public List<UserVO> selectAll() {
return sqlSession.selectList("edu.springboard.mapper.userMapper.selectAll");
}
userMapper
<select id="selectAll" resultType="userVO">
SELECT * FROM user
</select>
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원목록조회</title>
</head>
<body>
<a href="<%= request.getContextPath() %>">home으로 돌아가기</a>
<h2>회원목록조회</h2><hr>
<table border="1" style="width:700px;">
<tr>
<th style="width:40px;">회원번호</th>
<th style="width:120px;">아이디</th>
<th style="width:160px;">가입일</th>
<th style="width:180px;">이메일</th>
</tr>
<c:forEach items="${userList}" var="userList">
<tr>
<td>${userList.uno}</td>
<td>${userList.uid}</td>
<td>${userList.rdate}</td>
<td>${userList.uemail}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
특정회원정보조회
UserController
@RequestMapping(value="/user/view.do")
public String view(String uno, HttpServletRequest request, Model model) {
//권한체크 : 로그인된 회원 권한이 관리자인지
HttpSession session = request.getSession();
if(session.getAttribute("loginUser") == null
||
!((UserVO)session.getAttribute("loginUser")).getUauthor().equals("A")) {
return "redirect:/";
}
UserVO user = userService.selectOne(uno);
if(user != null) {
System.out.println("회원정보조회완료");
model.addAttribute("viewUser",user);
return "user/view";
}else {
System.out.println("회원정보조회실패");
return "redirect:/";
}
}
UserService
public UserVO selectOne(String uno);
UserServiceImpl
@Override
public UserVO selectOne(String uno) {
return userDAO.selectOne(uno);
}
UserDAO
public UserVO selectOne(String uno) {
return sqlSession.selectOne("edu.springboard.mapper.userMapper.selectOne",uno);
}
userMapper
<select id="selectOne" parameterType="String" resultType="userVO">
SELECT *
FROM user
WHERE uno=#{uno}
</select>
list.jsp
<td>
<a href="view.do?uno=${userList.uno}">${userList.uid}</a>
</td>
view.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원상세페이지</title>
</head>
<body>
<a href="<%= request.getContextPath() %>">home으로 돌아가기</a><br>
<a href="list.do">회원목록으로 돌아가기</a>
<h2>회원상세페이지</h2><hr>
<!-- 회원목록 페이지에서 id 클릭시 상세정보 페이지로 이동합니다
이때 클릭한 아이디 회원 정보를 전부 상세페이지에 출력합니다
-->
<table border="0">
<table>
<tr>
<th>아이디 : </th>
<td>${viewUser.uid}</td>
</tr>
<tr>
<th>비밀번호 : </th>
<td>${viewUser.upw}</td>
</tr>
<tr>
<th>이름 : </th>
<td>${viewUser.uname}</td>
</tr>
<tr>
<th>연락처 : </th>
<td>${viewUser.uphone}</td>
</tr>
<tr>
<th>이메일 : </th>
<td>${viewUser.uemail}</td>
</tr>
<tr>
<th>권한 : </th>
<td>${viewUser.uauthor}</td>
</tr>
<tr>
<th>상태 : </th>
<td>${viewUser.ustate}</td>
</tr>
<tr>
<th>가입일 : </th>
<td>${viewUser.rdate}</td>
</tr>
</table>
</table>
</body>
</html>
특정회원정보 수정에서 회원정보 받아오기
UserController
@RequestMapping(value="/user/modify2.do", method = RequestMethod.GET)
public String modify2(String uno, Model model) {
UserVO user = userService.selectOne(uno);
model.addAttribute("viewUser",user);
return "user/modify2";
}
view.jsp
<button onclick="location.href='modify2.do?uno=${viewUser.uno}'">수정</button>
modify2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원정보수정</title>
<style>
th{text-align:right;}
button{
width: 300px;
height: 40px;
background-color: royalblue;
color:white;
font-weight: bold;
border: 1px solid white;
border-radius: 5px;
cursor:pointer;
font-size: 18px;
}
input[type="text"],input[type="password"] {
outline:none;
height: 30px;
border: 1px solid #EEEEEE;
border-radius: 5px;
}
</style>
</head>
<body>
<a href="<%= request.getContextPath() %>">home으로 돌아가기</a>
<h2>회원정보수정하기</h2><hr>
<form action="modify2.do" method="post">
<table>
<tr>
<th>수정할 아이디 : </th>
<td><input type="text" name="uid" id="uid" value="${viewUser.uid}" readonly></td>
</tr>
<tr>
<td colspan="2">수정 정보 입력</td>
</tr>
<tr>
<th>이름 : </th>
<td><input type="text" name="uname" id="uname" value="${viewUser.uname}"></td>
</tr>
<tr>
<th>연락처 : </th>
<td><input type="text" name="uphone" id="uphone" value="${viewUser.uphone}"></td>
</tr>
<tr>
<th>이메일 : </th>
<td><input type="text" name="uemail" id="uemail" value="${viewUser.uemail}"></td>
</tr>
<tr>
<th>권한 : </th>
<td>
<input type="radio" name="uauthor" value="A"
<c:if test="${viewUser.uauthor.equals('A')}">
checked
</c:if>
>관리자
<input type="radio" name="uauthor" value="U"
<c:if test="${viewUser.uauthor.equals('U')}">
checked
</c:if>
>일반
</td>
</tr>
</table>
<br>
<!--
상세페이지에서 수정버튼 클릭시 modify2.jsp가 포워드됩니다
이때 클릭한 상세데이터를 입력양식에 출력합니다.
-->
<button>수정하기</button>
</form>
</body>
</html>
modify2의 코드에서 c:if 를 input type radio 태그 안에서 사용하여 조건을 확인하고 checked를 주고 있습니다
<input type="radio" name="uauthor" value="A"
<c:if test="${viewUser.uauthor.equals('A')}">
checked
</c:if>
>관리자
<input type="radio" name="uauthor" value="U"
<c:if test="${viewUser.uauthor.equals('U')}">
checked
</c:if>
>일반
'Spring' 카테고리의 다른 글
[Spring] AJAX 한 건의 데이터 받기 (1) | 2024.11.29 |
---|---|
[Spring] MVC 연습 (0) | 2024.11.28 |
[Spring] @Controller (0) | 2024.11.25 |
[Spring] 스프링 MVC 프로젝트 (0) | 2024.11.24 |
[Spring] AOP 어노테이션 (0) | 2024.11.23 |