8.ServletConfig对象和ServletContext对象(我的JavaEE笔记)

一、servletConfig对象

在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。比如:

<servlet>
    <servlet-name>ConfigDemo1</servlet-name>
    <servlet-class>cn.itcast.servletConfig.ConfigDemo1    </servlet-class>
    <init-param>
    <param-name>xxx</param-name>
    <param-value>123</param-value>
    </init-param>
</servlet>

注意:针对每个servlet,我们需要为其单独配置,而在servlet元素外面使用标签<context-param>配置的初始化信息是对所有的servlet共享的。

现在我们在servlet中使用初始化信息(工程ConfigAndContext)

packagecn.itcast.servletConfig;
importjava.io.IOException;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class ConfigDemo1 extends HttpServlet{
    private ServletConfig config;
    public void init(ServletConfig config)throws ServletException{
    String value=config.getInitParameter("xxx");
    System.out.println(value);
}
    public void doGet(HttpServletRequestrequest, HttpServletResponseresponse)
        throws ServletException,IOException{
    }
public void doPost(HttpServletRequestrequest, HttpServletResponseresponse)
        throws ServletException,IOException{
        doGet(request,response);
    }
}

当我们使用地址 http://localhost:8080/ConfigAndContext/servlet/ConfigDemo1 访问时在窗口中会打印出123这个初始化信息。我们也可以在doGet方法中使用:

package cn.itcast.servletConfig;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigDemo1 extends HttpServlet {
    private ServletConfig config;
    public void init(ServletConfig config) throws ServletException{
        //在初始化方法中使用
        /*String value = config.getInitParameter("xxx");
        System.out.println(value);*/
        this.config = config;//在doGet方法中使用
    }
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //得到初始化参数
        String value = config.getInitParameter("xxx");
        //会将得到的初始化参数打印在网页中,注意输出方式
        response.getOutputStream().write(value.getBytes());
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

当然我们也可以配置多个初始化参数,并通过名字得到相关的值:

package cn.itcast.servletConfig;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigDemo1 extends HttpServlet {
    
    private ServletConfig config;
    public void init(ServletConfig config) throws ServletException{
        //在初始化方法中使用
        /*String value = config.getInitParameter("xxx");
        System.out.println(value);*/
        this.config = config;//在doGet方法中使用
    }
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //得到初始化参数
        String value = config.getInitParameter("xxx");
        //会将得到的初始化参数打印在网页中,注意输出方式
        response.getOutputStream().write(value.getBytes());
        
        //得到多个初始化参数
        Enumeration e = config.getInitParameterNames();
        while(e.hasMoreElements()){
            String name = (String) e.nextElement();
            value = config.getInitParameter(name);
            response.getOutputStream().write((name + "=" + value).getBytes());
        }
        
        //得到码表
        String charset = this.config.getInitParameter("charset");
        //得到链接数据库
        String url = this.config.getInitParameter("url");
        String username = this.config.getInitParameter("username");
        String password = this.config.getInitParameter("password");

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }
}

其配置信息如下:

<servlet>
<servlet-name>ConfigDemo1</servlet-name>
<servlet-class>cn.itcast.servletConfig.ConfigDemo1</servlet-class>

<init-param>
<param-name>xxx</param-name>
<param-value>yyy</param-value>
</init-param>

<init-param><!--配置码表-->
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--配置数据库-->
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://3305/test</param-value>
</init-param>
<init-param><!--配置用户名-->
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param><!--配置密码-->
<param-name>password</param-name>
<param-value>walp1314</param-value>
</init-param>
</servlet>

当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象就可以得到当前servlet的初始化参数信息。也就是说我们不需要自己定义一个ServletConfig字段,直接使用即可。

package cn.itcast.servletConfig;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigDemo2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //我们直接得到ServletConfig对象
        ServletConfig config = this.getServletConfig();
        System.out.println("aaa" + config.getInitParameter("xx"));
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

二、ServletContext对象(context域对象)

(1)ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
(2)由于一个web应用中的所有servlet共享同一个ServletContext对象,因此servlet对象之间可以通过ServletContext对象来实现通讯,ServletContext对象通常也被称之为context域对象
我们先将数据通过servlet存入context域对象中:

package cn.itcast.context;
//多个servlet通过servletContext实现数据共享
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//将数据存到context对象之中
public class ContextDemo1 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String data = "aaa";
        ServletContext context = this.getServletConfig().getServletContext();
        context.setAttribute("data", data);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

然后从context域中取出我们存入的数据:

package cn.itcast.servletConfig;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ConfigDemo2 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //我们直接得到ServletConfig对象
        ServletConfig config = this.getServletConfig();
        System.out.println("aaa" + config.getInitParameter("xx"));
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

