일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- javascript
- sql
- string
- 큐
- html
- List
- CSS
- alter
- BFS
- 스프링부트
- NIO
- JPA
- Properties
- GC로그수집
- priority_queue
- dfs
- 스택
- 힙덤프
- Union-find
- union_find
- date
- math
- spring boot
- deque
- map
- scanner
- Java
- 리소스모니터링
- set
- Calendar
- Today
- Total
매일 조금씩
01/29 ! - Spring MVC (3) : welcome 페이지 구현, 파일 업로드 구현(JSON, XML) , 데이터베이스 연결(직접연결, JdbcTemplate) 본문
01/29 ! - Spring MVC (3) : welcome 페이지 구현, 파일 업로드 구현(JSON, XML) , 데이터베이스 연결(직접연결, JdbcTemplate)
mezo 2021. 2. 25. 20:00Spring MVC template
구형버전이여서 활용시 유의사항이 있다.
Spring MVC Project 설정 => 프로젝트 복사 (Properties 에서 Project setting에서 이름변경 해줘야함)
1. web.xml 수정
/ -> *.do
utf-8 인코딩 필터 설정
2. Properties
JRE System Library -> 버전 변경
Project Facets -> Java 버전 변경
3. pom.xml
JDK 버전 변경
Spring Framework 버전 변경
aspectj 버전변경
slf4j 버전 변경
4. 필요한 추가 라이브러리 설정
3-5. welcome 파일 지정 하기
http://localhost:8082/프로젝트명/*.jsp
http://localhost:8082/프로젝트명/
=> http://localhost:8082/프로젝트명/특정.jsp
WEB-INF 밖에 있는 시작 페이지를 실행시키면 바로 특정 jsp 파일이 뜨게한다.
먼저 시작 페이지에 다음과 같이 작성하고
<%
response.sendRedirect("index.do");
%>
web.xml에 아래 코드를 맨 위에 넣는다.
<welcome-file-list>
<welcome-file>index.do</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
그러면
이렇게 실행된다. 시작과 함께 index.do를 요청하는 것이다.
[ fileupload lib ]
1. cos.jar
2. common-io / common-fileupload
3-6. 파일 업로드하기 - cos.jar
> SpringWebEx01
1) cos.jar 를 프로젝트에 추가
파일을 업로드 하기 위해선 cos.jar가 필요하므로 maven repository에서 검색해서 pom.xml에 코드를 추가한다.
<!-- https://mvnrepository.com/artifact/servlets.com/cos -->
<dependency>
<groupId>servlets.com</groupId>
<artifactId>cos</artifactId>
<version>05Nov2002</version>
</dependency>
cos.jar를 추가해줘야 MultipartRequest 클래스를 사용할 수 있다.
2) 다음 형식에 맞춰서 페이지에 작성한다.
<form method="post" enctype="multipart/form-data"
<input type="file"
> write.jsp
<form action="write_ok.do" method="post" enctype="multipart/form-data">
파일: <input type="file" name="upload" />
<input type="submit" value="전송" />
</form>
3) webapp에 upload 폴더 생성
4) HomeController.java에 파일 업로드 코드 추가
@RequestMapping("/write.do")
public String write() {
return "write";
}
@RequestMapping("/write_ok.do")
public String write_ok(HttpServletRequest request, HttpServletResponse response) {
String uploadPath="C:\\Java\\java\\spring-workspace\\SpringWebEx01\\src\\main\\webapp\\upload";
int maxFileSize = 1024 * 1024 * 2;
String encType = "utf-8";
MultipartRequest multi = null;
try {
multi = new MultipartRequest(request, uploadPath, maxFileSize, encType, new DefaultFileRenamePolicy());
System.out.println(multi.getOriginalFileName("upload"));
System.out.println(multi.getFilesystemName("upload"));
} catch (IOException e) {
System.out.println("[에러] " + e.getMessage());
}
return "write_ok";
}
5) 입력 받는 코드 (get 메서드)
<form action="write_ok.do" method="post" enctype="multipart/form-data">
데이터: <input type="text" name="data" /> <br /><br />
파일: <input type="file" name="upload" />
<input type="submit" value="전송" />
</form>
입력받는 페이지가 위와 같을 때 이것을 처리하는 controller 코드는 다음과 같다.
@RequestMapping("/write_ok.do")
public String write_ok(HttpServletRequest request, HttpServletResponse response) {
String uploadPath="C:\\Java\\java\\spring-workspace\\SpringWebEx01\\src\\main\\webapp\\upload";
int maxFileSize = 1024 * 1024 * 2;
String encType = "utf-8";
MultipartRequest multi = null;
try {
multi = new MultipartRequest(request, uploadPath, maxFileSize, encType, new DefaultFileRenamePolicy());
System.out.println(multi.getOriginalFileName("upload"));
System.out.println(multi.getFilesystemName("upload"));
// text로 받을 때
System.out.println(multi.getParameter("data"));
} catch (IOException e) {
System.out.println("[에러] " + e.getMessage());
}
return "write_ok";
}
파일은 아래의 두개 메서드를 사용해서 입력받은 값을 가져오고
- getOriginalFileName() : 사용자가 입력 폼에서 직접 지정한 파일명을 리턴한다.
- getFilesystemName() : type의 속성값이 file 인 input 태그에서 사용자가 선택한 파일 이름이 아니다. 사용자가 선택한 파일 이 실제로 서버상의 폴더에 저장되었을 때의 파일명을 리턴한다. 왜냐하면 업로드시 파일명이 변경될 수 있기 때문이다.
텍스트는 getParameter()를 사용한다.
3-7. 파일 업로드하기 - common-io / common-fileupload
> SpringWebEx01
1) lib 가져와서 pom.xml에 추가하기
> pom.xml
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2) 입력받는 파일 설정해주기 (파일크기, 언어 등 )
아래는 cos.jar 방식일때 controller 에서 이를 처리하는 방법이다.
common-io / common-fileupload 방식일 땐 위와 다르다.
파일 크기 등 제한 사항들을 servlet-context.xml에서 beans로 선언하고 들어간다.
이때 크기 설정에서 value 값으로 연산자가 못들어가서 곱한후의 값 여기선 1Mbyte인 1040576을 쓴다.
임시데이터로 입력 파일을 잡고 그걸 넣어주는 형식이기 때문에 그 임시데이터의 크기 설정도 필요하다.
> webapp > WEB-INF > spring > appServlet > servlet-context.xml
<!-- Upload Component 설정 -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.common.CommonsMultipartResoulver">
<beans:property name="maxUploadSize" value="1040576" />
<!-- 임시데이터 크기 설정 -->
<beans:property name="maxInMemorySize" value="1040576" />
<beans:property name="defaultEncoding" value="utf-8" />
</beans:bean>
3) 입력 받는 코드 (get 메서드)
> HomeController.java
@RequestMapping("/write_ok2.do")
public String write_ok2(@RequestParam("upload") MultipartFile multipartFile) {
System.out.println("업로드 이름 : " + multipartFile.getName());
System.out.println("파일 이름 : " + multipartFile.getOriginalFilename());
System.out.println("파일 사이즈 : " + multipartFile.getSize());
return "write_ok";
}
- getOriginalFileName() : 사용자가 입력 폼에서 직접 지정한 파일명을 리턴한다.
- geName() : 입력 받는 페이지의 입력 태그 name을 리턴한다.
- getSize() : 업로드한 파일 크기를 리턴한다.
여기까진 임시데이터로 버퍼에 저장한 상태도 실질적으로 업로드는 여기서부터다.
4) 실제 업로드
// 파일 이름이 중복되면 오버라이팅됨 => DefaultRenamePolicy로 해결 가능
@RequestMapping(value = "/write_ok2.do")
public String write_ok2(@RequestParam("upload") MultipartFile multipartFile) {
System.out.println("업로드 이름 : " + multipartFile.getName());
System.out.println("파일 이름 : " + multipartFile.getOriginalFilename());
System.out.println("파일 사이즈 : " + multipartFile.getSize());
FileOutputStream fos = null;
try {
String uploadPath="C:\\Java\\java\\spring-workspace\\SpringWebEx01\\src\\main\\webapp\\upload";
fos = new FileOutputStream(uploadPath + "\\" + multipartFile.getOriginalFilename());
fos.write(multipartFile.getBytes());
} catch (FileNotFoundException e) {
System.out.println("[에러] " + e.getMessage());
} catch (IOException e) {
System.out.println("[에러] " + e.getMessage());
}
return "write_ok";
}
이런 파일 말고 json, xml, csv파일 업로드 방법도 알아야한다.
3-8. json, xml 파일 업로드
1) json-simple을 추가
2) view 페이지에 json데이터 출력
두가지 방법이 있다.
1. controller는 그냥 두고 view페이지에서 JSONArray와 JSONObject로 our.println하는 방법
> json1.jsp
<%@ page language="java" contentType="text/json; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="org.json.simple.JSONArray" %>
<%@ page import="org.json.simple.JSONObject" %>
<%
JSONArray jsonArray = new JSONArray();
JSONObject obj1 = new JSONObject();
obj1.put("name", "name1");
obj1.put("publisher", "publisher1");
obj1.put("author", "author1");
obj1.put("price", "price1");
JSONObject obj2 = new JSONObject();
obj2.put("name", "name2");
obj2.put("publisher", "publisher2");
obj2.put("author", "author2");
obj2.put("price", "price2");
jsonArray.add(obj1);
jsonArray.add(obj2);
out.println(jsonArray);
%>
2. view페이지는 그냥 두고 controller에서 Map으로 구현하는 방법
> HomeController.java
@RequestMapping(value = "/json2.do")
@ResponseBody
public String json2(Locale locale, Model model) {
Map<String, String> map = new HashMap<String, String>();
map.put("name", "name1");
map.put("publisher", "publisher1");
map.put("author", "author1");
map.put("price", "price1");
return JSONValue.toJSONString(map);
}
오브젝트는 Map이고 그걸 배열에 담고 싶으면 List를 사용하면된다.
> HomeController.java
@RequestMapping(value = "/json2.do")
@ResponseBody
public String json2(Locale locale, Model model) {
List<Map> lists = new ArrayList<Map>();
Map<String, String> map1 = new HashMap<String, String>();
map1.put("name", "name1");
map1.put("publisher", "publisher1");
map1.put("author", "author1");
map1.put("price", "price1");
Map<String, String> map2 = new HashMap<String, String>();
map2.put("name", "name1");
map2.put("publisher", "publisher1");
map2.put("author", "author1");
map2.put("price", "price1");
lists.add(map1);
lists.add(map2);
return JSONValue.toJSONString(lists);
}
3-9. 데이터베이스 연결하기(1) - 직접연결
> SpringWebEx03
Spring에서 제공하는 jdbc 데이터베이스 연동 라이브러리를 사용한다.
1) mariadb를 pom.xml에 추가
> pom.xml
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.7.1</version>
</dependency>
2) Spring JDBC를 pom.xml에 추가
3) spring-jdbc를 pom.xml에 추가한 후, 내 프로젝트 jdbc 버전과 맞게 버전 수정 후 저장
> pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
${org.springframework-version} 이걸 쓰면 내가 가지고 있는 것과 맞는 버전으로 세팅된다.
4) 데이터베이스와 관련한 설정 해주기
> root-context.xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.mariadb.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3307/sample" />
<property name="username" value="root" />
<property name="password" value="!123456" />
</bean>
servlet-context.xml에 넣어도 된다.
> servlet-context.xml
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="org.mariadb.jdbc.Driver" />
<beans:property name="url" value="jdbc:mysql://localhost:3307/sample" />
<beans:property name="username" value="root" />
<beans:property name="password" value="!123456" />
</beans:bean>
공통적인 부분이기때문에 root-context.xml에 넣는것이 더 효율적이다.
5) 데이터베이스 연동
[ @Autowired ]
> HomeController.java
@Controller
public class HomeController {
@Autowired
private DataSource dataSource;
@RequestMapping(value = "/jdbc1.do")
public String jdbc1(Locale locale, Model model) {
// System.out.println("dataSource : " + dataSource);
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
String sql = "select now() as now";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
if(rs.next()) {
System.out.println("현재 시간 : " + rs.getNString("now"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(rs != null) try {rs.close();} catch(SQLException e) {}
if(pstmt != null) try {pstmt.close();} catch(SQLException e) {}
if(conn != null) try {conn.close();} catch(SQLException e) {}
}
return "jdbc1";
}
}
@Autowired 는 자동 검색 기능이다. 내부적으로 인스턴스화 된걸 찾아준다.
DataSource, JdbcTemplate, SampleDAO 등 인스턴스화가 필요한 것들을 new를 하지 않고 선언만 해주면 된다.
하지만 여전히 데이터베이스 연동코드가 매우 길다. 스프링에선 이부분을 간단한 코드로 작성할 수 있게 JDBC 코드용 기본 템플릿을 제공하고 있다. 그게 jdbcTemplate이다.
3-10. 데이터베이스 연결하기(2) - JdbcTemplate
[ JdbcTemplate ]
스프링에서 제공하는 SQL 연산들을 수행 할 수 있도록 해주는 JDBC 코드용 기본 템플릿을 말한다.
Spring Framework는 JdbcTemplate 클래스를 제공하며 반복코드 없이 손쉽게 DB와 연동할 수 있도록 구현되어 있다.
그 동안은 db에 연결하기 위해서는 여러가지를 선언해주어야 했다.
DriverManager, Connection..등등
JdbcTemplate을 이용하여 이런 것들을 통합하여 쉽게 데이터베이스와 연동할 수 있다.
세개의 메서드를 사용가능하다.
- update() : 주로 SQL 연산을 통해 데이터베이스를 갱신시켜줄 때 사용한다.
- queryForObject() : select 쿼리를 실행하여 한개의 객체를 받아올 때 사용한다.
- query() 또는 queryForList() : queryForInt()가 하나의 결과 값을 위한 메소드인 반면, 많은 결과 값(로우 값)을 처리 할 수 있 는 메소드이다.
root-context.xml에 아래 코드를 추가한다.
<!-- 데이터베이스 설정정보를 jdbc template이 가져감 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- <constructor-arg ref="dataSource"/> -->
<property name="dataSource" ref="dataSource" />
</bean>
그리고 위쪽의 긴 코드를 jdbcTemplate를 사용하면 아래와같이 짧아진다.
> HomeController.java
@Controller
public class HomeController {
@Autowired
private JdbcTemplate jdbcTemplate;
// jdbcTemplate 사용
@RequestMapping(value = "/jdbc2.do")
public String jdbc2(Locale locale, Model model) {
// System.out.println("jdbcTemplate : " + jdbcTemplate);
// 데이터를 Object 형태로 가져온다. 다른것 형태로 해도 된다.
String result = jdbcTemplate.queryForObject("select now()", String.class);
System.out.println("result : " + result);
return "jdbc1";
}
}
그럼 model2 방식 처럼 dao를 사용해보자.
데이터베이스 연결은 dao에서 이뤄져야 하므로 jdbcTemplate을 dao에서 사용하게 된다.
> HomeController.java
@Controller
public class HomeController {
@Autowired
private SampleDAO dao;
// spring한테 인스턴스화 된걸 가져오게 맡김 ( 아래에 new로 되었던게 없어짐 )
// @Autowired + jdbcTemplate + dao
@RequestMapping(value = "/jdbc3.do")
public String jdbc3(Locale locale, Model model) {
// 생성자로 jdbcTemplate부를때
// SampleDAO dao = new SampleDAO(jdbcTemplate);
// @Autowired로 jdbcTemplate 부를때
// SampleDAO dao = new SampleDAO();
System.out.println(dao.selectNow());
return "jdbc1";
}
}
> SampleDAO.java
@Repository
public class SampleDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
// controller에서 dao에 @Autoowired 사용하지 않을 때
// public SampleDAO(JdbcTemplate jdbcTemplate) {
// this.jdbcTemplate = jdbcTemplate;
// }
public String selectNow() {
System.out.println("jdbcTemplate : " + jdbcTemplate);
String result = jdbcTemplate.queryForObject("select now()", String.class);
return result;
}
}
응용실습) 직접연결과 JdbcTemplate를 사용한 우편번호 검색기
> ZipcodeMVCEx03
1. DataSource
2. JdbcTemplate
google/naver