SpringMVC工程升级SpringBoot过程

原始工程说明:

SpringMVC 4.2.4.RELEASE

Shiro 1.5.3

Log4j2 2.14.1

Mybatis 3.3.0

Mybatis-spring 1.2.2

JDK 1.8

C3P0 0.9.5.5

shiro-freemarker-tags 1.0.2

OJDBC6 11.2.0.3

tk.mapper 3.4.2

com.github.pagehelper 5.0.0

spring-data-redis 1.8.6.RELEASE

jedis 2.9.0

jms 2.0.1

artemis-jms-client 2.17.0

升级步骤:

一、引入SpringBoot,去除SpringMVC

修改pom,引入SpringBoot依赖,同时去除SpringMVC相关依赖

(说明:推荐一个IDEA插件Maven Helper,可以很好的查看和解决包的冲突)

示例如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-parent</artifactId>
    <version>2.3.12.RELEASE</version>
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

说明:因为工程使用了Log4j2日志,而SpringBoot默认也会开启日志(默认用的是logback),会导致冲突。所以在引入SpringBoot stater时,需要将log排除。

二、创建application类

该类是SpringBoot的启动入口类,为了复用之前已有的XML配置,此处需要将XML资源都引入进来。

示例代码:

@SpringBootApplication(proxyBeanMethods = false,
exclude = { RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class })
@ImportResource(locations = { "classpath:spring-*.xml", "classpath:mybatis-config.xml" })
@PropertySource("classpath:config.properties")
public class TaApplication {
    public static void main(String[] args) {
        SpringApplication.run(TaApplication.class, args);
    }
}

说明1:由于SpringBoot会自动给所有扫描到的Bean进行代理增强,但是老工程里面的Bean都已经被Spring托管了,所以会导致一些INFO的提示:

Bean '' of type [xxx] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

所以,此处使用proxyBeanMethods=false,禁用SpringBoot的自动代理。

说明2:SpringBoot引入data-Redis包后,由于会自动配置,导致与XML里的配置冲突,故此处通过exclude,禁用Redis的自动配置。

说明3:通过ImportResource,可以将老工程里的XML配置都引入到工程里。(后续可以再逐个将XML配置改为Configuration模式)

说明4:通过PropertySource引入老工程里的properties配置文件(SpringBoot工程默认的配置文件都是Application,为了兼容老的配置,此处先引入进来,后续可以逐步迁移到application配置文件中)

三、创建application.yml配置文件

SpringBoot工程相关的配置都在此文件中进行配置

示例代码如下:

server:
    port: 81
logging:
    config: classpath:log4j2.xml
spring:
    main:
        allow-bean-definition-overriding: true

说明1:通过server.port指定springboot默认的启动端口

说明2:因为springboot默认的log4j2配置文件名称为log4j2-spring.xml,故此处需要通过配置指定log4j2的配置文件

update 20220929:spring boot 默认支持log4j2-spring.xml 或者log4j2.xml名称,直接使用这两个文件名会导致一些问题。

因为log4j2默认会自动装配,当发现存在log4j2.xml或log4j2-spring.xml时就会使用配置文件进行配置,而此时spring还未完成创建上下文,将会导致spring look up失效。

可以修改配置的文件名为其他的,然后在yml里面指定即可

参考:

xml - Spring Boot log4j2 application creates one empty and one working log file - Stack Overflowhttps://stackoverflow.com/questions/70424393/spring-boot-log4j2-application-creates-one-empty-and-one-working-log-file

Core Featuresicon-default.png?t=N5F7https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging.custom-log-configuration

Log4j – Configuring Log4j 2icon-default.png?t=N5F7https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticConfiguration

说明3:可能因为配置相关问题,部分类会被多次扫描并自动注入Spring,导致Spring Bean创建异常。故通过allow-bean-definition-overiding=true,解决重复扫描并创建的问题

四、解决Shiro兼容性问题

问题1描述:

经过前面几步,工程终于能够正常启动了。但是访问页面后,出现了很诡异的问题,页面跳转到CAS并经过认证后返回,但是无法正常进入页面,出现了无限重定向的问题。排查了好久(由于与问题2纠缠在一起,导致在排查该问题时有些混乱),终于发现原来是回调路径设置的有问题。

