开源项目学习-jeesite1.2.7-配置文件

本文目的为查看jeesite的配置文件都配了点啥,缺失部分待补

WEB-INF/web.xml

配置DispatcherServlet

代码片段1,代码片段2

可以看到上述代码中定义了一个自己的listener,目前感觉作用不大

package com.thinkgem.jeesite.modules.sys.listener;

import javax.servlet.ServletContext;

import org.springframework.web.context.WebApplicationContext;

import com.thinkgem.jeesite.modules.sys.service.SystemService;

public class WebContextListener extends org.springframework.web.context.ContextLoaderListener {
    
    @Override
    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
        if (!SystemService.printKeyLoadMessage()){
            return null;
        }
        return super.initWebApplicationContext(servletContext);
    }
}

这么做有啥用?怎么用?

基础知识

resources/spring-mvc.xml

加载配置属性文件

代码片段

<!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:jeesite.properties" />

依赖注入相关

使用Annotation自动注册Bean,只扫描@Controller:

代码片段1

<!-- 使用Annotation自动注册Bean,只扫描@Controller -->
    <context:component-scan base-package="com.thinkgem.jeesite" use-default-filters="false"><!-- base-package 如果多个,用“,”分隔 -->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

这么做有啥用?怎么用?

详述context:component-scan作用

信息转换

代码片段1

<!-- 默认的注解映射的支持,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -->
    <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
        <mvc:message-converters register-defaults="true">
            <!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8" />
            </bean>
            <!-- 将Jackson2HttpMessageConverter的默认格式化输出为false -->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list><value>application/json;charset=UTF-8</value></list>
                </property>
                <property name="prettyPrint" value="false"/>
                <property name="objectMapper">  
                    <bean class="com.thinkgem.jeesite.common.mapper.JsonMapper"></bean>  
                </property> 
            </bean>
            <!-- 使用XML格式输出数据 -->
            <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                <constructor-arg>
                    <bean class="org.springframework.oxm.xstream.XStreamMarshaller">
                        <property name="streamDriver">
                            <bean class="com.thoughtworks.xstream.io.xml.StaxDriver"/>
                        </property>
                        <property name="annotatedClasses">
                            <list>
                                <value>com.thinkgem.jeesite.common.persistence.BaseEntity</value>
                                <value>com.thinkgem.jeesite.common.supcan.treelist.TreeList</value>
                                <value>com.thinkgem.jeesite.common.supcan.treelist.cols.Col</value>
                                <value>com.thinkgem.jeesite.common.supcan.treelist.cols.Group</value>
                            </list>
                        </property>
                    </bean>
                </constructor-arg>
                <property name="supportedMediaTypes" value="application/xml"></property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

这么做有啥用?怎么用?

基础知识

根据URL后缀自动判定Content-Type及相应的View

代码片段

<!-- REST中根据URL后缀自动判定Content-Type及相应的View -->
    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="mediaTypes" >
            <map> 
                <entry key="xml" value="application/xml"/> 
                <entry key="json" value="application/json"/> 
            </map>
        </property>
        <property name="ignoreAcceptHeader" value="true"/>
        <property name="favorPathExtension" value="true"/>
    </bean>

目前没有啥感觉

这么做有啥用?怎么用?

springmvc不同的url后缀返回不同格式的数据

定义视图文件解析

<!-- 定义视图文件解析 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="${web.view.prefix}"/>
        <property name="suffix" value="${web.view.suffix}"/>
    </bean>

这么做有啥用?怎么用?

基础知识

静态资源相关

代码片段

<!-- 对静态资源文件的访问, 将无法mapping到Controller的path交给default servlet handler处理 -->
<mvc:default-servlet-handler />
    
<!-- 静态资源映射 -->
<mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>

这么做有啥用?怎么用?

基础知识

定义无Controller的path<->view直接映射

代码片段

<!-- 定义无Controller的path<->view直接映射 -->
	<mvc:view-controller path="/" view-name="redirect:${web.view.index}"/>

这么做有啥用?怎么用?

springmvc基础知识(15):mvc:view-controller标签

拦截器配置,拦截顺序:先执行后定义的,排在第一位的最后执行

代码片段