web容器在启动时,它会为每个web应用程序都创建一个对应的ServletContext对象,它代表当前的web应用。即ServletContext对象可以对整个web应用中所有的servlet使用,同时一般不在其中一个<servlet>标签中定义,而是在外部定义。如:

<web-app>
<context-param>
<param-name>1111</param-name>
<param-value>2222</param-value>
</context-param>
。。。。。。

这里我们通过context对象获得整个站点的初始化资源:

package cn.itcast.context;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ContextDemo3 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //注意:这里我们其实可以直接取得context对象,而不需要通过ServletConfig对象
        ServletContext context = this.getServletContext();
        String name = context.getInitParameter("1111");
        System.out.println(name);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

实现servlet之间的转发

我们访问ContextDemo4这个servlet,然后这个servlet将请求转发给ContextDemo5进行处理:

package cn.itcast.context;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ContextDemo4 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.注意:字符串是不会在浏览器中输出的,因为我们在转发后,ContextDemo5这个
        //servlet会将response中的数据全部清掉
        response.getOutputStream().write("1111".getBytes());
        
        //2.这种情况我们强制关闭流会自动清理缓存,也就是说会将字符串输出到浏览器中
        //但是此时转发请求会出错,因为流已经关闭了.
        OutputStream out = response.getOutputStream();
        out.write("1111".getBytes());
        out.close();
        
        ServletContext context = this.getServletContext();
        RequestDispatcher rd = context.getRequestDispatcher("/servlet/ContextDemo5");
        rd.forward(request, response);
        
        //3.这行代码是会执行的,会在窗口打印出字符串
        System.out.println("Hello");
        
        //4.这行代码虽然会执行,但是不会发到浏览器中,因为此时在请求转发之后相当于
        //整个操作已经结束了,数据就不会发送到浏览器中了。
        response.getOutputStream().write("Hello".getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

注意上面四种特殊情况。

ContextDemo5进行处理转发的请求:

package cn.itcast.context;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ContextDemo5 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getOutputStream().write("ContextDemo5".getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

在web工程中我们用到资源文件时一般就是.xml文件或者.properties文件,一般较为复杂的资源文件使用.xml,简单文件使用.properties文件。

资源文件(db1.properties)

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3305/test
username=root
password=walp1314

下面看操作资源文件:

package cn.itcast.context;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ContextDemo6 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try{
            test1();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
    //使用传统方式读取资源文件
    public void test1() throws Exception{
        FileInputStream fin = new FileInputStream("db1.properties");
        System.out.println(fin);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

注意:这里的test1方法中我们采用传统的方式去读取资源文件。但是如果这样读取资源文件我们将资源文件放在工程中的任何目录都是访问不了的,因为这个程序是右tomcat去调用java虚拟机执行,所以我们如果将资源文件放在工程中,那么路径就要写这个资源文件路径(如果是在src下,那么路径就是classes)相对于tomcat的bin目录的地址。这显然很麻烦,当然我们也可以将资源文件直接放在tomcat的bin目录中,此时直接写上文件名即可,但是这在实际开发中显然是行不通的。

方式二:使用ServletContext对象读取资源文件(1)

//使用ServletContext对象读取资源文件(1)
    public void test2() throws Exception{
        //此时我们将配置文件放在src下,部署之后此文件在/WEB-INF/classes下。
        InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db1.properties");
        
        //读取properties文件需要使用Properties对象
        Properties properties = new Properties();
        properties.load(in);
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        
        System.out.println(driver);
    }

方式三:使用ServletContext对象读取资源文件(2)

//使用ServletContext对象读取资源文件(2)
    public void test3() throws IOException{
        //这里我们得到资源文件的绝对路径,此时资源文件放在src下
        String path = this.getServletContext().getRealPath("/WEB-INF/classes/db1.properties");
        
        //之后就可以采用传统方式进行读取
        FileInputStream fin = new FileInputStream(path);
        
        Properties properties = new Properties();
        properties.load(fin);
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        
        System.out.println(driver);
        
    }

方式四:读取WebRoot目录下的资源文件


    //读取WebRoot目录下的资源文件
    public void test4() throws IOException{
        //注意此时资源文件是在webRoot下的,也就是在web工程下面,可以直接读取
        InputStream in = this.getServletContext().getResourceAsStream("/db2.properties");
        Properties properties = new Properties();
        properties.load(in);
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        
        System.out.println(driver);
    }

下面看使用类装载器读取资源文件(一定要注意:虽然都放在src目录下,但是路径写法不同)

package cn.itcast.context;
//使用类装载器读取资源文件
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ContextDemo7 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try{
            test1();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    
    public void test1() throws IOException{
        ClassLoader loader = ContextDemo7.class.getClassLoader();
        
        //注意:这里的资源文件也是放在src目录下面,但是和之前的写法却不同
        InputStream in = loader.getResourceAsStream("db1.properties");
        //说明:这个类装载器装载src下的class文件,当然也可以装载资源文件,而资源文件刚好
        //在src下,所有资源文件和类装载器在同一个目录中
        Properties properties = new Properties();
        properties.load(in);
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        
        System.out.println(driver);
    }
    
    //读取类路径下(包下)的资源文件
    public void test2() throws IOException{
        ClassLoader loader = ContextDemo7.class.getClassLoader();
        
        InputStream in = loader.getResourceAsStream("cn/itcast/context/db1.properties");
        
        Properties properties = new Properties();
        properties.load(in);
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        
        System.out.println(driver);
    }
    
    //但是通过类装载器读取资源文件在资源文件很大的时候容易造成虚拟机内存溢出
    //所以使用类装载器的方式不适合读取较大的资源文件
    //下面读取较大的资源文件
    public void test3() throws IOException{
        //读取db.mp4并拷贝到E:\根目录下
        //path路径有两种情况:1.path=C:\aaa\bbb\db.mp4; 2.path=db.mp4
        String path = this.getServletContext().getRealPath("WEB-INF/classes/db.mp4");
        
        //资源文件放在src下,这里我们是需要从路径中截取出文件名
        String filename = path.substring(path.lastIndexOf("\\") + 1);
        //这里表示从最后一个\的后面一个字符开始截取
        
        InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.mp4");
        byte buffer[] = new byte[1024];//开辟一个缓冲区
        int len = 0;
        FileOutputStream out = new FileOutputStream("e:\\" + filename);
        while((len = in.read(buffer)) > 0){
            out.write(buffer, 0, len);
        }
        out.close();
        in.close();
        
    }
    

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

普通java类通过servlet读取资源文件

package cn.itcast.dao;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
//在普通java类中取得(或写入)资源文件中的相关数据只能功过类装载器来实现
public class Dao {
    public void run() throws IOException{
        //这里资源文件在src下,注意:这里不能使用getResourceAsStream方法,原因在后面说明
        URL url_s = Dao.class.getClassLoader().getResource("db1.properties");
        //结果是file:/E:/apache/tomcat/tomcat/webapps/ConfigAndContext/WEB-INF/classes/db1.properties
        //System.out.println(url_s);
        //得到资源的绝对路径
        String path = url_s.getPath();
        //结果是/E:/apache/tomcat/tomcat/webapps/ConfigAndContext/WEB-INF/classes/db1.properties
        //System.out.println(path);
        FileInputStream in = new FileInputStream(path);
        //注意:new一个FileOutputStream时如果不设置布尔值就会将文件清空
        FileOutputStream out = new FileOutputStream(path, true);
        
        Properties properties = new Properties();
        properties.load(in);
        System.out.println(properties.getProperty("driver"));
        System.out.println(properties.getProperty("url"));
        System.out.println(properties.getProperty("username"));
        System.out.println(properties.getProperty("password"));
        //第一次访问的时候值是null,第二次才会有值
        System.out.println(properties.getProperty("name"));
        properties.setProperty("name", "yj");
        //将相关内容写入到文件中去
        properties.store(out, "");
    }
}
package cn.itcast.context;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.dao.Dao;
public class ContextDemo8 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        Dao dao = new Dao();
        dao.run();
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

说明:这里之所以不使用getResourceAsStream方法是因为如果这样那么第一次访问时类装载器就会将资源文件加载进去,但是如果我们想程序后面那样对文件进行写入操作后,之后的访问还是不会得到相关的值,和上面不同,上面只是第一次没有值,但是之后就会有值。这是因为类加载器在每次加载的时候会先看内存中是否有这个资源文件,如果有就不会再次加载,所以如果使用getResourceAsStream方法,那么我们每次访问的资源文件都是第一次加载的那个,而不会更新。除非关掉web服务器,这显然不现实。但是我们通过其路径每次都new一个输入输出流则会每次都去更新资源文件。

缓存一些不经常变化的资源到浏览器中,提升服务器性能

package cn.itcast.context;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ContextDemo9 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String data = "aaa";
        //缓存一天
        response.setDateHeader("expires", System.currentTimeMillis() + 24*3600*1000);
        response.getOutputStream().write(data.getBytes());
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }
}

注意:这里我们在试验时可以在Internet选项中常规-设置-查看文件里面可以查看到缓存的文件,同时我们不能使用刷新查看试验结果,因为只要是刷新都会想服务器请求数据,所以这里我们可以使用超链接进行试验。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,738评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,377评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,774评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,032评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,015评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,239评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,724评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,374评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,410评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,457评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,132评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,733评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,804评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,022评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,515评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,116评论 2 341

推荐阅读更多精彩内容