在开发环境,原有的工程在IDEA的Tomcat部署配置时设置了Application Context,所以在访问页面时,路径都会带上这个context,比如http://xxx/yy/index (yy就是配置的application context)。

而改为SpringBoot后,CAS回调URL仍然配置的是之前的,所以导致了CAS回调访问该路径时,被拦截器拦住,认为需要进行用户认证,又触发了CAS认证访问,从而导致无限循环。发现问题后,将yy去掉即可(SpringBoot默认的application context = /,即没有yy)

问题2描述:

解决了CAS无限循环的问题,接着发现访问一些静态页面,也走了CAS认证(SHIRO配置的是静态页面可以直接访问),查看了很久shiro的配置,应该没有问题,也没有报SHIRO相关的异常,说明配置应该是兼容的。但是又没有正常的走SHIRO配置好的拦截器。只能硬着头皮,设置断点,慢慢研究SpringBoot下SHIRO的处理流程。最后通过日志发现了一条很诡异的INFO日志:

org.springframework.boot.web.servlet.ServletContextInitializerBeans:235 - Mapping filters: filterRegistrationBean urls=[/*] order=2147483647, filterRegistrationBean urls=[/*] order=2147483647, filterRegistrationBean urls=[/*] order=2147483647, characterEncodingFilter urls=[/*] order=-2147483648, formContentFilter urls=[/*] order=-9900, requestContextFilter urls=[/*] order=-105, shiroFilterFactoryBean urls=[/*] order=2147483647, menuPermissionFilter  urls=[/*] order=xxx

里面的menuPermissionFilter是工程里面自定义的一个Shiro Filter,按道理应该是在shiro里面进行管理和调用的,而且配置的拦截URL也不是/*。顿时感觉有可能问题在这里,因为这里把 menuPermissionFilter  urls设置成了/*,所以导致访问所有页面,都被强制走CAS了。

继续跟踪调试,发现了很有意思的现象,访问一个页面后,menuPermissionFilter被调用了两遍。

经过查看相关代码,基本发现了问题所在:SpringBoot自动将自定义的filter类加入到了ServletContext下的filterChain里,而且默认设置urls就是/*,所以导致了所有的页面访问,都会被menuPermissionFilter拦截,然后校验不通过,导致了页面无法访问。

查看源码,

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这是一个简单的示例工程,演示如何将一个基于SpringMVC JSP的应用升级为基于Spring Boot的应用。 1. 创建Spring Boot项目 在Eclipse或者Intellij IDEA中创建一个新的Spring Boot项目,选择Spring Web作为依赖。 2. 复制代码 将原来的SpringMVC JSP的代码复制到src/main/java目录下,并将JSP文件复制到src/main/resources/templates目录下。 3. 修改代码 修改代码以适应Spring Boot的要求,主要包括以下几个方面: - 修改配置文件 将原来的web.xml中的配置转换为application.properties或application.yml中的配置。例如: web.xml ``` <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/dispatcher-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> ``` application.properties ``` spring.mvc.servlet.load-on-startup=1 spring.mvc.servlet.path=/ spring.mvc.view.prefix=/templates/ spring.mvc.view.suffix=.jsp ``` - 修改DispatcherServlet配置 将原来的DispatcherServlet配置转换为Spring Boot的配置。例如: 原来的配置: ``` <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> ``` 转换后的配置: ``` @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/templates/"); resolver.setSuffix(".jsp"); return resolver; } ``` - 修改Controller 将Controller中的@RequestMapping注解中的URL路径前缀去掉,并且在类上加上@RestController注解。例如: 原来的类: ``` @Controller @RequestMapping("/hello") public class HelloController { @RequestMapping(method = RequestMethod.GET) public String printHello(ModelMap model) { model.addAttribute("message", "Hello Spring MVC Framework!"); return "hello"; } } ``` 修改后的类: ``` @RestController public class HelloController { @RequestMapping("/hello") public String printHello(ModelMap model) { model.addAttribute("message", "Hello Spring Boot!"); return "hello"; } } ``` 4. 运行项目 在IDE中运行Spring Boot应用程序,访问http://localhost:8080/hello,应该能够看到“Hello Spring Boot!”的输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金融码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值