포스코DX X 비트교육센터 6기 - Spring


mapping 방법

  • main에서 multy url 사용하기
package com.poscodx.hellospring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MainController {

	@ResponseBody
	@RequestMapping({"/", "/main", "/board/write"} )
	public String main() {
		return "MainController.main()";
	}
}
  • @RequestMapping("/guestbook/*") 이렇게 url을 주면, 하위의 함수 이름으로 불러올 수 있음.
package com.poscodx.hellospring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @RequestMapping 클래스 단독 매핑
 * Spring MVC 4.X에서만 지원한다!
 */
@Controller
@RequestMapping("/guestbook/*")
public class GuestbookController {
	
	@ResponseBody
	@RequestMapping
	public String list() {
		return "GuestbookController.list()";
	}

	@ResponseBody
	@RequestMapping
	public String delete() {
		return "GuestbookController.delete()";
	}
}

But, 이는 스프링 MVC 버전 4에서만 지원하기 때문에, 지금 실습 환경에서는 에러가 발생함.

  • 메서드 단독 매핑
package com.poscodx.hellospring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @RequestMapping 메서드 단독 매핑
 */
@Controller
public class BoardController {

	@ResponseBody
	@RequestMapping("/board/write")
	public String write() {
		return "BoardController.write()";
	}

	@ResponseBody
	@RequestMapping("/board/view")
	public String view(Long no) {
		return "BoardController.write(" + no + ")";
	}
}

image

  • [ 강추 ] class + method 매핑
package com.poscodx.hellospring.controller;

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

/**
 * @RequestMapping 클래스 + 메서드 매핑
 *
 *  강추
 *
 */

@RequestMapping("/user")
@Controller
public class UserController {

	@RequestMapping("/joinform")
	public String joinform() {
		return "/WEB-INF/views/joinform.jsp";

	}

}

image

  • 변수 url의 다른 스타일
// /board/view/10
	@ResponseBody
	@RequestMapping("/board/view/{no}")
	public String view1(@PathVariable("no") Long no) {
		return "BoardController.write(" + no + ")";
	}

	// /board/view?no=10
	@ResponseBody
	@RequestMapping("/board/view")
	public String view2(Long no) {
		return "BoardController.write(" + no + ")";
	}

image

  • joinform과 join…

joinform.jsp

<form id="join-form" name="joinForm" method="post" action="${pageContext.request.contextPath }/user/join">

image

  • joinform이라는 이름이 안 좋 다!!
@RequestMapping("/user")
@Controller
public class UserController {

	@RequestMapping(value="/join", method=RequestMethod.GET)
	public String joinform() {
		return "/WEB-INF/views/join.jsp";
	}
	
	@RequestMapping(value="/join", method=RequestMethod.POST)
	public String join(UserVo userVo) {
		System.out.println("UserController.join(): UserDao.insert("+ userVo+")");
		return "redirect:/";
	}
}

image

  • url param 명과 변수명을 다르게 하기.
	@ResponseBody
	@RequestMapping("/update")	
	public String update(@RequestParam("n") String name) {
		return "UserController.update(" + name +")";
	}

image

+) 만일 n이라는 이름의 URL 파라미터가 없으면 400 bad request 에러가 난다.

이 문제를 해결하기 위해서는,

@ResponseBody
	@RequestMapping("/update2")	
	public String update2(@RequestParam(value="n", required=false, defaultValue="") String name) {
		
		return "UserController.update(" + name +")";
	}

required를 통해 null값이 들어와도 에러가 안나도록 막아주며, defaultValue를 통해 null이 아니라 “” 값이 들어오도록한다.

image

@ResponseBody
	@RequestMapping("/list")
	public String list(@RequestParam(value="p", required=true, defaultValue="1") int pageNo) {
		return "UserController.update(" + pageNo + ")";
	}

Emaillist03

  • pom.xml 세팅팅
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.poscodx</groupId>
		<artifactId>spring-practices</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>emaillist03</artifactId>
	<packaging>war</packaging>


	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.build.outputEncoding>UTF-8</project.build.outputEncoding>
		<maven.compiler.source>17</maven.compiler.source>
		<maven.compiler.target>17</maven.compiler.target>
		<org-springframework-version>5.3.25</org-springframework-version>
	</properties>

	<dependencies>
		<!-- spring mvc(web framework) -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org-springframework-version}</version>
		</dependency>

		<!--jstl-->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!--jdbc driver-->
		<dependency>
			<groupId>org.mariadb.jdbc</groupId>
			<artifactId>mariadb-java-client</artifactId>
			<version>3.0.8</version>
		</dependency>

		<!-- servlet-->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.2</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>emaillist03</finalName>
	</build>
</project>
  • web.xml 추가하기
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>emaillist03</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>
  
  <!-- Dispatcher Servlet -->
	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-servlet.xml</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>
  • spring-servlet.xml 추가
<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
	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:annotation-config />
	<context:component-scan base-package="com.poscodx.emailist.controller" />

</beans>


  • com.poscodx.emaillist.controller 패키지 만들기

앞으로 필요한 패키지

com.poscodx.emailist.controller

com.poscodx.emailist.repository  (dao)

com.poscodx.emaillist.vo
  • controller class 만들기
