Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- toUpperCase
- STS
- Join
- 인텔리제이
- 자바
- MVC2
- order by
- 메이븐
- select
- Model1
- 프로그래머스
- Model2
- @Controller
- 스프링
- 코딩테스트
- 세션
- JSP
- 서블릿
- 코테
- SQL
- 김영한
- 프레임워크
- @RestController
- DDL
- 기술 대비
- 뉴렉처
- MVC
- AOP
- 인프런
- 서브쿼리
Archives
- Today
- Total
Heestory
02.Spring MVC)서블릿,JSP,MVC 패턴 본문
서블릿 이용
@WebServlet(name = "memberFormServlet", urlPatterns = "/servlet/members/new-form")
public class MemberFormServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter w = response.getWriter();
w.write("<!DOCTYPE html>\n" +
"<html>\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>\n" +
"<form action=\"/servlet/members/save\" method=\"post\">\n" +
" username: <input type=\"text\" name=\"username\" />\n" +
" age: <input type=\"text\" name=\"age\" />\n" +
" <button type=\"submit\">전송</button>\n" +
"</form>\n" +
"</body>\n" +
"</html>\n");
}
}
HTML을 이용한 Form 작성
응답 결과는 항상 String이기 때문에 int는 형변환 필요하다
int age = Integer.parseInt(request.getParameter("age"));
@WebServlet(name = "memberSaveServlet" , urlPatterns = "/servlet/members/save")
public class MemberSaveServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("MemberSaveServlet.service");
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
System.out.println("member = " +member);
memberRepository.save(member);
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter w = response.getWriter();
w.write("<html>\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
"</head>\n" +
"<body>\n" +
"성공\n" +
"<ul>\n" +
" <li>id="+member.getId()+"</li>\n" +
" <li>username="+member.getUsername()+"</li>\n" +
" <li>age="+member.getAge()+"</li>\n" +
"</ul>\n" +
"<a href=\"/index.html\">메인</a>\n" +
"</body>\n" +
"</html>");
}
}
- 파라미터를 조회해서 Member 객체를 만든다.
- Member 객체를 MemberRepository를 통해서 저장
- Member 객체를 사용해서 결과 화면용 HTML을 동적으로 만들어서 응답
→ 데이터가 전송되고, 저장 결과를 확인 할 수 있다.
for (Member member : members) {
w.write(" <tr>");
w.write(" <td>" + member.getId() + "</td>");
w.write(" <td>" + member.getUsername() + "</td>");
w.write(" <td>" + member.getAge() + "</td>");
w.write(" </tr>");
}
- 목록 조회시 HTML을 for루프를 통해서 회원 수 만큼 동적으로 생성하고 응답한다.
서블릿 덕분에 동적으로 원하는 HTML을 만들 수 있다. 정적인 HTML 문서라면 화면이 계속 달라지는 회원의 저장 결과, 목록등을 만드는 것은 불가능하다.
그러나 자바 코드로 HTML을 만들어 내는 것은 비효율적이라(쓰는 것만으로 오타 확률 10000%)
HTML문서에 동적으로 변경해야하는 부분만 자바 코드를 넣을 수 있다면?
→ 템플릿 엔진
JSP,Thymeleaf,Freeemarker,Velocity 등이 있다.
JSP 이용
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
- JSP문서의 첫 시작
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/jsp/members/save.jsp" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>
이때 주소는 jsp까지 함께 적는다.
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ page import="hello.servlet.domain.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// request, response 사용 가능
MemberRepository memberRepository = MemberRepository.getInstance();
System.out.println("save.jsp");
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
System.out.println("member = " + member);
memberRepository.save(member);
%>
<html>
<head>
<title>Title</title>
</head>
<body>
성공
<ul>
<li>id=<%=member.getId()%></li>
<li>username=<%=member.getUsername()%></li>
<li>age=<%=member.getAge()%></li>
</ul>
<a href="/index.html">메인</a>
</body>
</html>
- <%@ page import %> : 자바의 import문
- <% ~ %> : 자바 코드 입력
- <%= ~ %> : 자바 코드 출력
JSP를 사용한 덕분에 뷰를 생성하는 HTML 작업을 깔끔하게 가져가고, 중간중간 동적으로 변경이 필요한 부분에만 자바 코드를 적용했다.
그러나 위의 코드를 보면 코드 상위 절반은 회원을 저장하기 위한 비즈니스 로직이고, 나머지 하위 절반만 결과를 HTML로 보여주기 위한 뷰 영역이다. 이처럼 JAVA코드, 데이터를 조회하는 리포지토리 등 다양한 코드가 모두 JSP에 노출되어있다. 유지 보수면에서 매우 비효율적.
특히, UI를 일부 수정하는 일과 비즈니스 로직을 수정하는 일은 각각 다르게 발생할 가능성이 매우 높고 대부분 영향을 서로 주지 않기 때문에 이처럼 변경의 라이프 사이클이 다른 부분을 하나의 코드로 관리하는 것은 유지 보수에 좋지 않다.
→ MVC 패턴의 등장 : 비즈니스 로직은 서블릿처럼 다른곳에서 처리하고, JSP는 목적에 맞게 HTML로 화면(View)을 그리는 일에 집중할 수 있게 한다.
MVC패턴
- 컨트롤러 : HTTP요청을 받아서 파라이머를 검증하고, 비즈니스 로직을 실행
- 모델 : 뷰에 출력할 데이터를 담아두는 역할
HttpServletRequest 객체를 사용, request는 내부에 데이터 저장소를 가지고 있는데, request.setAttribute(), requqest.getAttribute()를 사용하면 데이터를 보관하고, 조회할 수 있다. - 뷰 : 모델에 담겨있는 데이터를 사용해서 화면을 그림
컨트롤러에 비즈니스 로직을 둘 수 있지만, 이렇게 되면 컨트롤러가 너무 많은 역할을 담당한다. 비즈니스 로직은 서비스라는 계층을 별도로 만들어서 처리한다. 컨트롤러는 비즈니스 로직이 있는 서비스를 호출하는 역할을 담당한다.
@WebServlet(name = "mvcMemberFormServlet", urlPatterns = "/servlet-mvc/members/new-form")
public class MvcMemberFormServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String viewPath = "/WEB-INF/views/new-form.jsp";
//Controller에서 View로 이동할 때 디스패처 사용
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
- dispatcher.forward() : 다른 서블릿이나 JSP로 이동할 수 있는 기능
- /WEB-INF : 이 안에 있으면 외부에서 직접 JSP를 호출할 수 없다. 때문에 컨트롤러에서만 호출 가능
redirect : 실제 클라이언트(웹 브라우저)에 응답 나갔다가, 클라이언트가 redirect 경로로 다시 요청, 때문에 클라이언트가 인지할 수 있으며, URL 경로도 실제로 변경
forward : 서버 내부에서 일어나는 호출로 클라이언트가 전혀 인지하지 못한다
<!-- 상대경로 사용, [현재 URL이 속한 계층 경로 + /save] -->
<form action="save" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
form.jsp에서 사용한 상대경로
/로 시작한다면 절대경로 , 아니라면 상대경로임을 알 수 있는데 상대 경로시 그 파일 위치 기준으로 이동
/servlet-mvc/members/ 기준으로 /servlet-mvc/members/save 로 이동
<c:forEach var="item" items="${members}">
<tr>
<td>${item.id}</td>
<td>${item.username}</td>
<td>${item.age}</td>
</tr>
</c:forEach>
members의 모델에 보관한 것을 JSTL 반복문을 이용해 꺼낸다.
'개발(~국비) > Spring' 카테고리의 다른 글
04.Spring-MVC)MVC 구조의 이해 (0) | 2022.11.04 |
---|---|
03.Spring-MVC)MVC 프레임워크 만들기 (0) | 2022.11.02 |
01.Spring MVC)서블릿 (0) | 2022.10.28 |
09. 스프링)빈 스코프 (0) | 2022.10.27 |
08. 스프링)빈 생명주기 콜백 (0) | 2022.10.26 |