2023.07.26 수업
● 필터
- HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 코드
- 어플리케이션의 모든 HTTP Request에 대해서 감지를 할 수 있는 기능
- 이름 그대로 필터의 역할
참고용
2023.06.29 - [백엔드/웹 개발] - 로그인, 로그아웃 구현하기(필터)
로그인, 로그아웃 구현하기(필터)
2023.06.28수업 - 교재 : 자바 웹 개발 워크북 ※ 브라우저 개발자도구(f12) Network : 현재 접속된 주소의 진행사항 Application : 쿠키, 브라우저에 저장된 내용 Element : 홈페이지 요소(html, css 등을 보여줌)
dustj0824.tistory.com
▷ 다이나믹웹프로젝트 만들기
프로젝트명 : FilterEncodingExam
▷ 폼 작성용 jsp 파일 만들기
- 화면 구현 파일
- 약식 모델2 방식
경로 : FilterEncodingExam/src/main/webapp
파일명 : index.jsp
<%@ 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>
<link href="${ pageContext.request.contextPath }/css/styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<%-- 약식 모델2 방식 (서블릿, jsp) --%>
<div class="encoding">
<form action="encoding" method="post">
이름<input type="text" name="name" value="홍길동"> <br />
나이<input type="text" name="age" value="35"> <br />
장소<input type="text" name="place" value="한양"> <br />
<input type="submit" />
</form>
</div>
<script src="${ pageContext.request.contextPath }/js/index.js"></script>
</body>
</html>
* pageContext.request.contextPath
- 상대경로, 현재 위치를 기준으로 목표로하는 위치, 현재 위치의 문서를 기준으로 경로 인식
- contextPath가 변경되어도 소스 수정없이 적용 가능
- EL표현식을 통해 간편하게 사용
* pageContext : 웹 컨테이너가 JSP실행시 자동으로 생성하여 제공하는 내장객체
[다른 방법1]
컨텍스트 이름(test or /(root))을 직접 입력하는 방법
<a href="/test/test01/memberForm.jsp">
[다른 방법2]
getContext() 메서드를 이용해 컨텍스트 이름을 가져오는 방법
<a href="<%=reqeust.getContextPath() %>/test01/memberForm.jsp>
▷ CSS
경로 : FilterEncodingExam/src/main/webapp
파일명 : css/styles.css (폴더까지 만들기)
- form(jsp파일)의 디자인
- 클래스이름을 활용하여 css 하기
@charset "UTF-8";
/* 한글 테스트용 */
.encoding {
text-align: center;
font-size: 20px;
color: red;
border: 5px solid blue;
}
▷ 자바스크립트
경로 : FilterEncodingExam/src/main/webapp
파일명 : js/index.js (폴더까지 만들기)
- 한글이 잘 나오는지 검사용
/* 한글 테스트 */
for(let i = 0; i < 10; i++) {
document.write(`${i} <= ${ (i + 1) }입니다. <br />`)
}
▷ 서블릿
경로 : /FilterEncodingExam/src/main/java
패키지명 : apple.orange.servlet
클래스명 : EncodingServlet
- doPost만 사용
- JSP의 form을 통해 입력받은 자료를 읽어옴
package apple.orange.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class EncodingServlet
*/
@WebServlet("/encoding")
public class EncodingServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
PrintWriter out = res.getWriter();
String name = req.getParameter("name");
String age = req.getParameter("age");
String place = req.getParameter("place");
// echo 출력
out.print("이름은 " + name + "<br />");
out.print("나이는 " + age + "<br />");
out.print("장소는 " + place + "<br />");
out.print("<hr>");
}
}
▷ 실행 : run on server
-> 한글이 깨져보임
* Filter Life Cycle(생명주기)
init(최초 한번 실행) -> doFilter -> destory(WAS 종료 전 처리)
▷한글 깨짐현상을 해결하기 위한 필터 만들기
경로 : /FilterEncodingExam/src/main/java
패키지 : apple.orange.filter
클래스 : EncodingFilter
- 모든 url에 대하여 적용 ( /* )
- EncodingFilter extends HttpFilter(클래스 상속) implements Filter (인터페이스 상속)
- doFilter활용
* request.setCharacterEncoding("utf-8");
- 들어오는 파라미터를 UTF-8로 해석한다
- 폼 태그에서 입력한 값을 전송할 때는 GET방식과 POST방식으로 나뉘는데 POST방식으로 보내는 값이 '한글'일 경우 깨지지 않게 전달하기 위해 사용하는 것이다.
* response.setCharacterEncoding("utf-8");
- 서블릿이 HTML 파일을 만들 때 UTF-8 로 쓰기
- 웹 브라우저에게 한글이 포함되어 있으니 잘 표시하라고 알려주는 역할
* response.setContentType("text/html;charset=utf-8");
- HTML이 UTF-8 형식이라는 것을 브라우저에게 알리는 것
package apple.orange.filter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 요청이 들어오면 그 요청을 서블릿이 처리하기 전 또는 후에 마지막 추가처리를 하는 기능
// 웹브라우저 요청 > 필터 > 서블릿 > JSP뷰 > (정리)필터
@WebFilter("/*")
public class EncodingFilter extends HttpFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 공통필터 적용 시작
// 요청객체로부터 읽어오는 데이터를 무조건 UTF-8(유니코드)로 해석해라
request.setCharacterEncoding("UTF-8");
// 브라우저로 응답할때 기본 데이터 쓰기 절정을 UTF-8로 설정해라
// 이후 출력은 모두 UTF-8로 해석이 됨
response.setCharacterEncoding("UTF-8");
// 이후부터 모든 HTML관련 파일들을 UTF-8로 변환
// CSS, JS는 마임파일 타입이 text/css text/javascript이므로 문제 발생
// 그래서 한글설정을 하면 css, js파일들이 일부 실행안되는 문제 발생
// 아래의 방식으로 변경하여 해결
response.setContentType("text/html; charset: UTF-8");
// 위의 3가지 설정으로 필터 적용하기
// pass the request along the filter chain
chain.doFilter(request, response);
System.out.println("필터적용 완료");
}
}
▷ 필터 적용 후 실행
* 필터를 적용하여 실행 후 css를 수정하면 반영이 안됨
res.setContentType("text/html; charset: UTF-8"); 때문
그렇다고 작성하지 않으면 한글이 깨짐
▷ css 반영 안됨 문제 해결을 위해 필터에 내용 추가
- 정규표현식 활용하기
- pattern객체에 검색할 원본문자열에서 제거하고 싶은 또는 포함하고 있는지를 검사하고 있는 비교할 문자패턴을 등록
- 필터처리를 위한 요청객체와 응답객체를 웹프로토콜로 다운캐스팅
package apple.orange.filter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class EncodingFilter
*/
// 요청이 들어오면 그 요청을 서블릿이 처리하기 전 또는 후에 마지막 추가처리를 하는 기능
// 웹브라우저 요청 > 필터 > 서블릿 > JSP뷰 > (정리)필터
@WebFilter("/*")
public class EncodingFilter extends HttpFilter implements Filter {
/* css 반영 안됨 문제 해결 */
// Pattern : 자바에서 정규표현식 객체
private static final Pattern excludeUrls = Pattern.compile(
"^.*/(css|js|images|ckeditor)/.*$",
Pattern.CASE_INSENSITIVE);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
/* css 반영 안됨 문제 해결 */
// 필터처리를 위한 요청객체와 응답객체를 웹프로토콜로 다운캐스팅
// 현재 우리가 다루는 프로토콜은 웹관련 프로토콜이므로 굳이 객체의 타입을 조사하여
// 자식클래스 타입으로 변환할 필요는 없다
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// req(웹 요청객체), res(웹 응답객체)
// getRequestURI() : 웹 브라우저에서 요청한 요청주소 중에서
// 프로토콜, 서버주소, 포트번호를 뺀 요청처리에 관련한 나머지 주소
// http://localhost:8080/api/index.jsp라면
// 프로토콜 http:// 제거
// localhost:8080 서버주소 제거
// /api/index.jsp 요청 uri가 된다(getRequestURI)
// index.jsp : 실제 실행하는 앱이름 = 요청 애플리케이션 컨텍스트(request.getContextPath)
// 컨텍스트만 남기기 위해서
String path = req.getRequestURI().substring(req.getContextPath()
.length()).replaceAll("[/]+$", "");
// 공통필터 적용 시작
// 요청객체로부터 읽어오는 데이터를 무조건 UTF-8(유니코드)로 해석해라
request.setCharacterEncoding("UTF-8");
// 브라우저로 응답할때 기본 데이터 쓰기 절정을 UTF-8로 설정해라
// 이후 출력은 모두 UTF-8로 해석이 됨
response.setCharacterEncoding("UTF-8");
// 이후부터 모든 HTML관련 파일들을 UTF-8로 변환
// CSS, JS는 마임파일 타입이 text/css text/javascript이므로 문제 발생
// 그래서 한글설정을 하면 css, js파일들이 일부 실행안되는 문제 발생
// 아래의 방식으로 변경하여 해결
// response.setContentType("text/html; charset: UTF-8");
// 공통필터 적용 끝
// 허용불가경로 포함여부 판별
Matcher matcher = excludeUrls.matcher(path);
boolean isPathExcluded = matcher.find();
// 허용불가 경로가 아니면
if(!isPathExcluded) {
response.setContentType("text/html; charset: UTF-8");
System.out.println("허용불가 경로 아님" + path);
} else {
}
// 위의 3가지 설정으로 필터 적용하기
// pass the request along the filter chain
chain.doFilter(request, response);
System.out.println("필터적용 완료");
}
}
※ Pattern 활용: 자바에서 정규표현식 객체
(css|js|images|ckeditor)
Pattern.compile() : 비교할 목록리스트를 만들어라
"^.* : '\n' 개행문자를 제외한 모든 문자들
[정규표현식]
^ : 문자열 시작
. : '\n' 개행문자를 뺀 모든 문자들
* : 앞의 문자패턴을 여러번 반복해라
(...) : ()안의 내용을 그룹으로 묶음 분리, list의 효과
| : or, ()안의 내용들 중에 하나
$ : 앞의 그룹 문자들로 끝나는지
CASE_INSENSITIVE 대소문자 구분하지 않음
시작/.../끝 : 시작패턴(^.*), 끝의 패턴(.*$)을 포함하는가?
※ 다운캐스팅
req(웹 요청객체), res(웹 응답객체)
getRequestURI() : 웹 브라우저에서 요청한 요청주소 중에서
프로토콜, 서버주소, 포트번호를 뺀 요청처리에 관련한 나머지 주소
http://localhost:8080/api/index.jsp라면
프로토콜 http:// 제거,
localhost:8080 서버주소 제거,
/api/index.jsp 요청 uri가 된다(getRequestURI)
index.jsp : 실제 실행하는 앱이름 = 요청 애플리케이션 컨텍스트(request.getContextPath)
* replaceAll("[/]+$", "")
-> "[/]+$"패턴을 "" 공백으로 변경해라
[정규표현식]
...$ : ...단어로 끝나는가(문장의 끝)
^... : ...단어로 시작하는가(문장의 시작)
[...] : []안의 ...문자가 어떤 것이든 OK
* : 0부터 많음, 문자 또는 숫자 등의 수가 제한 없음
+ : 1부터 많음, 문자 또는 숫자 등의 수가 제한 없음
[/]+$ : 문자열의 끝에 '/'인 문자를 포함하면
▷ css 변경 후 실행
- 실행중인 서버를 종료하고 변경 내용 저장하여 재실행하기
- 재실행 후 css 변경하고 저장하면 바로 적용이 됨
@charset "UTF-8";
.encoding {
text-align: center;
font-size: 20px;
color: pink;
border: 1px solid grey;
}
추후 스프링 프로젝트를 진행하며 한글깨짐 현상을 해결하기 위해 필터를 만들었을때
css 파일적용이 안되는 경우가 있어 그것을 해결하기 위한 코드를 배운 것인데
Window > Preferences 설정 을 활용해도 되고,
해당 filter를 매핑할 때 모든 URL에 대해 인코딩될 수 있도록 /*와 같이 url-pattern을 설정 해주는 방법도 있는 것 같다
수업의 내용은 지금으로서는 이해하기 너무 어려우니 정규 표현식만 얻어가자.
'백엔드 > 웹 개발' 카테고리의 다른 글
블로그 화면 구성하기 - 타임리프5 (블로그 글 수정/생성 기능 추가하기) (0) | 2023.08.11 |
---|---|
블로그 화면 구성하기 - 타임리프4 (블로그 글 삭제 기능) (0) | 2023.08.10 |
리스너(Listener) (0) | 2023.07.04 |
사용자 정의 쿠키(자동로그인) (0) | 2023.07.03 |
로그인, 로그아웃 구현하기(필터) (0) | 2023.06.29 |