<!-- 拦截器配置,拦截顺序:先执行后定义的,排在第一位的最后执行。-->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="${adminPath}/**" />
			<mvc:exclude-mapping path="${adminPath}/"/>
			<mvc:exclude-mapping path="${adminPath}/login"/>
			<mvc:exclude-mapping path="${adminPath}/sys/menu/tree"/>
			<mvc:exclude-mapping path="${adminPath}/sys/menu/treeData"/>
			<mvc:exclude-mapping path="${adminPath}/oa/oaNotify/self/count"/>
			<bean class="com.thinkgem.jeesite.modules.sys.interceptor.LogInterceptor" />
		</mvc:interceptor>
		<!-- 手机视图拦截器 -->
		<mvc:interceptor>
			<mvc:mapping path="/**" />
			<bean class="com.thinkgem.jeesite.modules.sys.interceptor.MobileInterceptor" />
		</mvc:interceptor>
	</mvc:interceptors>

上述代码定义了一个自己的拦截器:LogInterceptor

public class LogInterceptor extends BaseService implements HandlerInterceptor {

	private static final ThreadLocal<Long> startTimeThreadLocal =
			new NamedThreadLocal<Long>("ThreadLocal StartTime");
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
			Object handler) throws Exception {
		if (logger.isDebugEnabled()){
			long beginTime = System.currentTimeMillis();//1、开始时间  
	        startTimeThreadLocal.set(beginTime);		//线程绑定变量(该数据只有当前请求的线程可见)  
	        logger.debug("开始计时: {}  URI: {}", new SimpleDateFormat("hh:mm:ss.SSS")
	        	.format(beginTime), request.getRequestURI());
		}
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
			ModelAndView modelAndView) throws Exception {
		if (modelAndView != null){
			logger.info("ViewName: " + modelAndView.getViewName());
		}
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
			Object handler, Exception ex) throws Exception {

		// 保存日志
		LogUtils.saveLog(request, handler, ex, null);
		
		// 打印JVM信息。
		if (logger.isDebugEnabled()){
			long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)  
			long endTime = System.currentTimeMillis(); 	//2、结束时间  
	        logger.debug("计时结束:{}  耗时:{}  URI: {}  最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m",
	        		new SimpleDateFormat("hh:mm:ss.SSS").format(endTime), DateUtils.formatDateTime(endTime - beginTime),
					request.getRequestURI(), Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024, 
					(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024); 
	        //删除线程变量中的数据,防止内存泄漏
	        startTimeThreadLocal.remove();
		}
		
	}

}

这段代码的作用就是通过拦截器用日志记录某个请求的耗时等信息。

这么做有啥用?怎么用?

基础知识

支持Shiro对Controller的方法级AOP安全控制

相关代码

    <!-- 支持Shiro对Controller的方法级AOP安全控制 begin-->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true" />
    </bean>
    
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
                <prop key="java.lang.Throwable">error/500</prop>
            </props>
            </property>
    </bean>
    <!-- 支持Shiro对Controller的方法级AOP安全控制 end -->

第一次接触,先不管了

文件上传相关

相关代码

<!-- 上传文件拦截,设置最大上传文件大小   10M=10*1024*1024(B)=10485760 bytes -->  
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
	<property name="maxUploadSize" value="${web.maxUploadSize}" />  
</bean>

这么做有啥用?怎么用?

基础知识

resources/spring-context.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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd"
	default-lazy-init="true">

	<description>Spring Configuration</description>
	
    <!-- 加载配置属性文件 -->
	<context:property-placeholder ignore-unresolvable="true" location="classpath:jeesite.properties" />
	
	<!-- 加载应用属性实例,可通过  @Value("#{APP_PROP['jdbc.driver']}") String jdbcDriver 方式引用 -->
    <util:properties id="APP_PROP" location="classpath:jeesite.properties" local-override="true"/>
	
	<!-- 使用Annotation自动注册Bean,解决事物失效问题:在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解。  -->
	<context:component-scan base-package="com.thinkgem.jeesite"><!-- base-package 如果多个,用“,”分隔 -->
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>
	
 	<!-- MyBatis begin -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.thinkgem.jeesite"/>
        <property name="typeAliasesSuperType" value="com.thinkgem.jeesite.common.persistence.BaseEntity"/>
        <property name="mapperLocations" value="classpath:/mappings/**/*.xml"/>
		<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
    </bean>
    
    <!-- 扫描basePackage下所有以@MyBatisDao注解的接口 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="com.thinkgem.jeesite"/>
        <property name="annotationClass" value="com.thinkgem.jeesite.common.persistence.annotation.MyBatisDao"/>
    </bean>
    
    <!-- 定义事务 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务  -->
	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
    <!-- MyBatis end -->
    
	<!-- 配置 JSR303 Bean Validator 定义 -->
	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

	<!-- 缓存配置 -->
	<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		<property name="configLocation" value="classpath:${ehcache.configFile}" />
	</bean>
	
	<!-- 计划任务配置,用 @Service @Lazy(false)标注类,用@Scheduled(cron = "0 0 2 * * ?")标注方法 -->
    <task:executor id="executor" pool-size="10"/> <task:scheduler id="scheduler" pool-size="10"/>
    <task:annotation-driven scheduler="scheduler" executor="executor" proxy-target-class="true"/>
    
	<!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
	    <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
	    <property name="driverClassName" value="${jdbc.driver}" />
	    
		<!-- 基本属性 url、user、password -->
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		
		<!-- 配置初始化大小、最小、最大 -->
		<property name="initialSize" value="${jdbc.pool.init}" />
		<property name="minIdle" value="${jdbc.pool.minIdle}" /> 
		<property name="maxActive" value="${jdbc.pool.maxActive}" />
		
		<!-- 配置获取连接等待超时的时间 -->
		<property name="maxWait" value="60000" />
		
		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
		<property name="timeBetweenEvictionRunsMillis" value="60000" />
		
		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
		<property name="minEvictableIdleTimeMillis" value="300000" />
		
		<property name="validationQuery" value="${jdbc.testSql}" />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="false" />
		<property name="testOnReturn" value="false" />
		
		<!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
		<property name="poolPreparedStatements" value="true" />
		<property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->
		
		<!-- 配置监控统计拦截的filters -->
	    <property name="filters" value="stat" /> 
	</bean>
	
	<!-- 数据源配置, 使用应用服务器的数据库连接池 
	<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/jeesite" />-->

	<!-- 数据源配置, 不使用连接池 
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>-->
	
