190718_Day69 서플릿 필터, 리스너, 파일업로드
<서블릿 필터>
사용자 요청에 따라 서블릿이나 JSP의 실행 전후, 필요에 따라 기능을 추가, 삭제해주는 역할
보통 클라이언트의 요청을 서블릿이 받기 전에 가로채어 필터에 작성된 내용을 수행 하는 것
인증, 로깅/감사, 이미지변환, 데이터압축, 암호화 등..
javax.servlet.Filter
util이라는 패키지에 넣어봤습니다~
환경설정 필요
Web.xml (WEB-INF안에)
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd "> <!-- 리스너 등록(0718오후) --> <listener> <listener-class>t0718.MyListener</listener-class> </listener> <!-- 전체 서블릿과 JSP에서 공유할 데이터 (text) 정의 --> <context-param> <param-name>common</param-name> <param-value>진꼬복 많이 받으세요 :)</param-value> </context-param> <!-- 경로 변경시 이미지 쉽게 루트 변경하려면! --> <context-param> <param-name>imgPath</param-name> <param-value>/TomTest/image</param-value> <!-- 이제 여기만 고치면 되네! --> </context-param> <context-param> <param-name>rootPath</param-name> <param-value>/TomTest</param-value> </context-param> <!-- 필터 클래스 등록 --> <filter> <filter-name>enc</filter-name> <!-- 아무거나! --> <filter-class>util.enc.EncFilter</filter-class> <init-param> <description>설명은 여기에 적어, encoding초기값</description> <param-name>encType</param-name> <!-- 얘를 EncFilter.java에서 가져다 씀 --> <param-value>UTF-8</param-value> <!-- EncFilter 무시하고 이 값으로 감 --> </init-param> </filter> <filter-mapping> <filter-name>enc</filter-name> <!-- 아무거나! --> <url-pattern>*.jsp</url-pattern> </filter-mapping> <!-- 서블릿 클래스 등록 --> <servlet> <servlet-name>my</servlet-name> <servlet-class>t0708.MyServlet</servlet-class> <init-param> <param-name>youName</param-name> <param-value>아무개</param-value> </init-param> </servlet>
<!-- (서블릿 클래스에 매핑될) 가상의 경로 설정 -->
<servlet-mapping>
<servlet-name>my</servlet-name>
<url-pattern>/gildong/my</url-pattern>
<!-- url-pattern엘리먼트 내의 맨 앞의 '/'는 (컨텍스트)루트를 의미!!
예) /gildong
===> http://localhost:8282/TomTest/gildong
-->
</servlet-mapping>
<!-- 카운트 서블릿등록 -->
<servlet>
<servlet-name>cnt</servlet-name>
<servlet-class>com.encore.t0708.CountServlet</servlet-class>
</servlet>
<!-- 카운트 서블릿에 매핑할 가상경로 정의 -->
<servlet-mapping>
<servlet-name>cnt</servlet-name>
<url-pattern>/cnt</url-pattern>
</servlet-mapping>
<!-- 카운트 서블릿등록2 -->
<servlet>
<servlet-name>cnt2</servlet-name>
<servlet-class>com.encore.t0708.CountServlet2</servlet-class>
</servlet>
<!-- 카운트 서블릿에 매핑할 가상경로 정의2 -->
<servlet-mapping>
<servlet-name>cnt2</servlet-name>
<url-pattern>/cnt2</url-pattern>
</servlet-mapping>
<!-- 파라미터서블릿등록 -->
<servlet>
<servlet-name>param</servlet-name>
<servlet-class>com.encore.t0709.ParamServlet</servlet-class>
</servlet>
<!-- 파라미터서블릿에 대한 가상경로 등록 -->
<servlet-mapping>
<servlet-name>param</servlet-name>
<url-pattern>/0709/result</url-pattern>
</servlet-mapping>
<!--
<error-page>는 에러발생동기와 ==> <error-code> 또는 <exception-type>
에러발생시 이동할 페이지의 정보를 저장 ==> <location>
-->
<!--
<error-page>
<error-code>500</error-code>
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/0711/error.jsp</location>
</error-page>
-->
<!--
<welcome-file-list>에는 페이지 명시 없을 때 보여줄 화면 페이지를 설정
- 페이지 명시하는 경우 : http://192.168.0.96:8282/TomTest/hello.jsp
- 페이지 명시하지 않는 경우 : http://192.168.0.96:8282/TomTest
<welcome-file>태그 중 위쪽에 명시된 페이지가 우선 순위가 높다.
만약 TomTest폴더 밑에 아래의 index.html, index.jsp, hello.jsp파일이
전부 있다면 index.html이 화면에 자동 출력됨.
-->
<session-config>
<session-timeout>1</session-timeout>
<!-- TomTest(WebContext) 안에 모든 페이지에 대해 '분' 단위의 세션유지 시간 설정 -->
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>hello.jsp</welcome-file>
</welcome-file-list>
</web-app>
EncFilter.java
package util.enc;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EncFilter implements Filter
{
private String encType;
@Override
public void init(FilterConfig config) throws ServletException
{
// System.out.println("init()");
// config 통해서 web.xml에 정의된 param을 읽기 가능
encType = config.getInitParameter("encType");
}
@Override
public void destroy()
{
// System.out.println("destroy()");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
// System.out.println("doFilter()");
if (encType != null) // web.xml에 encType이 정의되었다면
{
request.setCharacterEncoding(encType);
} else
{
request.setCharacterEncoding("UTF-8");
}
// doFilter와 페이지 연결 하려면
chain.doFilter(request, response);
// 다른 필터 혹은 요청 페이지와의 연결 진행
}
}
input.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>입력폼</title>
</head>
<%-- input.jsp (입력폼) --%>
<body>
<h3>입력폼</h3>
<hr>
<%
String youName = getServletConfig().getInitParameter("youName");
out.print("당신의 이름은 "+ youName+"<br>");
//application == ServletContext
String msg = application.getInitParameter("common");
out.print("<font color=green>서버의 메시지 :["+msg+"]</font><br>");
%>
${book }<br>
책제목: ${book.title } <br>
<form method="post" action="result.jsp">
이름: <input type="text" name="username"><br>
<button>전송</button>
</form>
</body>
</html>
result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파라미터 전송결과</title>
</head>
<%--result.jsp --%>
<body>
<h3>파라미터 전송결과</h3>
<hr>
전달 이름:
<%= request.getParameter("username") %>
</body>
</html>
web.xml에서 t0708/MyServlet 부분 서블릿 추가
ServletConfig 는 하나
ServletContext 는 여러개!
MyServlet.java(t0708)
package t0708;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet{
//서블릿 : 한개의 웹페이지 화면을 구성!!
@Override
public void init() throws ServletException {
System.out.println("init()");
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("service()");
//서블릿 서비스 메소드 == 웹브라우저 서비스!! ==> HTML 서비스
//request:클라이언트(사용자, 브라우저), response : 서버를 각각 의미
// (한글)문자집합 설정
response.setContentType("text/html;charset=UTF-8");
// text/html => MIME형식
// 입력:text 출력:html => out.print() 메소드를 통해 전달되는 text를 브라우저에게 html해석하시오!
//text:plane; text:xml; 이런식으로 형식을 줄 수 있다!
PrintWriter out = response.getWriter();
//PrintWriter out ==> 브라우저 출력 객체를 의미함.
//out.print("HTML코드(텍스트)");
out.print("<html><head><title></title></head>");
out.print("<body><h3>ServletTest</h3></hr>");
//190708 여기 추가
//web.xml에 등록된 initParam데이터 가져오기
ServletConfig config = getServletConfig(); // 현재 서블릿
String name = config.getInitParameter("youName");
String name2 = getInitParameter("youName");
out.print("name : " + name + ", name2 : " + name2 );
ServletContext application = getServletContext();
//TomTest와 같은 웹어플리케이션
String commonTxt = application.getInitParameter("common");
out.print("<font color=green>" + commonTxt + "</fong><br>");
out.print(application.getAttribute("book" + "<br>"));
//이 위까지 190708 추가
for (int i = 0; i < 10; i++) {
if(i%2==0)
out.println("<b><font color = red>용진</font></b><br>");
if(i%2==1)
out.println("<b><font color = blue>진주</font></b><br>");
}
out.print("</body></html>");
}
@Override
public void destroy() {
System.out.println("destroy()");
}
}
input.jsp에 추가
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>입력폼</title>
</head>
<%-- input.jsp (입력폼) --%>
<body>
<h3>입력폼</h3>
<hr>
<%
String youName = getServletConfig().getInitParameter("youName");
out.print("당신의 이름은 "+ youName+"<br>");
//application == ServletContext
String msg = application.getInitParameter("common");
out.print("<font color=green>서버의 메시지 :["+msg+"]</font><br>");
%>
${book }<br>
책제목: ${book.title } <br>
<form method="post" action="result.jsp">
이름: <input type="text" name="username"><br>
<button>전송</button>
</form>
</body>
</html>
어디에 쓰는데 이걸? 이미지 한곳에 모아놨었는데, 그 폴더에 없고 예를 들어 coffee 폴더 안에 있어...경로가 달라졌어!
그럼 그림 안나옴 ㅠㅠ
이미지 수십개 썼으면, 해당 jsp 가서 다 수정할거야? 아니지?
문제가 되는 페이지에 가서 수정하는게 아니라
web.xml에 등록하고
<context-param> <param-name>imgPath</param-name> <param-value>/TomTest/image</param-value> <!-- 이제 여기만 고치면 되네! --> </context-param>
해당하는 imgPath value값만 바꾸면 된다!
0717에 service.jsp에서 사진을
<img src="<%= application.getInitParameter("imgPath")%>/ebi.gif" width="400" height="300"> <img src="${initParam.imgPath }/ebi.gif" width="400" height="300">
- 이렇게 수정함, 적용 잘 됨!
- 너무 길면 ${initParam.imgPath }
<리스너>
- 특정 인터페이스를 구현하는 자바클래스
- web.xml의 리스너 설정 항목에 기술해두면 웹 애플리케이션 시작 시 자동으로 실행되어 모든 애플리케이션에서 참조할 객체 생성등을 수행
web.xml 에 리스터 등록
<listener>
<listener-class>t0718.MyListener</listener-class>
</listener>
MyListener.java
package t0718;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyListener implements ServletContextListener
{
@Override
public void contextDestroyed(ServletContextEvent sce)
{
// 끝날 때
//System.out.println("contextDestroyed");
}
@Override
public void contextInitialized(ServletContextEvent sce)
{
// 시작할 때
//System.out.println("contextInitialized");
//전체 웹어플리케이션에서 공유할 객체 저장
ServletContext application = sce.getServletContext();
application.setAttribute("book", new Book());
}
}
<파일 업로드>
- 사용자(클라이언트) PC내의 파일 -> 서버의 특정 디렉토리에 저장!
- <파일업로드 규칙>
- form태그의 method속성은 반드시 post!
- form태그의 속성 enctype="multipart/form-data" 추가!
- 폼내의 데이터들을 text가 아닌 stream으로 전송!
- input.jsp
- 참고) enctype = "application/x-www-form-urlencoded"
- 기본값
- form태그내의 name데이터들을 text로 전달!
- <파일 업로드 구현>
- inputFile.jsp : 폼제공
- resultFile.jsp : inputstream을 통해 파일 업로드 구현, 실행
inputFile.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>입력폼</title>
</head>
<%--inputFile.jsp --%>
<body>
<h3>입력폼</h3>
<hr>
<form action="resultFile.jsp" method="post"
enctype="multipart/form-data" >
이름: <input type="text" name="username"><br>
파일: <input type="file" name="myfile"><br>
<button>전송</button>
</form>
</body>
</html>
resultFile.jsp
<%@page import="java.io.FileWriter"%>
<%@page import="java.io.InputStreamReader"%>
<%@page import="java.io.BufferedReader"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과페이지</title>
</head>
<%--resultFile.jsp --%>
<body>
<h3>결과페이지</h3>
<hr>
이름: <%=request.getParameter("username") %> <br>
파일: <%=request.getParameter("myfile") %> <br>
<hr color="red">
<%
ServletInputStream sis = request.getInputStream();
BufferedReader br = new BufferedReader
(new InputStreamReader(sis,"UTF-8"));
String delimiter = br.readLine();//구분자역할을 하는 문자열
//"------WebKitFormBoundarys29EFHDUPZj87Yvt"
String str;
int count=0;
while( (str=br.readLine()) != null ){
count++;
// out.print(str+"<br>");
if(str.contains("name=\"myfile\"")){
System.out.println(count+"째줄에서 myfile을 찾았다!!");
//파일명 찾기
int startIdx = str.lastIndexOf("=")+2;
int endIdx = str.length()-1;
String fileName = str.substring(startIdx, endIdx);
//"애국가.txt"
FileWriter fw = new FileWriter
(application.getRealPath("/upload/")+ fileName);
//e:/jaelee/workspace2/TomTest2/upload/애국가.txt
br.readLine();
br.readLine();//두줄 skip
while( (str=br.readLine()) != null ){
if(str.contains(delimiter)) break;
out.print(str+"<br>");//브라우저화면 출력
fw.write(str+"\r\n");//파일 출력
}//while
fw.close();
}//if
}//while
//애국가.txt파일의 내용을 브라우저 화면에 출력하자!!
//애국가.txt파일을 upload폴더에 생성하고 내용을 파일출력하자!!
%>
</body>
</html>
<파일 업로드 툴>
- cos-20.08.zip
위의 툴을 사용해서 만들어 보자!
압축 풀고 lib 폴더에 jar 파일 넣고 빌드패스!
inputFile2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>입력폼</title>
</head>
<%--inputFile.jsp --%>
<body>
<h3>입력폼(파일업로드 : COS.jar - MultipartRequest 객체 사용 )</h3>
<hr>
<form action="resultFile2.jsp" method="post"
enctype="multipart/form-data" >
이름: <input type="text" name="username"><br>
파일: <input type="file" name="myfile"><br>
<button>전송</button>
</form>
</body>
</html>
resultFile2.jsp
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>결과페이지(파일업로드)</h3>
<%
//MultipartRequest(HttpServletRequest request, String saveDirectory)
//MultipartRequest(HttpServletRequest request, String saveDirectory,
//String encoding)
//MultipartRequest(HttpServletRequest request, String saveDirectory,
//int maxPostSize, String encoding, FileRenamePolicy policy)
String saveDir=application.getRealPath("/upload");
//---> "e:/jaelee/workspace2/TomTest/upload"
int maxSize= 5 * 1024 * 1024; //업로드 될 파일의 크기 제한, 단위:byte
// 5byte 5Kb 5Mb
MultipartRequest mreq = new MultipartRequest
(request,saveDir, maxSize, "UTF-8", new DefaultFileRenamePolicy());
//MultipartRequest생성자 호출 == 파일업로드 !
out.print("파일 업로드 성공 ~ !");
String name = mreq.getParameter("username");
%>
<br>
이름 : <%= name %><br>
원본파일명 : <%= mreq.getOriginalFileName("myfile") %><br>
저장파일명 : <%= mreq.getFilesystemName("myfile") %><br>
</body>
</html>
궁금상자
context-param
init-param
context-param(컨텍스트 초기화 파라미터)
- <web-app> 항목내 작성
- 범위 : 웹 애플리케이션 내에 모든 서블릿, jsp
init-param(서블릿 초기화 파라미터)
- <servlet> 항목내 작성
- 범위 : <init-param>항목을 포함하는 서블랏만
'클라우드 기반 웹 개발자 과정 공부 > Servlet & JSP' 카테고리의 다른 글
190717_Day68 <회원가입 미션> (0) | 2019.07.17 |
---|