杂记:Spring与Springboot的本地化配置

  created  by  鱼鱼 {{tag}}
创建于 2018年12月03日 11:32:40 最后修改于 2019年06月09日 12:24:17
评论区
评论
{{comment.creator}}
{{comment.createTime}} {{comment.index}}楼
评论

杂记:Spring与Springboot的本地化配置

杂记:Spring与Springboot的本地化配置

    利用这篇文章巩固一下Spring框架的基础,因为发现接触到的各种Spring的项目配置杂七杂八,从xml到注解,从properties到json到yaml,他们各有千秋,没有哪一种方式可以绝对取代另一种配置,所以在这里统一介绍一下各种配置方式的内容和利弊,以便随时查看。这并不是一篇Spring框架领域的教程,只是一种技术的补足或是一种投机取巧的学习手段。

    spring项目配置实例

    原始的Spring是采用纯xml进行配置的,我从github上找了一个规范经典的SSM项目,以下是一些常用的配置,从这里就可以看出xml的基本格式:

ApplicationContext-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <!------------------------------DB--------------------------------->
    <!--   配置数据库相关参数properties的属性 -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    
    <!--   配置Spring事务处理 -->
    <bean id="tmptransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  		<property name="dataSource" ref="dataSource"/>
    </bean>
    
     <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
    
    <!--   数据库连接池 使用dbcp-->
    <bean id="tmpdataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<!-- Connection Info -->
		<property name="driverClassName" value="$${jdbc.driver}" />
		<property name="url" value="$${jdbc.url}" />
		<property name="username" value="$${jdbc.username}" />
		<property name="password" value="$${jdbc.password}" />
		<property name="initialSize" value="5" />
		<property name="maxActive" value="200" />
		<property name="maxWait" value="60000" />
		<property name="minIdle" value="1" />
		<property name="timeBetweenEvictionRunsMillis" value="30000" />
    	<property name="minEvictableIdleTimeMillis" value="300000" />
    </bean>

    <!--   配置SqlSessionFactory对象 -->
    <bean id="tmpsqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <!-- 扫描entity包 使用别名 -->
        <property name="typeAliasesPackage" value="com.app.entity" />
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>

    <!--   配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <!-- 扫描dao包 -->
        <property name="basePackage" value="com.app.dao" />
    </bean>
    
    <!--------------------------------MVC---------------------------------->
    <!-- 扫描service包下所有使用注解的类型-->
        <context:component-scan base-package="com.soecode.lyf.service" />
    <!-- 配置viewResolver -->
    <bean id="tmpviewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="suffix" value=".jsp"/>
                <property name="contentType" value="text/html; charset=UTF-8" />
    </bean>
    
    
</beans>
<configuration>
    <!-- 配置全局属性 -->
    <settings>
        <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true" />

        <!-- 使用列别名替换列名 默认:true -->
        <setting name="useColumnLabel" value="true" />

        <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>
</configuration>

jdbc.properties

jdbc.url=jdbc:mysql://xx:3306/xxx
jdbc.username=root
jdbc.password=123456
jdbc.driver=com.mysql.jdbc.Driver

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1" metadata-complete="true">
    <!-- 配置DispatcherServlet -->
    <servlet>
        <servlet-name>seckill-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置springMVC需要加载的配置文件,这里我合并成了一个文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:ApplicationContext-*.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>seckill-dispatcher</servlet-name>
        <!-- 默认匹配所有的请求 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

    使用xml配置

    传统的xml配置内容已经在前面罗列出不再赘述,有以下几个要点:

引入properties属性文件

    有以下两种方式:

<context:property-placeholder location="classpath:jdbc.properties,classpath:redis.properties" /> 

<!-------旧版本-注意:PropertyPlaceholderConfigurer在3.1之后版本被改为PropertySourcesPlaceholderConfigurer----->
<bean id="tmpjdbcProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
    <property name="locations"> 
        <list> 
            <value>classpath*:jdbc.properties</value>
            <value>classpath*:redis.properties</value>  
        </list> 
    </property> 
