学习目标:
- SpringBoot框架搭建
- 无缝转移项目
- 利用SpringBoot特性做修改
迁移pom文件
在pom文件中先删除SpringMVC、junit 、mybatis,然后迁移到springboot项目中。
迁移dao文件
将src/main/resources文件下的jdbc.properties迁移到springboot的application.properties文件,再将logback.xml、mybatis-config.xml以及水印图片watermark.jpg都移动到springboot的resources文件下。
springboot讲究去xml化,所以很多xml配置文件我们就不迁移到springboot中,而是用代码来代替他的功能,将它写成类的配置。首先在MVC项目中的resources/spring下的spring-dao.xml文件中,我们配置了datasources、SqlSessionFactory等启动一个bean,但是扫描dao接口包呢在springboot中会启动全package扫描,所以不用配置。然后我们在springboot中创建com/imooc/o2o/config/dao的DataSourceConfiguration.java:
/**
* 配置datasource到ioc容器里面
*
*/
@Configuration
// 配置mybatis mapper的扫描路径
@MapperScan("com.imooc.o2o.dao")
public class DataSourceConfiguration {
@Value("${jdbc.driver}")
private String jdbcDriver;
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
/**
* 生成与spring-dao.xml对应的bean dataSource
*
* @return
* @throws PropertyVetoException
*/
@Bean(name = "dataSource")
public ComboPooledDataSource createDataSource() throws PropertyVetoException {
// 生成datasource实例
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 跟配置文件一样设置以下信息
// 驱动
dataSource.setDriverClass(jdbcDriver);
// 数据库连接URL
dataSource.setJdbcUrl(jdbcUrl);
// 设置用户名
dataSource.setUser(DESUtil.getDecryptString(jdbcUsername));
// 设置用户密码
dataSource.setPassword(DESUtil.getDecryptString(jdbcPassword));
// 配置c3p0连接池的私有属性
// 连接池最大线程数
dataSource.setMaxPoolSize(30);
// 连接池最小线程数
dataSource.setMinPoolSize(10);
// 关闭连接后不自动commit
dataSource.setAutoCommitOnClose(false);
// 连接超时时间
dataSource.setCheckoutTimeout(10000);
// 连接失败重试次数
dataSource.setAcquireRetryAttempts(2);
return dataSource;
}
}
然后创建SessionFactoryConfiguration.java:
@Configuration
public class SessionFactoryConfiguration {
// mybatis-config.xml配置文件的路径
private static String mybatisConfigFile;
@Value("${mybatis_config_file}")
public void setMybatisConfigFile(String mybatisConfigFile) {
SessionFactoryConfiguration.mybatisConfigFile = mybatisConfigFile;
}
// mybatis mapper文件所在路径
private static String mapperPath;
@Value("${mapper_path}")
public void setMapperPath(String mapperPath) {
SessionFactoryConfiguration.mapperPath = mapperPath;
}
// 实体类所在的package
@Value("${type_alias_package}")
private String typeAliasPackage;
@Autowired
private DataSource dataSource;
/**
* 创建sqlSessionFactoryBean 实例 并且设置configtion 设置mapper 映射路径 设置datasource数据源
*
* @return
* @throws IOException
*/
@Bean(name = "sqlSessionFactory")
public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 设置mybatis configuration 扫描路径
sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFile));
// 添加mapper 扫描路径
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath;
sqlSessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources(packageSearchPath));
// 设置dataSource
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置typeAlias 包扫描路径
sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasPackage);
return sqlSessionFactoryBean;
}
}
然后我们将MVC中的dao、entity、util以及src/main/resources下的mapper文件都迁移到springboot中,然后将ut中的AreaDaoTest.java移进来,然后因为我们不用xml文件了,测试类中也没有了BaseTest类,所以不用继承BaseTest,取而代之的是@RunWith(SpringRunner.class)、@SpringBootTest两个注解。至此,dao层迁移成功。
迁移service文件
接下来是service层的迁移,在spring-service.xml配置文件中,一个是配置事务管理器,有bean标签,我们可以用代码的方式实现,然后是配置基于注解的声明式事务,这个有一个tx:annotation-driven标签,不能写入bean,我们可以用继承的方式来实现。
同理,我们在config文件下创建service文件,然后写一个TransactionManagementConfuguration.java:
/**
* 对标spring-service里面的transactionManager
* 继承TransactionManagementConfigurer是因为开启annotation-driven
*
*/
@Configuration
// 首先使用注解 @EnableTransactionManagement 开启事务支持后
// 在Service方法上添加注解 @Transactional 便可
@EnableTransactionManagement
public class TransactionManagementConfiguration implements TransactionManagementConfigurer {
@Autowired
// 注入DataSourceConfiguration里边的dataSource,通过createDataSource()获取
private DataSource dataSource;
@Override
/**
* 关于事务管理,需要返回PlatformTransactionManager的实现
*/
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource);
}
}
接下来是spring-redis.xml配置文件的迁移,因为偶我们在src/main/resources下的redis.properties文件配置了redis的相关信息,所以我们将该文件下的配置信息转移到springboot的application.properties文件。然后将spring-redis.xml文件转换为springboot的config/redis的RedisConfiguration.java中:
/**
* spring-redis.xml里的配置
*
*/
@Configuration
public class RedisConfiguration {
@Value("${redis.hostname}")
private String hostname;
@Value("${redis.port}")
private int port;
@Value("${redis.pool.maxActive}")
private int maxTotal;
@Value("${redis.pool.maxIdle}")
private int maxIdle;
@Value("${redis.pool.maxWait}")
private long maxWaitMillis;
@Value("${redis.pool.testOnBorrow}")
private boolean testOnBorrow;
@Autowired
private JedisPoolConfig jedisPoolConfig;
@Autowired
private JedisPoolWriper jedisWritePool;
@Autowired
private JedisUtil jedisUtil;
/**
* 创建redis连接池的设置
*
* @return
*/
@Bean(name = "jedisPoolConfig")
public JedisPoolConfig createJedisPoolConfig() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 控制一个pool可分配多少个jedis实例
jedisPoolConfig.setMaxTotal(maxTotal);
// 连接池中最多可空闲maxIdle个连接 ,这里取值为20,
// 表示即使没有数据库连接时依然可以保持20空闲的连接,
// 而不被清除,随时处于待命状态。
jedisPoolConfig.setMaxIdle(maxIdle);
// 最大等待时间:当没有可用连接时,
// 连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
// 在获取连接的时候检查有效性
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
return jedisPoolConfig;
}
/**
* 创建Redis连接池,并做相关配置
*
* @return
*/
@Bean(name = "jedisWritePool")
public JedisPoolWriper createJedisPoolWriper() {
JedisPoolWriper jedisPoolWriper = new JedisPoolWriper(jedisPoolConfig, hostname, port);
return jedisPoolWriper;
}
/**
* 创建Redis工具类,封装好Redis的连接以进行相关的操作
*
* @return
*/
@Bean(name = "jedisUtil")
public JedisUtil createJedisUtil() {
JedisUtil jedisUtil = new JedisUtil();
jedisUtil.setJedisPool(jedisWritePool);
return jedisUtil;
}
/**
* Redis的key操作
*
* @return
*/
@Bean(name = "jedisKeys")
public JedisUtil.Keys createJedisKeys() {
JedisUtil.Keys jedisKeys = jedisUtil.new Keys();
return jedisKeys;
}
/**
* Redis的Strings操作
*
* @return
*/
@Bean(name = "jedisStrings")
public JedisUtil.Strings createJedisStrings() {
JedisUtil.Strings jedisStrings = jedisUtil.new Strings();
return jedisStrings;
}
}
然后将dto、enums、exceptions、service、util包转移到spring boot项目中去。然后用service的测试类AreaServiceTest.java、WechatAuthServiceTest.java来测试。
接下来是web层,同样,在config/web的MvcConfiguration.java进行类的配置来代替MVC中spring-web.xml配置文件,
/**
* 开启Mvc,自动注入spring容器。 WebMvcConfigurerAdapter:配置视图解析器
* 当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean
*
*/
@Configuration
// 等价于<mvc:annotation-driven/>
@EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter implements ApplicationContextAware {
// Spring容器
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 静态资源配置
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");
// registry.addResourceHandler("/upload/**").addResourceLocations("file:/Users/baidu/work/image/upload/");
registry.addResourceHandler("/upload/**")
.addResourceLocations("file:/D:/projectdev/image/upload/");
}
/**
* 定义默认的请求处理器
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
/**
* 创建viewResolver
*
* @return
*/
@Bean(name = "viewResolver")
public ViewResolver createViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
// 设置Spring 容器
viewResolver.setApplicationContext(this.applicationContext);
// 取消缓存
viewResolver.setCache(false);
// 设置解析的前缀
viewResolver.setPrefix("/WEB-INF/html/");
// 设置试图解析的后缀
viewResolver.setSuffix(".html");
return viewResolver;
}
/**
* 文件上传解析器
*
* @return
*/
@Bean(name = "multipartResolver")
public CommonsMultipartResolver createMultipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setDefaultEncoding("utf-8");
// 1024 * 1024 * 20 = 20M
multipartResolver.setMaxUploadSize(20971520);
multipartResolver.setMaxInMemorySize(20971520);
return multipartResolver;
}
@Value("${kaptcha.border}")
private String border;
@Value("${kaptcha.textproducer.font.color}")
private String fcolor;
@Value("${kaptcha.image.width}")
private String width;
@Value("${kaptcha.textproducer.char.string}")
private String cString;
@Value("${kaptcha.image.height}")
private String height;
@Value("${kaptcha.textproducer.font.size}")
private String fsize;
@Value("${kaptcha.noise.color}")
private String nColor;
@Value("${kaptcha.textproducer.char.length}")
private String clength;
@Value("${kaptcha.textproducer.font.names}")
private String fnames;
/**
* 由于web.xml不生效了,需要在这里配置Kaptcha验证码Servlet
*/
@Bean
public ServletRegistrationBean servletRegistrationBean() throws ServletException {
ServletRegistrationBean servlet = new ServletRegistrationBean(new KaptchaServlet(), "/Kaptcha");
servlet.addInitParameter("kaptcha.border", border);// 无边框
servlet.addInitParameter("kaptcha.textproducer.font.color", fcolor); // 字体颜色
servlet.addInitParameter("kaptcha.image.width", width);// 图片宽度
servlet.addInitParameter("kaptcha.textproducer.char.string", cString);// 使用哪些字符生成验证码
servlet.addInitParameter("kaptcha.image.height", height);// 图片高度
servlet.addInitParameter("kaptcha.textproducer.font.size", fsize);// 字体大小
servlet.addInitParameter("kaptcha.noise.color", nColor);// 干扰线的颜色
servlet.addInitParameter("kaptcha.textproducer.char.length", clength);// 字符个数
servlet.addInitParameter("kaptcha.textproducer.font.names", fnames);// 字体
return servlet;
}
/**
* 添加拦截器配置
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/** 店家管理系统拦截部分 **/
String interceptPath = "/shopadmin/**";
// 注册拦截器
InterceptorRegistration loginIR = registry.addInterceptor(new ShopLoginInterceptor());
// 配置拦截的路径
loginIR.addPathPatterns(interceptPath);
/** shopauthmanagement page **/
loginIR.excludePathPatterns("/shopadmin/addshopauthmap");
/** scan **/
loginIR.excludePathPatterns("/shopadmin/adduserproductmap");
loginIR.excludePathPatterns("/shopadmin/exchangeaward");
// 还可以注册其它的拦截器
InterceptorRegistration permissionIR = registry.addInterceptor(new ShopPermissionInterceptor());
// 配置拦截的路径
permissionIR.addPathPatterns(interceptPath);
// 配置不拦截的路径
/** shoplist page **/
permissionIR.excludePathPatterns("/shopadmin/shoplist");
permissionIR.excludePathPatterns("/shopadmin/getshoplist");
/** shopregister page **/
permissionIR.excludePathPatterns("/shopadmin/getshopinitinfo");
permissionIR.excludePathPatterns("/shopadmin/registershop");
permissionIR.excludePathPatterns("/shopadmin/shopoperation");
/** shopmanage page **/
permissionIR.excludePathPatterns("/shopadmin/shopmanagement");
permissionIR.excludePathPatterns("/shopadmin/getshopmanagementinfo");
/** shopauthmanagement page **/
permissionIR.excludePathPatterns("/shopadmin/addshopauthmap");
/** scan **/
permissionIR.excludePathPatterns("/shopadmin/adduserproductmap");
permissionIR.excludePathPatterns("/shopadmin/exchangeaward");
/** 超级管理员系统拦截部分 **/
interceptPath = "/superadmin/**";
// 注册拦截器
InterceptorRegistration superadminloginIR = registry.addInterceptor(new SuperAdminLoginInterceptor());
// 配置拦截的路径
superadminloginIR.addPathPatterns(interceptPath);
superadminloginIR.excludePathPatterns("/superadmin/login");
superadminloginIR.excludePathPatterns("/superadmin/logincheck");
superadminloginIR.excludePathPatterns("/superadmin/main");
superadminloginIR.excludePathPatterns("/superadmin/top");
superadminloginIR.excludePathPatterns("/superadmin/clearcache4area");
superadminloginIR.excludePathPatterns("/superadmin/clearcache4headline");
superadminloginIR.excludePathPatterns("/superadmin/clearcache4shopcategory");
}
}
然后将web文件转移到springboot项目中,web层就转移成功了。
接下来进行前端的操作,然后将src/main里的webapp转移到项目里,然后由于springboot中没有src/main/webapp/WEB-INF/html/web.xml配置文件,所以我们在spring boot的application.properties和MvcConfiguration.java中配置相关信息来迁移kaptcha验证码。
在mvc中我们在外置tomcat的servers里的server.xml将图片的根路径docBase指定了,但是springboot是内置tomcat的,所以我们需要在MvcConfiguration.java加入相关的类来指定目录。
然后拦截器就是先将mvc中的interceptor包转移到springboot中,然后也是在MvcConfiguration.java中添加addInterceptor方法来指定拦截器。