免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1900 | 回复: 0
打印 上一主题 下一主题

springMVC整合memcached,以注解形式使用 [复制链接]

论坛徽章:
43
15-16赛季CBA联赛之上海
日期:2020-11-04 09:36:5515-16赛季CBA联赛之北控
日期:2018-10-29 18:20:3415-16赛季CBA联赛之北京
日期:2018-10-06 21:39:5715-16赛季CBA联赛之天津
日期:2018-08-09 10:30:41ChinaUnix元老
日期:2018-08-03 17:26:00黑曼巴
日期:2018-07-13 09:53:5415-16赛季CBA联赛之吉林
日期:2018-03-30 12:58:4315-16赛季CBA联赛之佛山
日期:2017-12-01 10:26:3815-16赛季CBA联赛之上海
日期:2017-11-14 09:20:5015-16赛季CBA联赛之江苏
日期:2019-02-20 09:53:3319周年集字徽章-庆
日期:2019-08-27 13:23:2515-16赛季CBA联赛之广夏
日期:2019-09-03 18:29:06
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-08-01 13:59 |只看该作者 |倒序浏览
下载win的安装包,貌似没有64位的安装包,反正我是没找到。下载地址:http://pan.baidu.com/s/1kTC99kj
首先定位到安装文件的解压目录,win7按住shift选择打开此处cmd也可以。
输入安装命令  memcached -d install  瞬间完成安装……
然后启动它:
  手动启动:winKey+R键,输入services.msc,找到memcached启动它。
  或者命令行启动:memcached -d start
  停止服务:memcached -d stop
  telnet 127.0.0.1 11211(默认的端口) ,输入stats,出现信息则表示ok!
java如果想要与memcached联合使用的话,需要使用memcached的客户端,这是网友们的叫法。其实就是jar包。这些jar包帮我们封装好了一些方法,避免我们自己再去实现复杂的操作了。
目前我看到有三个客户端:
java_memcached-release     --->:danga的,我也不知道这是什么组织……,但这个客户端比较老牌的了。
alisoft-xplatform-asf-cache  --->:阿里的
XMemcached                      --->schina上看到的,貌似是纯国产啊,应用的还是挺广泛的~
  jar包下载地址:http://pan.baidu.com/s/1sjLQO8l
我做的示例整合的是 java_memcached-release 这个版本的
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlnssi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SpringMVC-Memcached</display-name>

  <!-- 引入 spring -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:/applicationContext*.xml</param-value>
  </context-param>
  
  <!-- 引入 springMVC -->
  <servlet>
      <servlet-name>springMVC</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath*:/spring-servlet-config.xml</param-value>
      </init-param>
  </servlet>  
  <servlet-mapping>
      <servlet-name>springMVC</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
  
  <!-- 编码 UTF-8 -->
  <filter>
      <filter-name>SpringMVC-Memcached-Encoding</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>
  <filter-mapping>
      <filter-name>SpringMVC-Memcached-Encoding</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  
</web-app>
View Code

src目录下新建 applicationContext.xml 配置文件
如果你需要把mybatis整合尽量的话,在此配置文件下增加数据源、事务管理等等

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlnssi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
    http://www.springframework.org/schema/context   
    http://www.springframework.org/s ... ing-context-3.1.xsd  
    http://www.springframework.org/schema/aop   
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <!-- 引入memcached配置文件 -->
    <import resource="spring-memcached.xml"/>
   
</beans>
View Code

src目录下新建 spring-memcached.xml 配置文件,该配置文件定义memcached的各种配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlnssi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
    http://www.springframework.org/schema/context   
    http://www.springframework.org/s ... ing-context-3.1.xsd  
    http://www.springframework.org/schema/aop   
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
   
   
    <!-- 客户端:java_memcached-release_2.6.3 -->
    <bean id="memcachedPool" class="com.danga.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" lazy-init="false" destroy-method="shutDown">
        <constructor-arg>
            <value>memcachedPool</value>
        </constructor-arg>
        <!-- 可以设置多个memcached服务器 -->
        <property name="servers">
            <list>
                <value>127.0.0.1:11211</value>
            </list>
        </property>
        <!-- 每个服务器初始连接数 -->
        <property name="initConn">
            <value>20</value>
        </property>
        <!-- 每个服务器最小连接数 -->
        <property name="minConn">
            <value>20</value>
        </property>
        <!-- 每个服务器最大连接数 -->
        <property name="maxConn">
            <value>1000</value>
        </property>
        <!-- 主线程睡眠时间 -->
        <property name="maintSleep">
            <value>30000</value>
        </property>
        <!-- TCP/Socket的参数,如果是true在写数据时不缓冲,立即发送出去参数 -->
        <property name="nagle">
            <value>false</value>
        </property>
        <!-- 连接超时/阻塞读取数据的超时间是 -->
        <property name="socketTO">
            <value>3000</value>
        </property>
    </bean>
   
    <bean id="memcachedClient" class="com.danga.MemCached.MemCachedClient" >
        <constructor-arg>
            <value>memcachedPool</value>
        </constructor-arg>
    </bean>
   