package com.poscodx.emailist.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class EmaillistController {
	
	@ResponseBody
	@RequestMapping("/")
	public String main() {
		return "ok!";
	}
}

image

  • 잘 되는 것을 확인

image

그린이:장은영

  • web.xml에 contextLoad Listener 추가
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
	<display-name>emaillist03</display-name>

	<!-- here!!! -->
        <context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:config/applicationContext.xml</param-value>
	</context-param>

	<!-- ContextLoad Listener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- here!!! -->

	<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>

	<!-- Dispatcher Servlet -->
	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-servlet.xml</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>
  • applicationContext.xml 추가

image

<?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:aop="http://www.springframework.org/schema/aop"
	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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">

	<context:annotation-config />

	<context:component-scan
		base-package="com.poscodx.emailist.repository">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Repository" />
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Service" />
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Component" />
	</context:component-scan>


</beans>
 

image

=> applicationContext.xml를 통해 Root Application Context 컨테이너가 만들어진 것이다.

  • com.poscodx.emailitt.repository 패키지 안에 EmaillistRepository.java를 만든다.
package com.poscodx.emailist.repository;

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 org.springframework.stereotype.Repository;

import com.poscodx.emaillist.vo.EmaillistVo;

@Repository
public class EmaillistRepository {
	
	public List<EmaillistVo> findAll() {
		List<EmaillistVo> result = new ArrayList<>();
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			conn = getConnection();

			//3. SQL 준비
			String sql = "select no, first_name, last_name, email from emaillist order by no desc";
			pstmt = conn.prepareStatement(sql);
			
			//4. binding
			
			//5. SQL 실행
			rs = pstmt.executeQuery();
			
			//6. 결과 처리
			while(rs.next()) {
				Long no = rs.getLong(1);
				String firstName = rs.getString(2);
				String lastName = rs.getString(3);
				String email = rs.getString(4);
				
				EmaillistVo vo = new EmaillistVo();
				vo.setNo(no);
				vo.setFirstName(firstName);
				vo.setLastName(lastName);
				vo.setEmail(email);
				
				result.add(vo);
			}
			
		} catch (SQLException e) {
			System.out.println("error:" + e);
		} finally {
			try {
				// 7. 자원정리
				if(rs != null) {
					rs.close();
				}
				if(pstmt != null) {
					pstmt.close();
				}
				if(conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return result;
	}

	public void insert(EmaillistVo vo) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		
		try {
			conn = getConnection();
			
			String sql = "insert into emaillist values(null, ?, ?, ?)";
			pstmt = conn.prepareStatement(sql);
			
			pstmt.setString(1, vo.getFirstName());
			pstmt.setString(2, vo.getLastName());
			pstmt.setString(3, vo.getEmail());
			
			pstmt.executeQuery();
		} catch (SQLException e) {
			System.out.println("error:" + e);
		} finally {
			try {
				if(pstmt != null) {
					pstmt.close();
				}
				if(conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public void deleteByEmail(String email) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		
		try {
			conn = getConnection();
			
			String sql = "delete from emaillist where email=?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, email);
		
			pstmt.executeQuery();
		} catch (SQLException e) {
			System.out.println("error:" + e);
		} finally {
			try {
				if(pstmt != null) {
					pstmt.close();
				}
				if(conn != null) {
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}		
	}
	
	private Connection getConnection() throws SQLException {
		Connection conn = null;
		
		try {
			Class.forName("org.mariadb.jdbc.Driver");
			String url = "jdbc:mariadb://192.168.0.178:3307/webdb?charset=utf8";
			conn = DriverManager.getConnection(url, "webdb", "webdb");
		} catch (ClassNotFoundException e) {
			System.out.println("드라이버 로딩 실패:" + e);
		} 
		
		return conn;
	}
}
  • annotation 잊지말기.
  • Root Applicaton context라는 컨테이너 안에. EmaillistRepository(DAO)를 넣은 것이다.

  • 이를 EmaillistController.java에 이용하기
package com.poscodx.emailist.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.ResponseBody;

import com.poscodx.emailist.repository.EmaillistRepository;

@Controller
public class EmaillistController {
	
	@Autowired //root Applicaton context안의 Emaillistrepository에서 web application context 안의 emaillistController 의 연결을 돕는다.
	private EmaillistRepository emaillistRepository;
	
	
	@ResponseBody
	@RequestMapping("/")
	public String main() {
		emaillistRepository.findAll();
		return "ok!";
	}
}

  • @Autowired : root Applicaton context안의 Emaillistrepository에서 web application context 안의 emaillistController 의 연결을 돕는다.

  • 먼저 emaillistController를 본 다음 autowired를 통해 emaillistRepoistory를 살핀다.

@RequestParam vs @PathVariable

데이터를 받아오는 데에 사용

  • @RequestParam : 데이터를 여러개 받아온다.

  • @PathVariable : 값을 하나만 받아올 수 있다.

mysite03

  • css가 안 불러와진다..!

: mapping이 안되어 있다.

spring-servlet.xml에 driven과 handler 추가

        <!-- 
		validator
		Defalut Servlet Handler 작동 시키기 위함.
		Message converter
		Argument Resolve
	 -->
	<mvc:annotation-driven />

	<!-- Default Servlert Handler -->
	<mvc:default-servlet-handler />

image