스프링부트 2.7.6 + mybatis + jsp +maven 기준으로 3.0.5 업그레이드 방법
1단계 :
pc에 설치 된 자바 버전을 17이상으로 올려준다.
2단계 :
pom.xml 이나 , build.gradle 에서 단순히 버전만 올리면 에러 뿐만 아니라 프로젝트 구조가 바뀌어서 힘들다.
따라서, https://start.spring.io/ 사이트에서 기본적인 샘플 프로젝트를 다운 받은 후 임포트 해서 이 프로젝트를 기준으로 업데이트할 프로젝트
파일들을 옮기는 방법을 추천한다.
위와 같이 프로젝트에 사용한 기본 라이브러리를 설정 한 후 다운 받는다.
pom.xml 에서 다음 부분만 기존 프로젝트 있는 내용으로 변경 처리한다.
<groupId>com.example</groupId> <artifactId>macaronics</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>sample</name> <description>3.0 업그레이드 샘플</description>
3단계 :
기존 프로젝트에서 파일들을 덮어씌운다.
1) src/main/java/이하파일들 덮어 씌우기
2)src/main/resources/이하파일들 덮어 씌우기
3)src/main/webapp/이하파일들 덮어 씌우기
4단계 :
아직 추가하지 않은 라이브러리 및 기타 3.0 에서 특화된 많은 오류사항이 보일텐데,
먼저, javax. 를 이클립스 crtl +shfit +h , shift+shift 로 전체 파일을 jakarta. 포 변경한다.
javax.sql.DataSource , javax.imageio.ImageIO , javax.crypto.SecretKey 등은 jakarta 가 아니라 기존 그대로 javax 이다.
5단계 :
시큐리티 변경
Spring Security 변경 SecurityConfig에서 제거된 다음의 메서드를 변경해주어야 한다. authorizeRequests() ➔ authorizeHttpRequests() antMatchers() ➔ requestMatchers() regexMatchers() ➔ RegexRequestMatchers()
@Configurable -> 스프링부트 3.0 이상 작동 안됨
@Configurable 사용하고 있다면 @Component 변경 처리한다.
다음과 같은 @Component 만 사용해도 작동 되는 것 같으나 세부적으로 살펴보지 않은관계로
@EnableWebSecurity 과 @EnableMethodSecurity은 사용처리해 준다.
//@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true) // secured 어노테이션 활성화 //@Configurable -> 스프링부트 3.0 이상 작동 안됨 //@EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록이 됩니다. @Component public class SecurityConfig {
샘플 예
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf().disable().cors().disable() .authorizeHttpRequests(request -> request .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll() .requestMatchers(HttpMethod.GET, "/board/**").permitAll() .requestMatchers(HttpMethod.POST, "/board/**","/comment/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN", "ROLE_MANAGER") .requestMatchers(HttpMethod.DELETE, "/board/**" ,"/comment/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN", "ROLE_MANAGER") .requestMatchers(HttpMethod.PUT, "/board/**" ,"/comment/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_MANAGER" ,"ROLE_USER") .requestMatchers("/", "/resources/**", "/loginForm/**", "/login/**", "/join/**", "/displayFile","/phoneCertification", "/emailAuthentication/send", "/findIdPassword/**","/like/list").permitAll() ) .formLogin(login -> login .loginPage("/loginForm") .loginProcessingUrl("/login") .usernameParameter("userId") .passwordParameter("password") .defaultSuccessUrl("/", true) .failureHandler(customFailureHandler) // 로그인 오류 실패 체크 핸들러 .permitAll() ) .logout(); return http.build(); }
6단계 :
6. com.navercorp.lucy 라이브러리를 사용하고 있다면 오류가 나올텐데.
이것이 아직 업데이트 되지 않고 기존 javax 를 사용하고 있어서 이다.
다음과 같이 파일을 만들어 준다.
XssEscapeServletFilterUpdate
package net.macaronics.util.filter.navercorp; import java.io.IOException; import com.navercorp.lucy.security.xss.servletfilter.XssEscapeFilter; import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; @Component public class XssEscapeServletFilterUpdate implements Filter { private XssEscapeFilter xssEscapeFilter = XssEscapeFilter.getInstance(); @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new XssEscapeServletFilterWrapperUpdate(request, xssEscapeFilter), response); } @Override public void destroy() { } }
XssEscapeServletFilterWrapperUpdate
package net.macaronics.util.filter.navercorp; import java.util.HashMap; import java.util.Map; import java.util.Set; import com.navercorp.lucy.security.xss.servletfilter.XssEscapeFilter; import jakarta.servlet.ServletRequest; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; public class XssEscapeServletFilterWrapperUpdate extends HttpServletRequestWrapper { private XssEscapeFilter xssEscapeFilter; private String path = null; public XssEscapeServletFilterWrapperUpdate(ServletRequest request, XssEscapeFilter xssEscapeFilter) { super((HttpServletRequest)request); this.xssEscapeFilter = xssEscapeFilter; String contextPath = ((HttpServletRequest) request).getContextPath(); this.path = ((HttpServletRequest) request).getRequestURI().substring(contextPath.length()); } @Override public String getParameter(String paramName) { String value = super.getParameter(paramName); return doFilter(paramName, value); } @Override public String[] getParameterValues(String paramName) { String values[] = super.getParameterValues(paramName); if (values == null) { return values; } for (int index = 0; index < values.length; index++) { values[index] = doFilter(paramName, values[index]); } return values; } @Override public Map<String, String[]> getParameterMap() { Map<String, String[]> paramMap = super.getParameterMap(); Map<String, String[]> newFilteredParamMap = new HashMap<>(); Set<Map.Entry<String, String[]>> entries = paramMap.entrySet(); for (Map.Entry<String, String[]> entry : entries) { String paramName = entry.getKey(); Object[] valueObj = (Object[])entry.getValue(); String[] filteredValue = new String[valueObj.length]; for (int index = 0; index < valueObj.length; index++) { filteredValue[index] = doFilter(paramName, String.valueOf(valueObj[index])); } newFilteredParamMap.put(entry.getKey(), filteredValue); } return newFilteredParamMap; } /** * @param paramName String * @param value String * @return String */ private String doFilter(String paramName, String value) { return xssEscapeFilter.doFilter(path, paramName, value); } }
사용
@Bean FilterRegistrationBean<?> getFilterRegistrationBean() { FilterRegistrationBean<XssEscapeServletFilterUpdate> filterRegistration = new FilterRegistrationBean<XssEscapeServletFilterUpdate>(); filterRegistration.setFilter(new XssEscapeServletFilterUpdate()); filterRegistration.setOrder(1); // registrationBean.addUrlPatterns("*.do", "*.go"); //filter¸¦ // registrationBean.addUrlPatterns("*.do", "*.go" ,"/member/*"); // url patterns filterRegistration.addUrlPatterns("/comment/*", "/customerSupport/*"); // filter¸¦ return filterRegistration; }
7단계 :
jsp 오류 잡기
- Servlet
우선 Servlet의 패키지가 변경되었습니다.
javax.servlet =====> jakarta.servlet
SpringBoot 버전업을 원하시는 분들은 해당 사항 주의하시길 바랍니다.
- JSP, JSTL
물론, 추세에 따르면 JSP보다는 Vue.js, react 등 별도의 프론트 프레임워크 혹은 라이브러리를
이용하고 있지만, 혹시나 모를 JSP 이용자분들을 위해 세팅법을 알려드립니다.
기존 SpringBoot 2.x 와는 또 다른 부분들이 있더군요.
기존의 제공되는 내장형 tomcat의 의존성을 주석처리 및 제거해주도록 합니다.
[pom.xml]
<!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> -->
이후, JSP로 View를 리턴해줄 수 있는 tomcat의 의존성을 주입해주도록 합니다.
[pom.xml]
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>
이제 JSP 에 대한 resolver를 세팅해줄건데요, bean이 아닌 properties 를 통해 세팅해주도록 하겠습니다.
[application.properties]
spring.mvc.view.prefix=/WEB-INF/view/ spring.mvc.view.suffix=.jsp
위와같이 본인의 환경에 맞게 세팅을 해주시면 간단하게 완료입니다.
이제 JSTL 사용에 대해 알아볼건데요.
기존 2.x 에서 사용하듯 의존성을 주입하고 jstl을 사용하려고 하면
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
JSP내에서 해당 taglib을 못받아오는 에러를 경험해보실 수 있습니다.
글의 상단에서 말씀 드렸듯, servlet의 패키지가 변경되었듯 jstl 또한 변경이 있었더군요.
그럴땐 아래의 의존성을 주입해주도록 합니다.
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api --> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>3.0.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl --> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>3.0.1</version> </dependency>
출처 : [SpringBoot] SpringBoot 3.0 에서 Jsp, Jstl 세팅 그리고 Servlet 변경점
8 단계 :
기존 프로젝트에서 추가 안한 라이브러리들을 하나씩 추가해보면서 오류를 잡아 본다.
9. 만약 JPA 프로젝트라만 Query DSL 설정 참조.
기존
<dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>5.0.0</version> </dependency>
= > 업데이트
<dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>5.0.0</version> <classifier>jakarta</classifier> <scope>provided</scope> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>5.0.0</version> <classifier>jakarta</classifier> </dependency>
오류 참조
https://github.com/querydsl/querydsl/issues/3431#issuecomment-1328623180
10. 기타 pom.xml 참조
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.5</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>net.macaronics</groupId> <artifactId>macaronics</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>system</name> <description>Macaronics system</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mustache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.mariadb.jdbc</groupId> <artifactId>mariadb-java-client</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- https://islet4you.tistory.com/entry/SpringBoot-SpringBoot-30-에서-Jsp-Jstl-세팅-그리고-Servlet-변경점 [SpringBoot] SpringBoot 3.0 에서 Jsp, Jstl 세팅 그리고 Servlet 변경점 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency>--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api --> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>3.0.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl --> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!--여기부터 커스텀 라이브러리 추가--> <dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-core</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>org.imgscalr</groupId> <artifactId>imgscalr-lib</artifactId> <version>4.2</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>1.10.0</version> </dependency> <dependency> <groupId>com.navercorp.lucy</groupId> <artifactId>lucy-xss-servlet</artifactId> <version>2.0.1</version> </dependency> <!--// After Spring Boot 3.0--> <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>jakarta.mail</groupId> <artifactId>jakarta.mail-api</artifactId> <version>2.1.0</version> </dependency> <!--3.0 업데이트 설명서--> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-properties-migrator</artifactId> <scope>runtime</scope> </dependency> --> <!-- log4jdbc-remix , mybatis 쿼리 실행 보기 --> <dependency> <groupId>org.lazyluke</groupId> <artifactId>log4jdbc-remix</artifactId> <version>0.2.7</version> </dependency> </dependencies> <!-- <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build>--> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> <defaultGoal>install</defaultGoal> </build> </project>
댓글 ( 4)
댓글 남기기