[1] Spring MVC
: 톰캣은 받은 데이터를 모두 전송. 톰캣의 web.xml에 있던 url 값들은 Dispatcher서블릿에 설정된다.
: Dispatcher는 여러 컨트롤러중, 필요한 컨트롤러를 사용하여 model을 반환받고, dispatcher은 model, view값을 jsp에 넘겨서 결과페이지를 반환하게 한다.
: Dispatcher 역할의 집중화 = mvc모델의 발전
여기서 Maven은 Java Resources ▶ Libraries ▶ Maven Dependencies 에 있는 라이브러리를 참조하고(+pom.xml), Tomcat은 로컬에서 src ▶ main ▶ webapp ▶ WEB-INF ▶ lib 에 있는 라이브러리를 참조한다.(+web.xml)
* sts설치시 압축폴더오류: .jar > .zip 으로 변경했고, 윈도우 내장프로그램으론 .contents 압축을 풀 수 없어서 반디집 깔아서 사용함
* spring에서 javaEE 버튼 없을때 추가하는 법
Eclipse에서 Java EE 추가방법
Eclipse 우측상단에 JavaEE 보기가 없는 경우 Open Perspective를 클릭하여 Java EE가 보이는지 ...
blog.naver.com
[2] sts초기설정
2-1) web.xml 저장하기
: pom.xml에 web,xml파일이 없다고 에러가 뜸. 설치해둔 톰캣 폴더에서 web.xml파일을 가져와서 WEB-INF폴더 만들고 안에 넣어주기.
2-2) 라이브러리 자바 버전 (jdk) 변경
:maven pom.xml - overview tap - properties - create
:maven이 사용하는 폼파일 변경
: pom.xml 수정 후에는 update잊지말기.
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
2-3) UTF-8 로 설정 변경
2-4) jsp 파일 생성 ▶ jsp와 관련된 톰캣 라이브러리 추가
: The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path ▶ maven repository에서 maven 버전에 맞게 dependency받아다 pom.xml에 저장하기
: mvc 활용을 위해 spring web mvc dependency도 추가하기
2-5) 그외
: window-web browser-default system browser 설정 (내장브라우저 쓰기싫으면!)
: jsp에서 톰캣 최초 실행시 해당 버전 & 홈디렉토리 연결 (bin폴더가 있는 화면까지 가야 홈디렉토리)
[3] Spring Dispatcher를 Front Controller로 설정하기
: 웹프로젝트에 spring을 얹는 과정
: spring-webmvc.jar 안에 DispatcherServlet.class가 있으므로 이를 다운받아야 한다 ▶ maven repository에서 spring webmvc dependency 추가
3-1) Dispatcher-Servlet.xml 생성하기
: 컨트롤러는 순수 저바 코드로 남겨두고, 서블릿에 관한 url 은 web.xml이 모든 URL을 받도록 설정한다. (받아서 dispatcher Servlet.xml에게 넘김)
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/dispatcher-servlet.xml];
👉 web.xml에서 넘겼는데 받아서 정리할 -servlet.xml 이 없으므로 500에러 반환. 이때 내가지정한 dispatcher이름(지정어)+servlet.xml(예약어)이 WEB-INF폴더 안에 있어주면된다.
//web.xml
<!-- dispatcherServlet 설정 -->
<servlet>
<servlet-name>dispatcher</servlet-name> //이름을 dispatcher로 지어서 오류에도 dispatcher로 나옴
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<!-- 모든 url mapping -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
//url 패턴을 /*로 설정하면, 다 돌고 mvc값을 가져온 리턴값이 다시 dispatcher로 돌아가서 일치하는 애를 찾게 되면서, 해당 jsp가 없으면 무한루프로 갇히게 된다.
//그냥 '/'로 설정하면 리턴값이 dispatcher에 없을때 그대로 출력한다
* dispatcher-servlet 설정파일 - IoC container - Core Technologies
Index of /spring-framework/docs
docs.spring.io
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- mvc는 id자리에 url이 사용된다. 요청이 url로 올거니까. -->
<!-- url요청이 오면 class에 담긴 컨트롤러가 객체화되어 컨테이너에 담긴다 -->
<bean id="/index" class="com.newlecture.web.controller.IndexController">
</bean>
</beans>
3-2) IndexController 작성
: servlet & jsp 때는 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {equest.getRequestDispatcher("/WEB-INF/view/index.jsp").forward(request, response);} 으로 값을 받고 다른페이지로 연결하는데만 중심을 두었다면, (url은 @WebServlet("/index") 로 컨트롤러에 붙어있었다)
: 디스패쳐를 통한 컨트롤러는 dispatcher Servlet이 url을 모두 가지고 있으므로 (디스패쳐가 forward하는 담당), public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {...}는 model and view 객체를 반환한다
//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>
</head>
<body>
<h1> hey ${data }</h1> //model and view가 여기 값으로 들어간다
</body>
</html>
-------------------------------
//dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- dispatcher는 id자리에 url이 사용된다. 요청이 url로 올거니까. -->
<!-- url요청이 오면 class에 담긴 컨트롤러가 객체화되어 컨테이너에 담긴다 -->
<bean id="/index" class="com.newlecture.web.controller.IndexController">
</bean>
</beans>
---------------------------------
//IndexController.java
package com.newlecture.web.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
//컨테이너에서 꺼내서 가지고 있는 기능을 호출하기 - 컨트롤러마다 Handler Request를 구현해놓아야 dispatcher Servlet과 연결된다
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"); //(attribute name, value)
mv.setViewName("/WEB-INF/view/index.jsp"); //절대경로로 지정해야 혼선이없다
return mv;
}
}
👉 Index.jsp - IndexController.java가 한묶음인데 사용자가 index.jsp페이지를 호출할 수 있는게 문제가 된다. (위와같이 출력값이 완전히 다르다)
[4] view 페이지 & 서버의 상대경로와 절대경로
: 일단 Index.jsp는 WEB-INF아래에 넣어놓으면 사용자가 접근할 수 없다.
: 하지만 리턴하는 jsp의 경로는 절대경로, 상대경로에 따라 다르게 리턴되므로 주의해야 한다.
✔ 상대경로
mv.setViewName("WEB-INF/view/index.jsp"); ('/' 루트가 빠짐)
👉 dispatcher의 ID는 실제 폴더 여부에 상관없이 그 아이디로 요청시 객체를 담는다.
<bean id="/aa/index" class="com.newlecture.web.controller.IndexController">
> /aa/WEB-INF/view/index.jsp로 검색하게 된다 > 화면이 없다는 404 에러 발생
✔ 절대경로
mv.setViewName("/WEB-INF/view/index.jsp");
<bean id="/aa/index" class="com.newlecture.web.controller.IndexController">
> 정해져있는 /WEB-INF/view/index.jsp로만 반환한다
[5] View Resolver
: 반복되는 view의 일부분을 알아서 붙여준다
: 컨트롤러의 ModelAndView에 jsp파일명만 쓸 수 있다! 👉 반복되는 '/WEB-INF/view/ .jsp'는 view resolver의 역할.
ModelAndView mv = new ModelAndView("index");
* view resolver가 없으면 무한루프로 찾다가 오류메시지가 나온다
메시지 Circular view path [index]: would dispatch back to the current handler URL [/index] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
<!-- view resolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
[6] 정적파일 서비스하기
: 루트에 맞게 저장해놓은 로고 이미지가 웹에서 출력이 되지않는다 그이유는? 👉 스프링이 정적 파일을 제공하지 않도록 막아놓았기 때문.
//web.xml
<!-- 모든 url mapping -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern> // /* 는 jsp까지도 정적파일 불허 , /는 jsp는 정적파일 허용
</servlet-mapping>
: 정적인 리소스(이미지, html, js, css 등) get 요청시 > mvc 지시어로 된 매핑으로 받는다. 이때 저장된 폴더 자체를 루트로 인식하게 해서 그곳에서만 정적 파일을 뒤지도록 한다.
http://localhost:8080/images/logo.png
// 사용자가 mapping="/images/"로 시작하는 url을 요청하면 location="/images/"에서 찾게 해주겠다
<mvc:resources location="/images/" mapping="/images/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/css/" mapping="/css/**" />
// 여러요소가 많으므로 일반적으로는 resource폴더를 따로 만들어서 몰아둔다
<mvc:resources location="/resource/" mapping="/resource/**" />
// 이렇게 몰아두면 html의 이미지 링크마다 /resource/를 모두 붙여야하므로, 실무에서는 정적파일용 폴더를 루트로 해서 몰아두는 편.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" //mvc로 확장
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- (도메인 이름을 포함한) 파일 이름과 스키마파일 -->
<mvc:resources location="/static/" mapping="/**" />