</beans>

和spring-mvc.xml具有相似之处

通过全局搜索发现只有一个测试类加载了该配置文件

package com.thinkgem.jeesite.common.test;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;

/**
 * Spring 单元测试基类
 * @author ThinkGem
 * @version 2013-05-15
 */
@ActiveProfiles("production")
@ContextConfiguration(locations = {"/spring-context.xml"})
public class SpringTransactionalContextTests extends AbstractTransactionalJUnit4SpringContextTests {

	protected DataSource dataSource;

	@Autowired
	public void setDataSource(DataSource dataSource) {
		super.setDataSource(dataSource);
		this.dataSource = dataSource;
	}
	
}

先不看了

resources/jeesite.properties

代码片段

#============================#
#===== Database sttings =====#
#============================#

#oracle database settings
#jdbc.type=oracle
#jdbc.driver=oracle.jdbc.driver.OracleDriver
#jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
#jdbc.username=jeesite
#jdbc.password=123456

#mysql database setting
jdbc.type=mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jeesite?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

#mssql database settings
#jdbc.type=mssql
#jdbc.driver=net.sourceforge.jtds.jdbc.Driver
#jdbc.url=jdbc:jtds:sqlserver://localhost:1433/jeesite
#jdbc.username=sa
#jdbc.password=sa

#pool settings
jdbc.pool.init=1
jdbc.pool.minIdle=3
jdbc.pool.maxActive=20

#jdbc.testSql=SELECT 'x'
jdbc.testSql=SELECT 'x' FROM DUAL

#redis settings
redis.keyPrefix=jeesite
redis.host=127.0.0.1
redis.port=6379

#============================#
#===== System settings ======#
#============================#

#\u4ea7\u54c1\u4fe1\u606f\u8bbe\u7f6e
productName=JeeSite \u5feb\u901f\u5f00\u53d1\u5e73\u53f0
copyrightYear=2016
version=V1.2.7

#\u6f14\u793a\u6a21\u5f0f: \u4e0d\u80fd\u64cd\u4f5c\u548c\u4fdd\u5b58\u7684\u6a21\u5757\uff1a sys: area/office/user/role/menu/dict, cms: site/category
demoMode=false

#\u7ba1\u7406\u57fa\u7840\u8def\u5f84, \u9700\u540c\u6b65\u4fee\u6539\uff1aweb.xml
adminPath=/a

#\u524d\u7aef\u57fa\u7840\u8def\u5f84
frontPath=/f

#\u7f51\u7ad9URL\u540e\u7f00
urlSuffix=.html

#\u662f\u5426\u4e0d\u5141\u8bb8\u5237\u65b0\u4e3b\u9875\uff0c\u4e0d\u5141\u8bb8\u60c5\u51b5\u4e0b\uff0c\u5237\u65b0\u4e3b\u9875\u4f1a\u5bfc\u81f4\u91cd\u65b0\u767b\u5f55
notAllowRefreshIndex=false

#\u662f\u5426\u5141\u8bb8\u591a\u8d26\u53f7\u540c\u65f6\u767b\u5f55
user.multiAccountLogin=true

#\u5206\u9875\u914d\u7f6e
page.pageSize=30

