真实完整步骤,踩坑整理 有同样的坑,欢迎补充整理
网上的案例老是少了很多配置,本案例涉及到 spring-mvc,自定义多数据源,统一前缀,事务,mybatis,jsp访问异常,静态文件。
项目还是老的目录结构
springboot的目的就是为了简化开发,使用配置的方式,因此 我们最终的目标 就是删除springmvc项目中 web.xml springmvc相关配置 mybatis配置等;
1.添加springboot相关的pom依赖
redis、日志等等按需添加,老的spring的相关都删除
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<build>
<finalName>JoeProject</finalName>
<outputDirectory>${basedir}/target/site</outputDirectory>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/webapp</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.添加启动类
@SpringBootApplication
public class JoeApplication extends SpringBootServletInitializer {
// 入口
public static void main(String[] args) {
SpringApplication.run(JoeApplication.class, args);
}
// Java EE应用服务器配置,
// 如果要使用tomcat来加载jsp的话就必须继承SpringBootServletInitializer类并且重写其中configure方法
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JoeApplication.class);
}
}
3.添加 application.yml
3.1包括端口,全局参数以及全局路径,环境分支,上传
3.2本案例 数据源暂时不用配置(因为老的使用了多数据源 并且需要自定义解析数据库的密文,因此下面将使用编程式(较传统)配置多数据源),也可以使用苞米豆的 多数据源配置,然后注解Ds()
server:
port: 8082
servlet:
encoding:
charset: utf-8
context-path: /Joe
# 全局变量参数,可以用在jsp中 <script src="<%=application.getInitParameter("Joe") %>/static/ss.js></script>
context-parameters:
Joe: /Joe
spring:
profiles:
active: branch
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
4.重点!! web.xml的处理
4.1 老的web.xml都可以删除,但是里面一些主要的,包括全局参数 、欢迎页、异常处理、以及springmvc的配置文件(拦截器、事务、数据源与mybatis配置)都需要代码来处理
4.2 老项目全是*.do idea可以全局替换(注意要全词匹配 .do,然后大概看下防止错误) Eidt-find-replace in files
4.2.1 静态文件get请求处理
4.3 对spring-mvc.xml进行配置
4.3.1 路径拦截处理
修改后:
WebmvcConfig.java
@Configuration
// 踩坑 extends WebMvcConfigurationSupport导致我的页面访问请求都被当作一个Controller层请求而被处理了。导致页面的 js css都加载不出来
@Configuration
// public class WebmvcConfig extends WebMvcConfigurationSupport {
public class WebmvcConfig implements WebMvcConfigurer {
// 首页添加
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("views/loadLogin");
}
// 踩坑,不能使用application.yml的配置方式
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/test/*")
.excludePathPatterns("/", "/login", "/css/**", "/js/**", "/views/**");
super.addInterceptors(registry);
}
}
LoginInterceptor.java
public class LoginInterceptor extends BaseInterceptor implements HandlerInterceptor {
// 验证
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
Cookie userSysno = CookiesUntil.getCookieByName(request, "userSysno");
Cookie sid = CookiesUntil.getCookieByName(request, "sid");
boolean re;
if (userSysno != null && sid != null) {
re = this.checkLogin(request, response, sid, userSysno);
} else {
RedisUtil.ClearKey(userSysno.getValue() + "permissions");
re = false;
}
if (!re) {
RedisUtil.ClearKey(userSysno.getValue() + "permissions");
request.getRequestDispatcher("/login/loginOut").forward(request, response);
return false;
} else {
return true;
}
} catch (Exception ex) {
System.out.println("preHandle:" + ex.getMessage());
request.getRequestDispatcher("/login/loginOut").forward(request, response);
return false;
}
}
}
5.重点!!spring-mybatis配置修改 多数据源处理
老项目采用的AbstractRoutingDataSource、自定义SqlSessionFactoryBean、ThreadLocal<String> contextHolder切换数据源。
四个类搞定自定义多数据源
DynamicDataSource.java
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return CustomerContextHolder.getCustomerType();
}
}
DatasourceConfig.java 多数元配置
@Configuration
public class DatasourceConfig {
@Value("${jdbc.url: sqlserver://allin.w.allin}")
public String jdbcUrl;
@Value("${jdbc17.url: sqlserver://allin.r.Joe}")
public String jdbc17Url;
@Value("${jdbcallinDatatool.url: sqlserver://allin.w.allindatatool}")
public String jdbcallinDatatoolUrl;
@Value("${jdbc17Joeallin.url: sqlserver://allin.w.Joeallin}")
@Primary
@Bean(name = "dataSource1")
public DataSource dataSource1() {
DruidDataSource ds = new DruidDataSource();
try {
ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 自定义解析 配置文件中的url,可以使用setpassword setname
ds.setUrl(AllineDecoderClient.getInstance().getConnectionString(jdbcUrl));
} catch (Exception e) {
e.printStackTrace();
}
return ds;
}
@Bean(name = "dataSource2")
public DataSource dataSource2() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
ds.setUrl(AllineDecoderClient.getInstance().getConnectionString(jdbc17Url));
return ds;
}
@Bean(name = "dataSource3")
public DataSource dataSource3() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
ds.setUrl(AllineDecoderClient.getInstance().getConnectionString(jdbcallinDatatoolUrl));
return ds;
}
@Bean(name = "dataSource4")
public DataSource dataSource4() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
ds.setUrl(AllineDecoderClient.getInstance().getConnectionString(jdbc17JoeallinUrl));
return ds;
}
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("dataSource1", dataSource1());
dataSourceMap.put("dataSource2", dataSource2());
dataSourceMap.put("dataSource3", dataSource3());
dataSourceMap.put("dataSource4", dataSource4());
dynamicDataSource.setTargetDataSources(dataSourceMap);
// 设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(dataSource1());
return dynamicDataSource;
}
}
CustomerContextHolder.java
public class CustomerContextHolder {
public static final String DATA_SOURCE_A = "dataSource1";
public static final String DATA_SOURCE_B = "dataSource2";
public static final String DATA_SOURCE_C = "dataSource3";
public static final String DATA_SOURCE_D = "dataSource4";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}
public static String getCustomerType() {
return contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
DataSourceConfigDynamic.java
@Configuration
@MapperScan(basePackages = "com.Joe.allin.dao", sqlSessionFactoryRef = "sqlSessionFactory") // 踩坑 未配置sqlSessionFactoryRef
public class DataSourceConfigDynamic {
@Primary
@Bean("sqlSessionFactory")
SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dynamicDataSource);
// 踩坑 未配置setMapperLocations
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/Joe/allin/mapping/*.xml"));
return bean.getObject();
}
}
-- 使用多数据源 在service调用dao层数据源前使用,然后清楚,默认数据源A不用写
CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_B);
xxService.test();
CustomerContextHolder.clearCustomerType();
6.全局事务采用注解方式
7.全局异常处理 度娘一大堆
8.可能还会出现循环依赖、乱码、版本依赖冲突等。根据自己的问题自行处理
9.关于war jar的问题,我还是使用的war包,启动 直接application的方式就可以,依赖里内嵌了tomcat
版权归原作者 xuli_joe 所有, 如有侵权,请联系我们删除。