</bean>

    不管使用何种引用方式,PropertySourcesPlaceholderConfigurer全局范围内只有一个会生效。

    classpath*代表在导入的jar文件中也会进行查找,若非必要不要使用*,会降低执行效率。

自动扫描包

<context:component-scan base-package="com.app" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

    其中,include-filter是可选的,该配置项扫描包下的注解(@Service,@Component,@Repository,@Controller等),这里配置了一个过滤器,指定只扫描包中的Controller注解类,并将其注册为bean。当然,也可以手动配置注入所有的bean,但在可以用注解标注一个bean的今天,几乎已经没有人会这样做了。

    使用如下注解可以激活@Resource,@PostConstruct,@PreDestroy,@PersistenceContext,@Autowored,@Required等注解类:

<context:annotation-config />

    前者是包含后者的,所以定义了包扫描后,就不必在再注册annotationConfig。

    他们本质上其实还是注册了bean。

Spring mvc的常用配置

    写视图解析器:

<bean id="tmpviewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="suffix" value=".jsp"/>
        <property name="prefix" value="/WEB-INF/"/>
        <property name="contentType" value="text/html; charset=UTF-8" />
</bean>

这是Spring SSM最常见的一种视图解析器,还有很多解析器在此不详述,可以从这篇博客详细查看呢ViewResolver 视图解析器

    还有一些常用标签:

<!-------------不拦截静态资源,譬如静态目录下的js等---------------------------->
<!-------------因为web.xml中配置的拦截器已经拦截了所有 / 的url,所以不加此标签静态资源会被当成servlet请求处理--------------->
<mvc:default-servlet-handler/>

<!-------------mvc注解驱动,可以使用@RequestMapping等注解-------------------->
<mvc:annotation-driven />

<!-------------未被定义为Controller的请求内容将映射为/default------------>
<mvc:view-controller path="/" view-name="redirect:/default"/>
<!-------------将未定义为Controller的请求按视图解析器映射到资源路径下的/default(/WEB_INF/default.jsp)------------>
<mvc:view-controller path="/" view-name="/default"/>

注意:一般情况下 前两个标签会同时存在,否则会引发问题,例如view-controller的请求将直接解析而不再检查RequestMapping。

其他配置项目

启动定时任务(更多资源在Quertz那篇博客内):

<task:annotation-driven/>

导入资源:

<import resource="classpath:com/xxx/fisea.xml" />

    使用注解配置

    最基本的注解,使用如下注解声明注入一个bean:

@Component:当对组件的层次难以定位的时候使用这个注解

@Controller:表示控制层的组件

@Service:表示业务逻辑层的组件

@Repository:表示数据访问层的组件

    以上注解在功能上实际上是相同的,这不是单独使用的,需要配合xml文件中的注解扫描。

    而在对应的变量上面使用@Resource、@Autowired、@Qualifier 实现自动注入res 使用@Value("xx")实现自动注入值。

    @Qualifier代表byName注入、@Autowired代表byType注入、@Resource可以进行配置,默认使用byName。

使用@Configuration注解配置

    可以使用@Configuration和@Bean来取代xml中的注解配置,每一个@Bean标注的方法返回值都对应着一个注入容器中的bean,bean name默认同方法名,而对应的@Configuration标注的类则可以理解为一个xml:

@Configuration
public class MiniConfig{
    @Bean
    public User user(){
        User user=new User();
        user.setName("老李");
        return user;
    }
}

引入properties

    使用注解引入属性文件:

@PropertySource("classpath:ch2/test.properties")  
public clss Config{
        //@Value注解可以装配bean的属性值,properties值,定义变量
    @Value("${server.name}")         //装配properties属性    
    private String normal;
    @Value("fish")
    private String name;
    @Value("#{dataSource.url}")        //装配bean的属性
    private String jdbc;
}