#\u7855\u6b63\u7ec4\u4ef6\u662f\u5426\u4f7f\u7528\u7f13\u5b58
supcan.useCache=false

#\u901a\u77e5\u95f4\u9694\u65f6\u95f4\u8bbe\u7f6e, \u5355\u4f4d\uff1a\u6beb\u79d2, 30s=30000ms, 60s=60000ms
oa.notify.remind.interval=60000

#============================#
#==== Framework settings ====#
#============================#

#\u4f1a\u8bdd\u8d85\u65f6\uff0c \u5355\u4f4d\uff1a\u6beb\u79d2\uff0c 20m=1200000ms, 30m=1800000ms, 60m=3600000ms
session.sessionTimeout=1800000
#\u4f1a\u8bdd\u6e05\u7406\u95f4\u9694\u65f6\u95f4\uff0c \u5355\u4f4d\uff1a\u6beb\u79d2\uff0c2m=120000ms\u3002
session.sessionTimeoutClean=120000

#\u7f13\u5b58\u8bbe\u7f6e
ehcache.configFile=cache/ehcache-local.xml
#ehcache.configFile=cache/ehcache-rmi.xml

#\u7d22\u5f15\u9875\u8def\u5f84
web.view.index=/a

#\u89c6\u56fe\u6587\u4ef6\u5b58\u653e\u8def\u5f84
web.view.prefix=/WEB-INF/views/
web.view.suffix=.jsp

#\u6700\u5927\u6587\u4ef6\u4e0a\u4f20\u9650\u5236\uff0c\u5355\u4f4d\u5b57\u8282. 10M=10*1024*1024(B)=10485760 bytes\uff0c\u9700\u540c\u6b65\u4fee\u6539\uff1ackfinder.xml
web.maxUploadSize=10485760

#\u65e5\u5fd7\u62e6\u622a\u8bbe\u7f6e\uff0c\u6392\u9664\u7684URI\uff1b\u5305\u542b @RequestMapping\u6ce8\u89e3\u7684value\u3002\uff08\u5df2\u4f5c\u5e9f\uff09
#web.logInterceptExcludeUri=/, /login, /sys/menu/tree, /sys/menu/treeData, /oa/oaNotify/self/count
#web.logInterceptIncludeRequestMapping=save, delete, import, updateSort

#\u9759\u6001\u6587\u4ef6\u540e\u7f00
web.staticFile=.css,.js,.png,.jpg,.gif,.jpeg,.bmp,.ico,.swf,.psd,.htc,.htm,.html,.crx,.xpi,.exe,.ipa,.apk

#\u5355\u70b9\u767b\u5f55CAS\u8bbe\u7f6e
cas.server.url=http://127.0.0.1:8180/cas
cas.project.url=http://127.0.0.1:8080/jeesite

#\u5de5\u4f5c\u6d41\u8bbe\u7f6e
activiti.isSynActivitiIndetity=false
activiti.export.diagram.path=c:/activiti_diagram
#activiti font (windows font: \u5b8b\u4f53  linux font: simsun)
activiti.diagram.activityFontName=\u5b8b\u4f53
activiti.diagram.labelFontName=\u5b8b\u4f53
#5.21.0 \u65b0\u589e\u53c2\u6570 ,2016.06.23 \u8f66\u6811\u708e add
activiti.diagram.annotationFontName=\u5b8b\u4f53
#activiti\u5916\u90e8\u8868\u5355\u6839\u5730\u5740\u914d\u7f6e
activiti.form.server.url=

#\u4e0a\u4f20\u6587\u4ef6\u7edd\u5bf9\u8def\u5f84, \u8def\u5f84\u4e2d\u4e0d\u5141\u8bb8\u5305\u542b\u201cuserfiles\u201d
#userfiles.basedir=D:/jeesite

#\u5de5\u7a0b\u8def\u5f84\uff0c\u5728\u4ee3\u7801\u751f\u6210\u65f6\u83b7\u53d6\u4e0d\u5230\u5de5\u7a0b\u8def\u5f84\u65f6\uff0c\u53ef\u518d\u6b64\u6307\u5b9a\u7edd\u5bf9\u8def\u5f84\u3002
#projectPath=D\:\\workspace\\jeesite

上述代码中定义了一些参数的值,加载后可供其它配置文件使用

如何加载?

<!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:jeesite.properties" />

如何使用?

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="prefix" value="${web.view.prefix}"/>
   <property name="suffix" value="${web.view.suffix}"/>
</bean>
posted @ 2022-06-06 10:07  EA2218764AB  阅读(309)  评论(0编辑  收藏  举报