</beans>
View Code

src目录下新建 spring-servlet-config.xml 配置文件,该配置文件定义spring的各种配置信息。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlnssi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
    http://www.springframework.org/schema/context   
    http://www.springframework.org/s ... ing-context-3.1.xsd  
    http://www.springframework.org/schema/mvc  
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">  
   
    <!-- 使用@Controllers前配置 -->
    <mvc:annotation-driven />            
   
    <!-- 容器加载时 自动扫描所有注解 -->
    <context:component-scan base-package="com.test" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />
    </context:component-scan>     
     
     <!-- 配置静态资源  -->   
    <mvc:resources mapping="/js/**" location="/js/" />  
    <mvc:resources mapping="/image/**" location="/image/" />
    <mvc:resources mapping="/css/**" location="/css/" />     
   
      <!-- 使用jsp作为视图 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass">
            <value>org.springframework.web.servlet.view.JstlView</value>
        </property>
        <!-- 目标路径返回到pages下 使用jsp作为视图 -->
        <property name="prefix" value="/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>   
   
    <!-- 异常处理 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">   
        <property name="exceptionMappings">   
            <props>   
                <prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>   
            </props>   
        </property>   
    </bean>   

</beans>
View Code

新建包 com.test.utils  ,新建 MemcachedUtils.java
备注:MemcachedUtils.java是一个工具类,里面封装了一些memcached的方法,这些方法都是基于 java_memcached-release.jar进行包装的, 可以方便我们在项目中使用。
本工具类的原作者是:http://blog.csdn.net/yin_jw/article/details/32331453,我比较脸大,直接拿过来使用了~

package com.test.utils;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.Logger;

import com.danga.MemCached.MemCachedClient;