其他配置项

    你可能还需要配置xml的一些东西,这种配置形式一般使用在Springboot中:

@Configuration
@SpringBootConfiguration   //在Springboot中如果用了这个注解 就不要使用@Configuration了(其实是一个东西)
@EnableAutoConfiguration            //根据项目依赖添加自动配置项
@EnableWebMvc        //TODO
@ComponentScan(basePackages = "com.app")        //开启扫描,不指定basePackages扫描改类目录下所有目录
@Import(MaxConfig.class)                //引入其他配置
@MapperScan(value="org.fhp.springmybatis.dao")
@ImportResource("classpath:spring-mybatis.xml")        //使用xml注册bean
public class MiniConfig{
   
}

    很多注解内容一看就明白,在这里也就不多说了。

    使用Yaml取代properties

properties

    .properties文件用于申明一些在项目中常用的值(格式xxx=xxx)。除了以上两种引用方式,最基本的Properties取值是这样的:

Properties properties = new Properties();
// 使用ClassLoader加载properties配置文件生成对应的输入流
InputStream in = PropertiesMain.class.getClassLoader().getResourceAsStream("config/config.properties");
// 使用properties对象加载输入流
properties.load(in);
//获取key对应的value值
properties.getProperty(String key);

    web.xml

    在早期版本,web.xml几乎是web项目必不可少的配置文件,里面记录一些servlrt的常用配置,在不使用MVC框架时,需要用此文件定义servlet与url的对应关系,同时也可以定义过滤器和监听器,还有一些服务器相关的配置项,说一下常用的配置项,当然,有些内容已经过时了:

指定项目名(比如是在Tomcat管理页面显示的内容):

<display-name>fish</display-name>

指定一些初始化参数(应用在整个应用范围内):

<context-param>  
    <param-name>webAppRootKey</param-name>  
    <param-value>fish.root</param-value>  
</context-param>  
 
<context-param>  
    <param-name>contextConfigLocation</param-name>  
    <param-value>/WEB-INF/spring-configuration/*.xml</param-value>  
</context-param>

    这样配置的值可以在项目中使用ServletContext.getInitParameter("")读取,这是可选配置,此处定义了一个WebAppRootKey,它的值是一个key,默认是webapp.root,在以上项目中,可以使用System.getProperty("fish.root")获取项目路径,在同一容器下部署多个项目,需配置多个不同的WebAppRootKey。

    contextConfigLocation指定了项目要加载的Spring配置文件,默认值为/WEB-INF/applicationontext.xml,多个之间用逗号、空格或是分号隔开。

指定监听器:

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
</listener> 
 
<listener>  
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
</listener> 
	
<listener>
    <listener-class>com.app.mq.executor.JobExecutor</listener-class>
</listener>

    第二个监听器是必须使用的,当然 也可以集成接口,自己重写。

指定过滤器:

<!-- 字符集过滤器 -->
<filter>  
    <filter-name>CharacterEncodingFilter</filter-name>  
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    <init-param>  
        <param-name>encoding</param-name>  
        <param-value>UTF-8</param-value>  
    </init-param>  
    <init-param>  
        <param-name>forceEncoding</param-name>  
        <param-value>true</param-value>  
    </init-param>  
</filter>

指定servlet:

   尾注

    这篇博客基本涵盖了当前所有主流的项目本地方式,注意,是本地!在实际开发中,还有很多配置方式,比如利用统一配置中心(例如携程的Apollo),实际开发中也不应该拘泥于某一项配置方式,而应是配合使用。

    前文中,利用注解配置已经做到了项目去XML,尤其是在Springboot框架下的环境,甚至看不到xml的身影,但是,我们是不是忘记了什么?

    被遗忘的web.xml

    没错,在Springboot项目中,我们根本看不到web.xml的身影。

    //TODO

参考链接:手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis


2019-06-09鱼鱼

{{commentTitle}}

评论   ctrl+Enter 发送评论