newlec Spring MVC
4. Dispatcher Servlet 라이브러리 설정하기
기본적인 WEB프로젝트에 스프링을 얹어보고자 한다.
스프링이 프론트 컨트롤러를 제공한다. 이것을 사용하는 방법을 알아보고자 한다.
컨트롤러를 가지고 Dispatcher을 사용할 수 잇지만 내용들은 POJO클래스에 만들고
Dispatcher로 처리를 해줄 것이다.
https://mvnrepository.com/artifact/org.springframework/spring-webmvc
스프링 WEB이 필요한데 Spring WEB MVC 라이브러리를 다운받으면 다 필요해서 다 추가해주니 이것을 받자.
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.24.RELEASE</version>
</dependency>프로젝트에서 자바 리소스에 Libaries를 보면 두가지 묶음이 있다.
하나는 JRE 하나는 MAVEN Dependencies이다.
하위 Dependencies들이 포함되어 알아서 설치 된게 보인다.
spring-webmvc라이브러리를 확장하면 - DispatcherServlet.class를 사용할것이다.
오른쪽키 Copy qualified Name하면
패키지명과 클래스명을 한번에 받아올수있다.
org.springframework.web.servlet.DispatcherServlet.class
이 가져온건 서블릿 클래스이다.
front-controller 역할을 하는 서블릿이다.
5. dispatcher-servlet.xml 파일
스프링을 사용하기 위한 라이브러리를 다운 받앗다.
사용하기 위해 가장 필요한것은 Dispatcher Servlet xml파일이다.
MVC를 하기 위해서 스프링이 꼭 있어야하는 것은 아니다.
컨트롤단이 잇어야하고 VIEW에서 데이터를 받아서 화면에 출력해야한다.
원래는 이렇게 서블릿을 상속받아 만들었는데 이것을 사용하지 않겟다.
package webprj;
import javax.servlet.http.HttpServlet;
public class IndexController extends HttpServlet {}이기능을 분류해서 스프링의 DispatcherServlet가 만들것이다.
남이 만든 서블릿을 사용하려면 xml을 사용해야한다.
전에 컨트롤러를 할때 URL매핑을 어노테이션을 사용햇엇는데
남이 만든 서블릿이기 때문에 소스가 없어서 어노테이션을 쓸 수없다.
그래서 XML설정을 해줘야한다.
web.xml에서 매핑해야한다.
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> 서블릿 배울때 햇듯이 매핑해준다.
Front Controller만들었다. 어떤요청이 오더라도 매핑해준게 오게 해야한다.
루트로 시작하는 모든 URL이 오도록 설정해줘야한다.
그런데 모든주소를 받아서 매핑안한게 오면안된다.
http://localhost:8080/WEBPrj/index.jsp이렇게왓는데 이렇게오면 그냥 이파일을 요청한것이니 잘못된것이다.
<servlet-mapping>
<servlet-name>dispathcer</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>이렇게 변경해준다. 예외없이 dispathcer라는 프론트컨트롤러가 허락해야 올 수 있다.
IOException parsing XML document from ServletContext resource [/WEB-INF/dispathcer-servlet.xml
dispathcer가 모든 url을 가지고 와야하는데 원래 모든 url을 web.xml이 햇는데
*-servlet.xml이 매핑정보를 가지고 잇어서 적절한 컨트롤러를 배분해도록 하는 것이다.
설정파일 자체가 없어서 에러가 발생하는 것이다.
dispathcer-servlet.xml파일을 WEB-INF에 추가해줘야한다.
6. 스프링 컨트롤러 IndexController 작성하기
스프링의 dispathcer가 사용하는 설정파일이 xml이다.
스프링이 제공하는 것을 레퍼런스를 사용해야한다.
https://docs.spring.io/spring-framework/docs
버전에 맞는 레퍼런스를 보자 - spring-framework-reference -core -왼쪽에 The IoC Container에서 찾을 것이다.
configuration metadata로 가서 내리다보면 beans설정이 있다. 이것을 복사해오자. 이전에 만든거 가져와도된다.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>여기서 ID로 클래스를 꺼내서 담는거 엿는데 MVC에서는 ID에 URL을 담아서 사용하게된다.
컨테이너에 담겨진 객체들을 요청이 url로 오면 객체화해서 꺼내오게 되는 것이다.
<bean id="/index" class="com.newlecture.web.controller.IndexController">
</bean>index라는 url로 이 컨트롤러가 담겨잇고 이것을 객체화해서 호출하는 것이다.
POJO를 불러오기위해서는 약속되어있는 함수명을 사용해야한다.
이것이 바롸 handleRequest이다.
모든 컨트롤러는 dispathcer가 정해둔 함수를 약속해야한다.
얘가 제공하고 있는 인터페이스가 있는데 이것을 구현해야한다.
서블릿을 상속받아 사용햇는데 이제 스프링에 종속되는 것이다. 또다른 종속이 된것이다.
public class IndexController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
return null;
}
}반환할게 무엇인가? Dispatcher가 다빠졋으니 ModelAndView에 담아서 보내줘야한다.
setAttribute하듯이 mv.addObject("키", "값")해주면된다.
setView(view객체) setViewName(view이름) 메소드로 담은 것을 다시 view에 담는다.
POJO가 model and view를 담아서 Dispatcher에 보내준다.
이 model을 Dispatcher에가 jsp(VIEW)에 보내줌으로써 데이터가 보여지게 된다.
public class IndexController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("data", "hello spring mvc");
mv.setViewName("index.jsp");
return mv;
}
}404에러가 발생한다.
톰캣에서 어노테이션을 사용할때는 톰캣이 알아서 매핑된 주소를 가져왓다.
그런데 POJO라서 매핑된 주소를 가져오지 못하게 된다.
Dispatcher는 실행되는데 포워드하는데서 오류가 나오는 것이다.
web.xml에서 /*을하면 다시 Dispatcher를 거치게 되는 것이다.
index.jsp를 찾으려면 다시 걸려서 오는건데 찾을 수 없게 된다.
다시 *을빼주면 Dispatcher를 거치게되는데 찾아보다가 없으면 그냥 리소스를 직접 다시가져온다.
7. View 페이지를 위한 위치
*을 지웟다. 컨트롤러와 뷰가 분리되어 잇을경우 컨트롤러만 요청하도록 해야하는데 건너뛰고 view를 부를 수 잇으면안된다.
WEB-INF에 view페이지를 숨기자.
밖에서 WEB-INF에 요청하는 것은 불가능하지만 서버 컨트롤러쪽에서 요청하는 것은 가능하다.
mv.setViewName("WEB-INF/view/index.jsp");url을 또 바꿔준다
.
상대경로만 쓰면 앞에 루트를빼게되고 aa/WEB-INF를찾게된다 절대경로를 써야한다.
mv.setViewName("/WEB-INF/view/index.jsp");
이클립스가 적당한 요쳥 url을 입력해서 불러준다.
그런데 컨트롤러 실행시키면안온다.
편법으로 같은 이름을 부여하면 파일이 없어도 거기로 가서 불러와진다.
8. ViewResolver 사용하기
view페이지를 WEB-INF로 옮겻다. 쉽게 찾을 수잇도록하는 ViewResolver을 설정할 것이다.
경로가 복잡해졌는데 모든 컨트롤러가 이렇게 작성해애햔다.
/WEB-INF/view/와 .jsp를 제외하고 알아서 붙도록 하고자 한다.
이것이 ViewResolver이다.
-> 스프링부트에서는 spring properties에 작성했던 것이다.
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value= "/WEB-INF/view/"/>
<property name="suffix" value= ".jsp"/>
</bean>setPrefix = prefix setSuffix = suffix가 된것이다.
왜 그렇게 햇느냐 필요성을 알고 개념을 알고 해보는 것이다.
9. HTML 파일 설정하기
JSP때 했던 newlecutre사이트
css나 이미지가 깨진다.
web root에 css등 파일이잇어야하는것이다.
10. 정적파일 서비스하기
이미지나 css가 깨져서 페이지에서 볼수 없엇음 스프링 Dispatcher의 장난이다.
스프링이 정적인 파일을 제공하지 않도록 막아놓았기 때문이다.
그런데 jsp같은것은 열어 놧다.
WEB-INF의 사용자가 이미지를 요청하면 디렉토리에서 찾겟다를 정해놔야한다.
<mvc:resources location="/images/" mapping="/images/"/>
<mvc:resources location="/css/" mapping="/css/"/>그런데 이런것보다는 static한 파일들은 resource파일에 전부 넣어서 관리한다.
<mvc:resources location="/resource/" mapping="/resource/**"/>mvc태그를 사용하기 위해 dispatcher-servlet에 스키마파일을 추가해야한다.
xmlns:mvc="http://www.springframework.org/schema/mvc"
"http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd"스키마파일 이.xsd고 그 정의에 대한이름이 위 긴 url이다.
다른스키마와 중복이안되도록 도메인이름을 추가해서 긴것이다.
밑에 <>이름을 다넣으면 힘들다. 이것을 식별하기 위해서 xmlns:mvc로 태그설정을 해주는 것이다.
스키마에 이름을 붙여주고 태그를 추가할 수있게 하는 것이다.
jsp에들어가서 정적인 파일루트를 모두 /resource/를 다적어줘야해서 불편해진다.
<mvc:resources location="/static/" mapping="/**"/>static의 루트으로 매핑하고 밑의 폴더가 다 나오게 해버리자. 그러면 정적파일들이 다보여진다.
이전거는 resource안에 두면 resource파일안에서 두고 다 처리를 해줘야하는데
실제로는 static을 뒤지는 것이지만 그안에 있는 resource들을 찾게 되는 것이다.
static을 루트에 매핑을 햇으니 스태틱의 루트라고 생각하게끔되있는것이다.
11. 공지사항 컨트롤러 추가하기
ListController를 만들어보자.
url매핑을 해야된다. 어디서? dispatcher-servelt.xml
<bean id="/notice/list" class="com.newlecture.web.controller.notice.ListController"/>
public class ListController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView("notice/list");
mv.addObject("data", "Hello Spring MVC~");
return mv;
}
}12. Detail 컨트롤러 추가와 View 페이지 집중화의 필요성
디테일 패이지 만들고 url매핑의 문제점은 다음에 알아보도록 하자.
매핑 이후 컨트롤러에 연결하면된다.
<bean id="/notice/detail" class="com.newlecture.web.controller.notice.DetailController"/>
public class DetailController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView("notice/detail");
mv.addObject("data", "Hello Spring MVC~");
return mv;
}
}그런데 각 페이지에서 어디론가 가자면 .html이 남아있다. header마다 그런데 하나씩 다 고치기 힘들다.
이것을 집중화해야한다. 모든 파일마다 수정하는게 힘들다.
집중하기 위해 tiles를 사용할 것이다.
13. 페이지 공통분모 집중화
공통으로 나오는 부분을 집중화 하고자 한다.
컨텐츠를 가지고 잇는 페이지는 링크를 타고 제일 끝페이지에 있는다.
이런 유사한 컨텐츠들은 묶어두고 위의 링크에서는 하위페이지의 요약본 등이다.
페이지마다 공통으로 가진 부분이 잇다. header영역같은게 있다면 분리해서 공통으로 참조하도록 해야한다.
공통 부분을 수정하게 되면 모든 페이지를 다 수정해야하니 공통부분을빼고 하면좋다.
공통부분으로 두도록 include로 넣는 방법을 제공하고 잇엇다.
jsp:include로 하면 페이지마다 중복되서 넣어야하는 것이 이것마저도 불편해보인다.
이것마저 쉽게하는 것이 tiles 이다.
14. 페이지 모듈 분리하기
페이지마다 반복되는 header부분과 footer부분을 잘라내서 inc(include)폴더를 만들고 따로 jsp파일을 만들어준다.
list페이지와 detail페이지에서도 각각 지워준다.
list페이지와 detail페이지 'visual' 부분도 같다.
그런데 원래 inc는 페이지 전체의 것이기 때문에 고객센터와 관련된 부분만 따로 나누고 싶다.
customer/inc폴더를 만들고 visual.jsp를 만들어주자.
notice파일 자체도 고객센터 기능이기때문에 같이 합쳐준다.
이외의 기능들을 추가해나갈때 합쳐나갈 필요가 있으니 구분을 잘해두면 좋다.
이런것들을 하나하나 조립해나갈것이다.
남아있는 것은 layout.jsp로 두고 list.jsp에는 메인 부분만 남긴다.
detail도 main만 남긴다.
이런식으로 공통인 부분을 다빼고 남겨두면 모듈화를 시키게 되는 것이다.
15. Tiles 지시서 작성하기
다쪼개서 담아놧는데 이것을 엮기 위해 Tiles를 이용할것이다.
apache.org에서 프로젝트를 다운받아야한다. 그런데 종료된 서비스이다
직접 찾아보자. 페이지를 백엔드에서 아니라 프론트에서도 만든다.
점점 소규모 프로젝트는 프론트에서 만들고 합치는 작업을 백엔드에서 하는 양이 줄어드니 타일즈가 없어졋다.
더이상 합칠일이 줄어들엇다. 현재로선 백엔드에서도 만드는 일이 잇으니 배워놓으면 좋을 수 있다.
https://attic.apache.org/projects/tiles.html
설정방법을 알려줌
https://tiles.apache.org/framework/tutorial/basic/pages.html
/WEB-INF/tiles.xml에 둔다고 하니 만들고 넣자.
name은 컨트롤러가 반환하는 이름이다.
notice/list로 리스트를 불러왓는데 매핑되도록 이름을 맞춰서 만들어준다.
notice.list 반드시 '.'일필요는 없는데 일반적으로 이렇게 하는게 패턴만들기 편하다.
그런데 페이지마다 하나씩 있어야 만들어줘야하나 일단은 그렇다.
url마다 하면 불필요하게 코드가 늘어나는 것 같다.
일단 하나씩 나누고 나중에 합치고자 한다.
layout.jsp를 기반으로 하나씩 붙여나갈 것이다.
tiles가 지시서를 보고 각각을 조합해서 보여줄 것이다.
<definition name="notice.list" template="/WEB-INF/view/customer/inc/layout.jsp">
<put-attribute name="title" value="Tiles tutorial homepage" />
<put-attribute name="header" value="/WEB-INF/view/inc/header.jsp" />
<put-attribute name="visual" value="/WEB-INF/view/customer/inc/visual.jsp" />
<put-attribute name="aside" value="/WEB-INF/view/customer/inc/aside.jsp" />
<put-attribute name="body" value="/WEB-INF/view/customer/notice/list.jsp" />
<put-attribute name="footer" value="/WEB-INF/view/inc/footer.jsp" />
</definition>16. 레이아웃 페이지 만들기와 Tiles 라이브러리 설정하기
Tiles지시서와 dispatcher 지시서가 있는 것이다.
컨트롤러에서 일한 결과를 타일즈지시서가 사용하는 것이다.
이 레이아웃에서 어디에 포함할 것인지를 정해야한다.
Tiles가 제공하는 태그 라이브러리를 사용해야한다.
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-jsp</artifactId>
<version>3.0.8</version>
</dependency><%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
layout.jsp에 태그를 추가해주자.
헤더부분에 <tiles:insertAttribute name="header"/>을 넣어주자.
각각 넣어준다. 지시서의 이름과 같게 넣어줘야한다.
위의것처럼 파일을 넣을 수잇고
\tiles:getAsString name="title"/>
이런식으로 문자열로만 사용할 수도 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><tiles:getAsString name="title"/></title>
<link href="/css/customer/layout.css" type="text/css" rel="stylesheet" />
<style>
#visual .content-container{
height:inherit;
display:flex;
align-items: center;
background: url("../../images/customer/visual.png") no-repeat center;
}
</style>
</head>
<body>
<!-- header 부분 -->
<tiles:insertAttribute name="header"/>
<!-- --------------------------- <visual> --------------------------------------- -->
<!-- visual 부분 -->
<tiles:insertAttribute name="visual"/>
<!-- --------------------------- <body> --------------------------------------- -->
<div id="body">
<div class="content-container clearfix">
<!-- --------------------------- aside --------------------------------------- -->
<!-- aside 부분 -->
<tiles:insertAttribute name="aside"/>
<!-- --------------------------- main --------------------------------------- -->
<tiles:insertAttribute name="body"/>
</div>
</div>
<!-- ------------------- <footer> --------------------------------------- -->
<tiles:insertAttribute name="footer"/>
</body>
</html>17. Tiles ViewResolver 설정하기
레이아웃을 완성했는데 jsp를이용해서 접두사와 접미사를 만든것 대신
타일즈를 사용해서 합친것을 찾아주는 역할을 하는 게 있어야한다.
이것을 연결해주는 것이 Tiles ViewResolver이다.
그래서 지시서를 찾아야하는데 지시서를 어디서 찾냐면 tiles.xml을 넣어주면된다.
dispatcher-servlet.xml에 설정해주면된다.
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.tiles3.TilesView" />
<property name="order" value="1" />
</bean>
<bean class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions" value="/WEB-INF/tiles.xml" />
</bean>UrlBasedViewResolver/ InternalResourceViewResolver 두가지가 있어서 서로 경합하게 된다.
이 Resolver가 두개가 경합하지 않도록
<property name="order" value="1" />를통해서 순서를 정해줘야 한다.
prefix, suffix를 처리하는 것을 우선순위를 낮춰준다.
localhost:8080/notice/list하면 에러가 나와야하는데 안나옴
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>18. Tiles 설정에 Wildcard 이용하기
tiles.xml 할때 페이지마다 하나하나 지정하는것은 비효율적이게 느껴진다.
거의똑같은데 notice.이부분만 다르다. 패턴으로 사용할 수 있게끔 와일드카드 패턴 문자열을 제공하고 있다.
뭐가오든 걸리게 notice.*로 해주면 된다.
첫번째 와일드 카드값이 오면 이 값이 다시 또 사용할수잇도록
<put-attribute name="body" value="/WEB-INF/view/customer/notice/{1}.jsp" />로 만들어주면 첫 *에 온값이 {1}에 들어가게된다.
와일드카드가 만약 여러개이면 {2}..하나씩 추가할 수 있게된다.
와일드카드에 대한 방법은 여러가지 방법이 있는데 타일 사이트에 들어가면 사용방법이 있다.
https://tiles.apache.org/framework/tutorial/advanced/wildcard.html
와일드카드를 정규식으로 사용할 수도 있다. 실질적으로 사용할때는 별로 사용되지 않는다.
<definition name="notice.*" template="/WEB-INF/view/customer/inc/layout.jsp">
<put-attribute name="title" value="공지사항" />
<put-attribute name="header" value="/WEB-INF/view/inc/header.jsp" />
<put-attribute name="visual" value="/WEB-INF/view/customer/inc/visual.jsp" />
<put-attribute name="aside" value="/WEB-INF/view/customer/inc/aside.jsp" />
<put-attribute name="body" value="/WEB-INF/view/customer/notice/{1}.jsp" />
<put-attribute name="footer" value="/WEB-INF/view/inc/footer.jsp" />
</definition>19. Root 페이지들을 위한 Layout 페이지 만들기
와일드카드를 이용해서 패턴을 만들었다.
인덱스 페이지에 header와 footer가 없다.
루트페이지는 리스트나 디테일과 다른데 어떻게 설정할지를 알아보도록 하자.
인덱스페이지에 header와 footer를 붙여보자. 루트에 있는것만 만들고자한다
WEB-INF/inc 에 layout.jsp를 하나더 만들어주자.
index.jsp 에는 컨텐츠 내용만 남겨 놓는다.
루트에 있는것을 부르기위해 그냥 *만쓰면 무조건 여기에 걸려서 notice밑에있는것이 통과되지않는다.
root페이지는 root라는 이름에 서 찾도록 해줘야한다.
<definition name="root.*" template="/WEB-INF/view/inc/layout.jsp">
<put-attribute name="title" value="코딩 전문가를 만들기 위한 온라인 강의 시스템" />
<put-attribute name="header" value="/WEB-INF/view/inc/header.jsp" />
<put-attribute name="body" value="/WEB-INF/view/{1}.jsp" />
<put-attribute name="footer" value="/WEB-INF/view/inc/footer.jsp" />
</definition>public class IndexController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView("root.index");
return mv;
}
}20. 데이터 서비스 클래스(NoticeService) 준비하기
컨트롤러를 사용해서 입력을 다루는 방법에 대해서 알아보고자 한다.
뷰에 심을 수잇는 데이터를 담아야 한다.
jdbc수업에서 사용한 noticeService와 notice객체 가져오기.
db에 테이블 만들기는 이전에 만들어 둔것 사용하자.
2023.04.18
스프링 MVC의 내용을 이해하고자 한다.
'기초단계 > SPRING' 카테고리의 다른 글
| 2023.04.22 Spring (0) | 2023.04.24 |
|---|---|
| 2023.04.20 Spring (0) | 2023.04.20 |
| 2023.04.16 Spring (0) | 2023.04.17 |
| 2023.04.14 Spring (0) | 2023.04.17 |
| 2023.04.13 Spring (0) | 2023.04.13 |