publicclass MemcachedUtils {
    privatestaticfinal Logger logger = Logger.getLogger(MemcachedUtils.class);  
    privatestatic MemCachedClient cachedClient;  
    static {  
        if (cachedClient == null)  
            cachedClient = new MemCachedClient("memcachedPool";  
    }  
  
    private MemcachedUtils() {}  
  
    /**
     * 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @return*/publicstaticboolean set(String key, Object value) {  
        return setExp(key, value, null);  
    }  
  
    /**
     * 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/publicstaticboolean set(String key, Object value, Date expire) {  
        return setExp(key, value, expire);  
    }  
  
    /**
     * 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/privatestaticboolean setExp(String key, Object value, Date expire) {  
        boolean flag = false;  
        try {  
            flag = cachedClient.set(key, value, expire);  
        } catch (Exception e) {  
            // 记录Memcached日志  
            MemcachedLog.writeLog("Memcached set方法报错,key值:" + key + "\r\n" + exceptionWrite(e));  
        }  
        return flag;  
    }  
  
    /**
     * 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @return*/publicstaticboolean add(String key, Object value) {  
        return addExp(key, value, null);  
    }  
  
    /**
     * 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/publicstaticboolean add(String key, Object value, Date expire) {  
        return addExp(key, value, expire);  
    }  
  
    /**
     * 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/privatestaticboolean addExp(String key, Object value, Date expire) {  
        boolean flag = false;  
        try {  
            flag = cachedClient.add(key, value, expire);  
        } catch (Exception e) {  
            // 记录Memcached日志  
            MemcachedLog.writeLog("Memcached add方法报错,key值:" + key + "\r\n" + exceptionWrite(e));  
        }  
        return flag;  
    }  
  
    /**
     * 仅当键已经存在时,replace 命令才会替换缓存中的键。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @return*/publicstaticboolean replace(String key, Object value) {  
        return replaceExp(key, value, null);  
    }  
  
    /**
     * 仅当键已经存在时,replace 命令才会替换缓存中的键。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/publicstaticboolean replace(String key, Object value, Date expire) {  
        return replaceExp(key, value, expire);  
    }  
  
    /**
     * 仅当键已经存在时,replace 命令才会替换缓存中的键。
     *  
     * @param key
     *            键
     * @param value
     *            值
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/privatestaticboolean replaceExp(String key, Object value, Date expire) {  
        boolean flag = false;  
        try {  
            flag = cachedClient.replace(key, value, expire);  
        } catch (Exception e) {  
            MemcachedLog.writeLog("Memcached replace方法报错,key值:" + key + "\r\n" + exceptionWrite(e));  
        }  
        return flag;  
    }  
  
    /**
     * get 命令用于检索与之前添加的键值对相关的值。
     *  
     * @param key
     *            键
     * @return*/publicstatic Object get(String key) {  
        Object obj = null;  
        try {  
            obj = cachedClient.get(key);  
        } catch (Exception e) {  
            MemcachedLog.writeLog("Memcached get方法报错,key值:" + key + "\r\n" + exceptionWrite(e));  
        }  
        return obj;  
    }  
  
    /**
     * 删除 memcached 中的任何现有值。
     *  
     * @param key
     *            键
     * @return*/publicstaticboolean delete(String key) {  
        return deleteExp(key, null);  
    }  
  
    /**
     * 删除 memcached 中的任何现有值。
     *  
     * @param key
     *            键
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/publicstaticboolean delete(String key, Date expire) {  
        return deleteExp(key, expire);  
    }  
  
    /**
     * 删除 memcached 中的任何现有值。
     *  
     * @param key
     *            键
     * @param expire
     *            过期时间 New Date(1000*10):十秒后过期
     * @return*/privatestaticboolean deleteExp(String key, Date expire) {  
        boolean flag = false;  
        try {  
            flag = cachedClient.delete(key, expire);  
        } catch (Exception e) {  
            MemcachedLog.writeLog("Memcached delete方法报错,key值:" + key + "\r\n" + exceptionWrite(e));  
        }  
        return flag;  
    }  
  
    /**
     * 清理缓存中的所有键/值对
     *  
     * @return*/publicstaticboolean flashAll() {  
        boolean flag = false;  
        try {  
            flag = cachedClient.flushAll();  
        } catch (Exception e) {  
            MemcachedLog.writeLog("Memcached flashAll方法报错\r\n" + exceptionWrite(e));  
        }  
        return flag;  
    }  
  
    /**
     * 返回异常栈信息,String类型
     *  
     * @param e
     * @return*/privatestatic String exceptionWrite(Exception e) {  
        StringWriter sw = new StringWriter();  
        PrintWriter pw = new PrintWriter(sw);  
        e.printStackTrace(pw);  
        pw.flush();  
        return sw.toString();  
    }  
  
    /**
     *  
     * @ClassName: MemcachedLog
     * @Description: Memcached日志记录
     * @author yinjw
     * @date 2014-6-18 下午5:01:37
     *  
     */privatestaticclass MemcachedLog {  
        privatefinalstatic String MEMCACHED_LOG = "D:\\memcached.log";  
        privatefinalstatic String LINUX_MEMCACHED_LOG = "/usr/local/logs/memcached.log";  
        privatestatic FileWriter fileWriter;  
        privatestatic BufferedWriter logWrite;  
        // 获取PID,可以找到对应的JVM进程  privatefinalstatic RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();  
        privatefinalstatic String PID = runtime.getName();  
  
        /**
         * 初始化写入流
         */static {  
            try {  
                String osName = System.getProperty("os.name";  
                if (osName.indexOf("Windows" == -1) {  
                    fileWriter = new FileWriter(MEMCACHED_LOG, true);  
                } else {  
                    fileWriter = new FileWriter(LINUX_MEMCACHED_LOG, true);  
                }  
                logWrite = new BufferedWriter(fileWriter);  
            } catch (IOException e) {  
                logger.error("memcached 日志初始化失败", e);  
                closeLogStream();  
            }  
        }  
  
        /**
         * 写入日志信息
         *  
         * @param content
         *            日志内容
         */publicstaticvoid writeLog(String content) {  
            try {  
                logWrite.write("[" + PID + "] " + "- [" + new SimpleDateFormat("yyyy年-MM月-dd日 hh时:mm分:ss秒".format(new Date().getTime()) + "]\r\n"  
                        + content);  
                logWrite.newLine();  
                logWrite.flush();  
            } catch (IOException e) {  
                logger.error("memcached 写入日志信息失败", e);  
            }  
        }  
  
        /**
         * 关闭流
         */privatestaticvoid closeLogStream() {  
            try {  
                fileWriter.close();  
                logWrite.close();  
            } catch (IOException e) {  
                logger.error("memcached 日志对象关闭失败", e);  
            }  
        }  
    }  
}
View Code

测试部分,新建一个index.jsp、Login.java

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery/jquery-1.8.0.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
    <div><font color="red" size="10px">${returnMsg}</font></div>
    <form action="${pageContext.request.contextPath }/loginController/login" method="post" name="loginForm" id="loginForm">
        <div>
            用户名:<input class="username" type="text" id="username" name="username"  value=''/>
        </div>
        <div >
            密码:<input class="password" type="password" id="password" name="password" value=""/>
        </div>
        <div><input type="button" value="submit" onclick="login()" /></div>
    </form>
<script type="text/javascript">
   
    function login(){
        var username = $("#username".val();
        var password = $("#password".val();
        $("#loginForm".submit();
    }

    document.onkeydown=function(event){
        e = event ? event window.event ? window.event : null);
        if(e.keyCode==13){
            login();
        }
    }
   
</script>
</body>
</html>
View Code

package com.test.web;

import java.util.Date;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.test.utils.MemcachedUtils;

@Controller
@RequestMapping("/loginController"
publicclass Login {
   
    @RequestMapping("/login"
    public ModelAndView login(
            @RequestParam(value = "username" String userid,
            @RequestParam(value = "password") String passwd, HttpSession session){
        
        ModelAndView m = new ModelAndView();
        m.setViewName("../index");
        
        MemcachedUtils.set("wasd", "12ab",new Date(1000 * 60));
        Object ss = MemcachedUtils.get("wasd");
        
        System.out.println(ss.toString());
        m.addObject("returnMsg","好的!");
        return m;
    }
   
}
View Code
基本就是这样了,在整合的时候遇到一个问题  [ERROR] attempting to get SockIO from uninitialized pool!
原因是:spring-memcached.xml中的 memcachedPool 的名字要和MemcachedUtils.java中new MemCachedClient("memcachedPool"); 的名字对应起来。

具体原因已经有人分析了:http://blog.csdn.net/maerdym/article/details/10297993,我直接引用原作者的。

Memecached JavaClient在使用前需初始化SockIOPool,该类只有一个protected的构造方法,因此外部需使用其提供的静态方法getInstance来获取SockIOPool实例,getInstance方法允许传入poolname来指明SockIOPool名称. SockIOPool本身只是作为SchoonerSockIOPool的代理类,SchoonerSockIOPool内维护了一个连接池Map,其中poolname作为key,Pool实例作为值.因此在使用Spring整合Memcacheds时,如果在Spring配置文件中指明了poolname,则在初始化MemecachedClient时,需要在其构造函数中指明poolname.,如果没有声明poolname,则MemechachedClient则或获取名为default的Pool实例.

如以下配置,必须在实例化MemechacedClient时传入poolname.否则将无法进行数据操作或数据操作无效。

Spring配置文件,该配置文件声明了SockIOPool,由于该类的构造方法为protected类型,无法直接访问,因此需要使用工厂方法getInstance()来获取其实例,注:此处的<constructor-arg>标签不是作为构造函数的参数,而是作为工厂方法getInstance()的参数,即指明poolname为memcache

    <bean id="memcache" class="com.whalin.MemCached.SockIOPool" factory-method="getInstance" init-method="initialize" destroy-method="shutDown">  
        <constructor-arg>  
            <value>memcache</value>  
        </constructor-arg></span></strong></em></span>  
        <property name="servers">  
            <list>  
                <value>${memcache.server}</value>  
            </list>  
        </property>  
        <property name="initConn">  
            <value>${memcache.initConn}</value>  
        </property>  
        <property name="minConn">  
            <value>${memcache.minConn}</value>  
        </property>  
        <property name="maxConn">  
            <value>${memcache.maxConn}</value>  
        </property>  
        <property name="maintSleep">  
            <value>${memcache.maintSleep}</value>  
        </property>  
        <property name="nagle">  
            <value>${memcache.nagle}</value>  
        </property>  
        <property name="socketTO">  
            <value>${memcache.socketTO}</value>  
        </property>  
    </bean>  
在使用memcachedClient访问memchached时,需指明poolname为memcache(默认为default,但配置文件中没有对default进行配置)
        MemCachedClient memCachedClient = new MemCachedClient("memcache");  
        memCachedClient.set("name", "simple");  
        System.out.println(memCachedClient.get("name"));  
此处实例化MemCachedClient时,必须传入参数‘memcache’类指明pool实例名称,否则在插入的时候不报错,但读取的值始终为null
View Code

文中我搭建的工程放到了网盘上,需要的请移步下载哈:http://pan.baidu.com/s/1nthx0ff
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP