适用场景
这篇文章主要适用于传统ssm+shiro框架向springboot2.0项目转换,去除项目中原有的spring-*.xml 和各种.properties,也是踩了一些坑,记录下来进行分享。其中包括mybatis数据源配置,springmvc配置,以及webservice(soap)配置。
具体流程
ssm框架项目结构
图1这里使用的项目管理工具是maven,IDE将由myeclipse转换成IDEA,如果有不同,请自行调整,大同小异。
新建项目
图2在IDEA中新建maven项目
图3这里新建一个maven项目,也可以选择Spring Iniializer,具体没有什么影响
图4新建好项目,项目结构如下
图5
有大量关于新建项目的博客,这里不再赘述。
POM文件
父项目itom-all的pom.xml,这里使用的是springboot2.0.4。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>itom</module>
<module>itom-common</module>
<module>itom-dm</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.dimpt</groupId>
<artifactId>itom-all</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>itom-all</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<quartz.version>2.3.0</quartz.version>
<cxf.version>3.1.1</cxf.version>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.dimpt</groupId>
<artifactId>itom</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.dimpt</groupId>
<artifactId>itom-all</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.dimpt</groupId>
<artifactId>itom-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.dimpt</groupId>
<artifactId>itom-dm</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- 热部署模块 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
<version>1.0.0</version>
</dependency>
<!-- 2.数据库 -->
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.1.1</version>
</dependency>
<!-- DAO: MyBatis -->
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>9.0.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<!-- 3.Servlet web -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- 4.Spring -->
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.16</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.ezmorph/ezmorph -->
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<!--<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.3.2</version>
</dependency>
-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
子项目itom是web主体,itom-common和itom-dm为其他模块,不做描述。itom模块的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>itom-all</artifactId>
<groupId>com.dimpt</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>itom</artifactId>
<packaging>war</packaging>
<name>itom</name>
<version>0.0.1-SNAPSHOT</version>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
相当于compile,但是打包阶段做了exclude操作-->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
</dependency>
<!-- 热部署模块 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- 2.数据库 -->
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
<!-- 日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<!-- 3.Servlet web -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- 4.Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/webapp</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<finalName>itom</finalName>
</build>
</project>
这里为主要使用的依赖,根据项目具体添加,打包方式选择war包,也可以选择jar包,这里主要是页面中有jsp页面(后台一些管理页面,项目主要是对外提供api接口),加入了一些jsp相关的依赖,如使用其他模板可选择相应的依赖。日志模块使用的是logback,原先的logback.xml文件,也可以使用springboot application.property进行配置。
去除项目中spring-*.xml,和各种.properties文件
原来项目中各种.properties文件,眼花缭乱(功能以及开发人员不同导致),全部整合进application.properties中
图6
图7
application.properties
spring.profiles.active=dev
application-dev.properties
#打成war包,不起作用
server.port=8080
server.servlet.context-path=/itom
#druid c3p0任选一个使用
spring.datasource.druid.url=jdbc:postgresql://10.100.49.92:5432/itom?useUnicode=true&characterEncoding=utf8&stringtype=unspecified
spring.datasource.druid.driver-class-name=org.postgresql.Driver
spring.datasource.druid.username=root
spring.datasource.druid.password=root
spring.datasource.druid.initial-size=50
spring.datasource.druid.max-active=100
spring.datasource.druid.min-idle=20
spring.datasource.druid.max-wait=60000
spring.datasource.druid.pool-prepared-statements=true
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
#spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
spring.datasource.druid.test-while-idle=true
spring.datasource.druid.time-between-eviction-runs-millis=60000
spring.datasource.druid.filters=stat,wall,log4j
#mybatis.type-handlers-package=com.dimpt.watchtower.web.handler
c3p0.jdbcUrl=jdbc:postgresql://10.100.49.92:5432/itom?useUnicode=true&characterEncoding=utf8&stringtype=unspecified
c3p0.user=zt
c3p0.password=123
c3p0.driverClass=org.postgresql.Driver
c3p0.minPoolSize=3
c3p0.maxPoolSize=100
c3p0.maxIdleTime=1800000
c3p0.acquireIncrement=3
c3p0.maxStatements=1000
c3p0.initialPoolSize=3
c3p0.idleConnectionTestPeriod=60
c3p0.acquireRetryAttempts=30
c3p0.acquireRetryDelay=1000
c3p0.breakAfterAcquireFailure=false
c3p0.testConnectionOnCheckout=false
logging.level.root=INFO
logging.level.org.springframework=ERROR
logging.level.org.mybatis=ERROR
spring.jedis.host = 10.100.49.78
spring.jedis.port = 6379
zkHost=10.100.49.78:2181,10.100.49.79:2181,10.100.49.92:2181
solrHost=10.100.49.79
solrPort=8280
#redis property
currentAppStructName=\u77AD\u671B\u58541\u671F
currentCloudResourcePoolStructName=\u4E91\u8D44\u6E90\u6C601\u671F
currentMachineRoomStructName=\u673A\u623F1\u671F
items.error=错误
items.isNULL=字段不能为空
# itom/file/upload config
localDir=/home/tower/upload
tempDir=/home/tower/upload/temp
remoteHost=10.100.49.93
filesvr.username=tower
filesvr.password=tower
remoteDir=/home/tower/upload
# itom/app/upload config
uploadDir=/home/tower/upload
#kafka config
group.id=kafka-websocket
zookeeper.connect=10.100.8.6:2181
serializer.class=kafka.serializer.DefaultEncoder
key.serializer.class=kafka.serializer.StringEncoder
bootstrap.servers=10.100.8.6:9092
acks=1
数据库连接原先项目使用的c3p0连接池,如何选择看自己喜好,spring项目会自动加载application.properties文件作为启动文件,这里使用-dev,-dep,-prod用于多环境切换。
ssm中各种spring-*文件,都有其作用,这里分开进行拆解。
图8
-
spring-dao为数据库连接池配置,新建DataSourceConfig.java类
图9
package com.dimpt.common.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* Created by x250-thinkpad on 2019/1/2.
*/
@Configuration
@MapperScan(basePackages = "com.dimpt.watchtower.web.dao",sqlSessionTemplateRef = "adminSqlSessionTemplate")
public class DataSourceConfig {
/*@Bean(name = "adminDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid")
@Primary
public DataSource dataSource() {
return DataSourceBuilder.create().type(DruidDataSource.class).build();
}*/
@Bean(name = "adminDataSource")
@ConfigurationProperties(prefix = "c3p0")
@Primary
public DataSource dataSource() {
return DataSourceBuilder.create().type(ComboPooledDataSource.class).build();
}
@Bean(name = "adminSqlSessionFactory")
@Primary
public SqlSessionFactory adminSqlSessionFactory(@Qualifier("adminDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//分页插件
//PageHelper pageHelper = new PageHelper();
//PagePlugin pagePlugin = new PagePlugin();
// Properties props = new Properties();
// props.setProperty("reasonable", "true");
// props.setProperty("supportMethodsArguments", "true");
// props.setProperty("returnPageInfo", "check");
// props.setProperty("params", "count=countSql");
// pageHelper.setProperties(props);
//添加插件
//bean.setPlugins(new Interceptor[]{pagePlugin});
// 添加mybatis配置文件
bean.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-config.xml"));
// 添加mybatis映射文件
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return bean.getObject();
}
@Bean(name = "adminTransactionManager")
@Primary
public DataSourceTransactionManager adminTransactionManager(@Qualifier("adminDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "adminSqlSessionTemplate")
@Primary
public SqlSessionTemplate adminSqlSessionTemplate(@Qualifier("adminSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
这里注释了druid连接池,可以选择使用,mybatis-config.xml中为mybatis相关配置以及分页插件,也可选择其他方式进而删除这个文件。
- spring-web.xml,springmvc相关配置,新建WebAppConfig.java类
package com.dimpt.common.config;
import com.dimpt.watchtower.web.common.interceptor.AppVisitInterceptor;
import com.dimpt.watchtower.web.common.interceptor.UserLogsAndScoresInteceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
/**
* Created by x250-thinkpad on 2019/1/2.
*/
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Bean
public AppVisitInterceptor appVisitInterceptor(){
return new AppVisitInterceptor();
}
@Bean
public UserLogsAndScoresInteceptor userLogsAndScoresInteceptor(){
return new UserLogsAndScoresInteceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userLogsAndScoresInteceptor())
.addPathPatterns("/**");
registry.addInterceptor(appVisitInterceptor())
.addPathPatterns("/app/{ztWtAppId}");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {
//super.addResourceHandlers(resourceHandlerRegistry);
resourceHandlerRegistry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
resourceHandlerRegistry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
resourceHandlerRegistry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* 配置请求视图映射
* @return
*/
@Bean
public InternalResourceViewResolver resourceViewResolver()
{
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
//请求视图文件的前缀地址
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
//请求视图文件的后缀
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.viewResolver(resourceViewResolver());
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/index").setViewName("/index");
registry.addViewController("/admin").setViewName("/login");
}
@Bean
public ReloadableResourceBundleMessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("ValidationMessages","org/hibernate/validator/ValidationMessages");
messageSource.setUseCodeAsDefaultMessage(false);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(60);
return messageSource;
}
@Override
public Validator getValidator() {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setProviderClass(org.hibernate.validator.HibernateValidator.class);
localValidatorFactoryBean.setValidationMessageSource(messageSource());
return localValidatorFactoryBean;
}
@Bean
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(209715200);
multipartResolver.setDefaultEncoding("utf-8");
return multipartResolver;
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
spring2.0之后springmvc相关配置通过实现WebMvcConfigure.java 类,对静态文件等等进行配置,根据自己需要自行配置。
- spring-redis.xml
package com.dimpt.common.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Created by x250-thinkpad on 2019/1/2.
*/
@Configuration
public class JedisConfig {
@Value("${spring.jedis.host}")
String host;
@Bean
@Primary
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(30);
jedisPoolConfig.setMaxIdle(10);
jedisPoolConfig.setNumTestsPerEvictionRun(1024);
jedisPoolConfig.setTimeBetweenEvictionRunsMillis(30000);
jedisPoolConfig.setMinEvictableIdleTimeMillis(1800000);
jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(10000);
jedisPoolConfig.setMaxWaitMillis(1500);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestWhileIdle(true);
jedisPoolConfig.setBlockWhenExhausted(false);
return jedisPoolConfig;
}
@Bean
@Primary
public JedisPool jedisPool(JedisPoolConfig jedisPoolConfig){
return new JedisPool(jedisPoolConfig,host,6379,5000);
}
}
- spring-shiro.xml
package com.dimpt.common.config;
import com.dimpt.common.shiro.CustomShiroSessionDAO;
import com.dimpt.common.shiro.cache.JedisManager;
import com.dimpt.common.shiro.cache.JedisShiroSessionRepository;
import com.dimpt.common.shiro.cache.impl.JedisShiroCacheManager;
import com.dimpt.common.shiro.filter.*;
import com.dimpt.common.shiro.listenter.CustomSessionListener;
import com.dimpt.common.shiro.service.ShiroManager;
import com.dimpt.common.shiro.service.impl.ShiroManagerImpl;
import com.dimpt.common.shiro.session.CustomSessionManager;
import com.dimpt.common.shiro.token.SampleRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Created by x250-thinkpad on 2019/1/2.
*/
@Configuration
public class ShiroConfiguration {
//@Value("${spring.redis.host}")
//private String host;
//@Value("${spring.redis.port}")
//private int port;
@Autowired
private JedisPool jedisPool;
//@Value("${spring.redis.timeout}")
//private int timeout;
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public SessionIdGenerator sessionIdGenerator() {
return new JavaUuidSessionIdGenerator();
}
@Bean(name="sessionIdCookie")
public Cookie simpleCookie() {
SimpleCookie simpleCookie = new SimpleCookie("itom");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(-1);
return simpleCookie;
}
@Bean
public SessionListener customSessionListener(JedisShiroSessionRepository jedisShiroSessionRepository){
CustomSessionListener customSessionListener = new CustomSessionListener();
customSessionListener.setShiroSessionRepository(jedisShiroSessionRepository);
return customSessionListener;
}
@Bean
public JedisShiroSessionRepository jedisShiroSessionRepository(JedisManager jedisManager){
JedisShiroSessionRepository jedisShiroSessionRepository = new JedisShiroSessionRepository();
jedisShiroSessionRepository.setJedisManager(jedisManager);
KickoutSessionFilter.setShiroSessionRepository(jedisShiroSessionRepository);
return jedisShiroSessionRepository;
}
@Bean(name="rememberMeCookie")
public SimpleCookie rememberMeCookie() {
SimpleCookie rememberMeCookie = new SimpleCookie("itom-re");
rememberMeCookie.setHttpOnly(true);
rememberMeCookie.setMaxAge(2592000);
return rememberMeCookie;
}
@Bean(name="rememberMeManager")
public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
cookieRememberMeManager.setCookie(rememberMeCookie);
return cookieRememberMeManager;
}
@Bean
public CustomShiroSessionDAO customShiroSessionDAO(JedisShiroSessionRepository jedisShiroSessionRepository,SessionIdGenerator sessionIdGenerator) {
CustomShiroSessionDAO customShiroSessionDAO = new CustomShiroSessionDAO();
customShiroSessionDAO.setShiroSessionRepository(jedisShiroSessionRepository);
customShiroSessionDAO.setSessionIdGenerator(sessionIdGenerator);
return customShiroSessionDAO;
}
@Bean
public CustomSessionManager customSessionManager(CustomShiroSessionDAO customShiroSessionDAO,JedisShiroSessionRepository jedisShiroSessionRepository){
CustomSessionManager customSessionManager = new CustomSessionManager();
customSessionManager.setCustomShiroSessionDAO(customShiroSessionDAO);
customSessionManager.setShiroSessionRepository(jedisShiroSessionRepository);
return customSessionManager;
}
@Bean
public SessionValidationScheduler sessionValidationScheduler(DefaultWebSessionManager sessionManager){
ExecutorServiceSessionValidationScheduler serviceSessionValidationScheduler = new ExecutorServiceSessionValidationScheduler();
serviceSessionValidationScheduler.setInterval(18000000);
serviceSessionValidationScheduler.setSessionManager(sessionManager);
return serviceSessionValidationScheduler;
}
@Bean
public ShiroManager shiroManager(){
return new ShiroManagerImpl();
}
@Bean(name="login")
public AccessControlFilter loginFilter(){
return new LoginFilter();
}
@Bean(name="role")
public AccessControlFilter roleFilter(){
return new RoleFilter();
}
@Bean(name="permission")
public AccessControlFilter permissionFilter(){
return new PermissionFilter();
}
@Bean(name="simple")
public AccessControlFilter simpleFilter(){
return new SimpleAuthFilter();
}
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
* <p>
* Filter Chain定义说明
* 1、一个URL可以配置多个Filter,使用逗号分隔
* 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/noPermission");
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//配置过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
//<!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSessionManager sessionManager(CustomShiroSessionDAO customShiroSessionDAO, SessionListener customSessionListener,
Cookie sessionIdCookie) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionValidationInterval(18000000);
sessionManager.setGlobalSessionTimeout(18000000);
sessionManager.setSessionDAO(customShiroSessionDAO);
List<SessionListener> sessionListeners = new ArrayList<SessionListener>();
sessionListeners.add(customSessionListener);
sessionManager.setSessionListeners(sessionListeners);
sessionManager.setSessionValidationScheduler(sessionValidationScheduler(sessionManager));
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdCookie(sessionIdCookie);
// sessionManager.setSessionDAO(redisSessionDAO());
return sessionManager;
}
@Bean
public SecurityManager securityManager(DefaultWebSessionManager sessionManager, Realm sampleRealm, CookieRememberMeManager rememberMeManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm.
securityManager.setRealm(sampleRealm);
// 自定义缓存实现 使用redis
//securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager);
SecurityUtils.setSecurityManager(securityManager);
securityManager.setRememberMeManager(rememberMeManager);
return securityManager;
}
@Bean
public SampleRealm sampleRealm(){
SampleRealm sampleRealm = new SampleRealm();
// myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return sampleRealm;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
* @return
*/
@Bean
public JedisManager jedisManager() {
JedisManager jedisManager = new JedisManager();
jedisManager.setJedisPool(jedisPool);
// redisManager.setPassword(password);
return jedisManager;
}
@Bean
public JedisShiroCacheManager jedisShiroCacheManager(JedisManager jedisManager){
JedisShiroCacheManager jedisShiroCacheManager = new JedisShiroCacheManager();
jedisShiroCacheManager.setJedisManager(jedisManager);
return jedisShiroCacheManager;
}
@Bean
public KickoutSessionFilter kickoutSessionFilter(){
KickoutSessionFilter kickoutSessionFilter = new KickoutSessionFilter();
kickoutSessionFilter.setKickoutUrl("login");
return kickoutSessionFilter;
}
}
这里方法上的参数会自动注入,等同于@Autowired的作用,所以不需要进行指定名称
其他类似spring-*文件也按照这种方式进行初始化,这里就不一一列出。
- webservice soap服务启动配置,这里使用的cxf
package com.dimpt.common.config;
import com.dimpt.webservices.emp.SBEIPEIPImportEmpInfoSrv;
import com.dimpt.webservices.org.SBEIPEIPImportOrgInfoSrv;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
import java.util.Properties;
/**
* Created by x250-thinkpad on 2019/1/7.
*/
@Configuration
public class WebserviceConfig {
@Autowired
private SBEIPEIPImportEmpInfoSrv sbEIPEIPImportEmpInfoSrvImpl;
@Autowired
private SBEIPEIPImportOrgInfoSrv sbEIPEIPImportOrgInfoSrvImpl;
@Bean
public ServletRegistrationBean cfxServlet(){
return new ServletRegistrationBean(new CXFServlet(),"/services/*");//发布服务名称
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public Endpoint SB_EIP_EIP_ImportOrgInfoSrv(){
Properties props = System.getProperties();
props.setProperty("org.apache.cxf.stax.allowInsecureParser", "1");
props.setProperty("UseSunHttpHandler", "true");
EndpointImpl endpoint = new EndpointImpl(springBus(),sbEIPEIPImportOrgInfoSrvImpl);
endpoint.publish("SB_EIP_EIP_ImportOrgInfoSrv");
//endpoint.setWsdlLocation("classpath:WEB-INF/wsdl/SB_EIP_EIP_ImportOrgInfoSrv/SB_EIP_EIP_ImportOrgInfoSrv.wsdl");
return endpoint;
}
@Bean
public Endpoint SB_EIP_EIP_ImportEmpInfoSrv(){
Properties props = System.getProperties();
props.setProperty("org.apache.cxf.stax.allowInsecureParser", "1");
props.setProperty("UseSunHttpHandler", "true");
EndpointImpl endpoint = new EndpointImpl(springBus(),sbEIPEIPImportEmpInfoSrvImpl);
endpoint.publish("SB_EIP_EIP_ImportEmpInfoSrv");
//endpoint.setWsdlLocation("classpath:WEB-INF/wsdl/SB_EIP_EIP_ImportEmpInfoSrv/SB_EIP_EIP_ImportEmpInfoSrv.wsdl");
return endpoint;
}
}
网上关于cxf创建soap服务的文章很多,这里不讲解具体实现,主要是配置,
Properties props = System.getProperties();
props.setProperty("org.apache.cxf.stax.allowInsecureParser", "1");
这句代码的含义是创建服务时先加载相应类,不然可能会出现ClassNotFound,这里也是借鉴网上经验。
*项目启动类
package com.dimpt;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication(scanBasePackages={"com.dimpt"})
@MapperScan("org.dimpt.watchtower.web.dao")
@EnableAspectJAutoProxy
@EnableTransactionManagement
@EnableScheduling
public class ItomApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application){
return application.sources(ItomApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ItomApplication.class, args);
}
}
这里继承SpringBootServletInitializer ,是因为打包成war包启动的原因,如果不打包成war包可不继承该类。
总结
选择使用springboot重构项目原因是多方面的,不管是迭代速度,社区活跃度,还是对spring-cloud,springdata 等的支持,spingboot对模块化项目也很友好,学习成本相对低,对新人友好,等等。
花了差不多3天的时间,排了很多坑,pom.xml中有一些细节大家可以自行体会,分享出来也是给大家一个借鉴。
网友评论