分享
 
 
 

Tomcat-Apache HOWTO Tomcat+Apache HOWTO

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Tomcat-Apache HOWTO

This document explains how to connect Tomcat to the popular open source web server, Apache. It was originally part of Tomcat: A Minimalistic User's Guide by Gal Shachor, but has been split off for organizational reasons. It should be considered a work in progress. Since the Tomcat source tree is constantly changing, the information herein may be out of date. The only definitive reference at this point is the source code.

Other important documents:

Tomcat User's Guide

mod_jk HOWTO [??? should be rolled into tomcat-apache howto]

Jakarta FAQ Page

Other Tomcat-Apache HOWTOs: [should be integrated into this one?]

Howto Configure Tomcat 3.1 with Apache by Freddie Mendoza

Apache Web Server / JServ / Tomcat / SSL Installation on UNIX by Jan K. Labanowski

Tomcat and JServ by Jun Inamori

http://www.dmz.hitachi-sk.co.jp/Java/Tech/servlet/tomcat.html in Japanese

Table of Contents

[write me]

Apache - Tomcat Cooperation - Sample Server Integration

Up until now we have not discussed Tomcat as a server add on, instead we have considered it as a stand-alone container and discussed how it can be used. There are however a few problems with this picture:

Tomcat is not as fast as Apache when it comes to static pages.

Tomcat is not as configurable as Apache.

Tomcat is not as robust as Apache.

There are many sites with long time investment in certain web servers, for example, sites that are using CGI scripts/Server API modules/perl/php. We cannot assume that all of them will want to ditch this legacy.

For all these reasons it is recommended that real world sites use an industrial strength web server, such as Apache, for serving the static content of the site, and use Tomcat as a Servlet/JSP add-on.

Our agenda:

Cover the fundamental behavior of the web server.

Explain what configuration is needed.

Demonstrate this on Apache.

Common Installation and Configuration Problems

This section isn't meant to be your one-stop shop for all troubles Tomcat, but a resource for stumbling blocks common to many first-time Tomcat'ers. See the help section for additional links.

http://webserver:8007/ gives a 500

This is what you should see in your tomcat.log file:

HANDLER THREAD PROBLEM: java.io.IOException: Stream broken

By default, Tomcat listens for AJP connections on port 8007. AJP is the protocol used to communicate between the web server and Tomcat, not Tomcat and your browser. To test your Tomcat installation, FIX ME ?

<Directory> and <Location> directives ignored

FIX ME Apache never applies because forwarded to Tomcat.

Web server won't start when Tomcat is running

FIX ME Port conflict.

"Bad command or filename" when executing Tomcat scripts

[FIX ME] UNIX file format on DOS. Because Tomcat is developed on *nix (rather, the jars are built and distributed there), you may have to convert the files to PC (versus UNIX) format.

Starting Tomcat From Another Directory

Setting Tomcat to Cooperate with the Apache Web Server

Web Server Operation

In a nutshell a web server is waiting for client HTTP requests. When these requests arrive the server does whatever is needed to serve the requests by providing the necessary content. Adding a servlet container may somewhat change this behavior. Now the web server needs also to perform the following:

Load the servlet container adapter library and initialize it (prior to serving requests).

When a request arrives, it needs to check and see if a certain request belongs to a servlet, if so it needs to let the adapter take the request and handle it. The adapter on the other hand needs to know what requests it is going to serve, usually based on some pattern in the request URL, and to where to direct these requests.

Things are even more complex when the user wants to set a configuration that uses virtual hosts, or when they want multiple developers to work on the same web server but on different servlet container JVMs. We will cover these two cases in the advanced sections.

What is the Needed Configuration

The most obvious configuration that one can think of is the identity of the servlet URLs that are under the responsibility of the servlet container. This is clear; someone must know what requests to transmit to the servlet container... Yet there are additional configuration items that we should provide to the web-server/servlet-container combination:

We also need to provide configuration regarding the available Tomcat processes and on which TCP/IP host/port they are listening.

We need to tell the web server the location of the adapter library (so it will be able to load it on startup).

We need to set adapter internal information such as where and how much to log, etc. All this information must appear either in the web server configuration, or in a private configuration files used by the adapter. The next section will demonstrate how configuration can be implemented on Apache.

Making it on Apache

This section shows you how to configure Apache to work with Tomcat; it tries to provide explanations as well as insight for the configuration directives that you should use. You can find additional information in the jserv install page .

When Tomcat starts up it will automatically generate a configuration file for Apache in TOMCAT_HOME/conf/jserv/tomcat-apache.conf. Most of the time you don't need to do anything but include this file (appending "Include TOMCAT_HOME/conf/jserv/tomcat-apache.conf") in your httpd.conf. If you have special needs, for example an AJP port other the 8007, you can use this file as a base for your customized configuration and save the results in another file. If you manage the Apache configuration yourself you'll need to update it whenever you add a new context.

Tomcat: you must restart tomcat and apache after adding a new context; Apache doesn't support configuration changes without a restart. Also the file TOMCAT_HOME/conf/jserv/tomcat-apache.conf is generated when tomcat starts, so you'll need to start Tomcat before Apache. Tomcat will overwrite TOMCAT_HOME/conf/tomcat-apache.conf each startup so customized configuration should be kept elsewhere.

The Apache-Tomcat configuration uses Apache core configuration directives as well as Jserv unique directives so it may confuse you at first, there are however two things simplifying it:

In general you can distinguish between the two directive "families" by noting that all the Jserv unique directives start with an "ApJServ" prefix.

The entire Tomcat related configuration is concentrated in a single configuration file named tomcat.conf, or the automatically generated tomcat-apache.conf, so you can look at a single file. Lets look now at a sample tomcat.conf file.

A Minimalistic Apache-Tomcat Configuration

###########################################################

# A minimalistic Apache-Tomcat Configuration File #

###########################################################

# Note: this file should be appended or included into your httpd.conf

# (1) Loading the jserv module that serves as Tomcat's apache adapter.

LoadModule jserv_module libexec/mod_jserv.so

# (1a) Module dependent configuration.

<IfModule mod_jserv.c>

# (2) Meaning, Apache will not try to start Tomcat.

ApJServManual on

# (2a) Meaning, secure communication is off

ApJServSecretKey DISABLED

# (2b) Meaning, when virtual hosts are used, copy the mount

# points from the base server

ApJServMountCopy on

# (2c) Log level for the jserv module.

ApJServLogLevel notice

# (3) Meaning, the default communication protocol is ajpv12

ApJServDefaultProtocol ajpv12

# (3a) Default location for the Tomcat connectors.

# Located on the same host and on port 8007

ApJServDefaultHost localhost

ApJServDefaultPort 8007

# (4)

ApJServMount /examples /root

# Full URL mount

# ApJServMount /examples ajpv12://hostname:port/root

</IfModule>

As you can see the configuration process was split into 4 steps that will now be explained:

In this step we instruct Apache to load the jserv shared-object (or the NT world dll). This is a well known Apache directive. If the loading went well and the module came from a file named mod_jserv.c (1a) we can start with the rest of the Jserv-Tomcat configuration.

This step sets various Jserv internal parameters, these parameters:

Instruct jserv not to start the Tomcat process. Automatically starting Tomcat is not implemented yet.

Disable the secret key challenge/response between Apache and Tomcat. Again, the secret key work is not implemented yet.

Instruct jserv to copy the base server mount points (see next section) in case of virtual hosting.

Instruct jserv to use the notice log level. Other log levels include emerg, alert, crit, error, warn, info and debug.

This step sets the default communication parameters. Basically it says that the default protocol used for the communication is ajpv12 (do not mess with this one) and that the Tomcat process runs on the same machine and listens on port 8007. If you run Tomcat on a machine other than the one used for Apache you should either update your ApJServDefaultHost or use a full URL when mounting contexts (see next). Also, if you configured the Tomcat connectors to use a port other then 8007, you should update your ApJServDefaultPort or use a full URL when mounting contexts.

This step mounts a context to Tomcat. Basically it says that all the web server paths that start with /examples go to Tomcat. This ApJServMount example is a rather simple one, in fact ApJServMount can also provide information regarding the communication protocol to be used and the location where the Tomcat process listens, for example:

ApJServMount /examples ajpv12://hostname:port/root

mounts the context /examples to a Tomcat process that runs on host "hostname" and listens on port number "port". Now that you understand the different configuration instructions in the sample file, how can you add it to the Apache configuration? One "simple" method is to write it's content in the httpd.conf (the Apache configuration file), this however can be very messy. Instead you should use the Apache include directive. At the end of the Apache configuration file (httpd.conf) add the following directive:

include <full path to the Tomcat configuration file>

for example:

include /tome/tomcat/conf/tomcat.conf

This will add your Tomcat configuration to Apache, after that you should copy the jserv module to the Apache libexec (or modules in the Win32 case) directory and restart (stop+start) Apache. It should now be able to connect to Tomcat.

Obtaining the Jserv Module (mod_jserv)

As previously stated, we need a web server adapter to sit in Apache and redirect requests to Tomcat. For Apache, this adapter is a slightly modified version of mod_jserv.

You may try to look here and see if there is an already pre-built version of mod_jserv that suites your OS (Usually there is one for NT), however, being a native library you should not expect that yet (too many OS's, not enough developers, life too short...). Moreover, small variations in the way you built Apache/Your specific UNIX variant may result in dynamic linking errors. You should really try to build mod_jserv for your system (don't panic, it is not that hard!).

Building mod_jserv on UNIX involves the following:

Download the source distribution of Tomcat from here.

Uncompress it into some directory.

Building the module:

Change directory into jakarta-tomcat/src/native/apache/jserv/

Execute the build command

apxs -c -o mod_jserv.so *.c

apxs is part of the Apache distribution and should be located in your APACHE_HOME/bin. Building mod_jserv for Win32 is less likely (you already have a downloadable dll for Win32). Yet if you want to build it you should install Visual C++ and perform the following:

Download the source distribution of Tomcat from here.

Unzip it into some directory.

Building the module:

Change directory into jakarta-tomcat\src\native\apache\jserv

Add Visual C++ into your environment by executing the script VCVARS32.BAT.

Execute the build command

nmake -f Makefile.win32

nmake is the Visual C++ make program. That's it; you have built mod_jserv...

Making Apache Serve your Context's Static Files

The previous Apache-Tomcat configuration file was somewhat inefficient, it instructed Apache to send any request for a resource that starts with the /examples prefix to be served by Tomcat. Do we really want that? There are many static files that may be a part of our servlet context (for example images and static HTML), why should Tomcat serve these files?

You may actually have reasons for doing that, for example:

You may want to configure Tomcat based security for these resources.

You may want to follow users requests for static resources using interceptors. In general however, this is not that case; and making Tomcat save static files is just a CPU waste. We should instead have Apache serve these static files and not Tomcat. Lets look now at a sample tomcat.conf file that does exactly that:

Having Apache serve the static files requires the following:

Instructing Apache to send all servlet requests to Tomcat.

Instructing Apache to send all JSP requests to Tomcat. and leaving Apache to handle the rest. Lets look now at a sample tomcat.conf file that does exactly that:

Apache-Tomcat Configuration where Apache Serves the Static Content

######################################################################

# Apache-Tomcat Smart Context Redirection #

######################################################################

LoadModule jserv_module modules/ApacheModuleJServ.dll

<IfModule mod_jserv.c>

ApJServManual on

ApJServDefaultProtocol ajpv12

ApJServSecretKey DISABLED

ApJServMountCopy on

ApJServLogLevel notice

ApJServDefaultHost localhost

ApJServDefaultPort 8007

#

# Mounting a single smart context:

#

# (1) Make Apache know about the context location.

Alias /examples D:\tomcat\webapps\examples

# (2) Optional, customize Apache context service.

<Directory "D:\tomcat\webapps\examples">

Options Indexes FollowSymLinks

# (2a) No directory indexing for the context root.

# Options -Indexes

# (2b) Set index.jsp to be the directory index file.

# DirectoryIndex index.jsp

</Directory>

# (3) Protect the WEB-INF directory from tampering.

<Location /examples/WEB-INF/>

AllowOverride None

deny from all

</Location>

# (4) Instructing Apache to send all the .jsp files under the context to the

# jserv servlet handler.

<LocationMatch /examples/*.jsp>

SetHandler jserv-servlet

</LocationMatch>

# (5) Direct known servlet URLs to Tomcat.

ApJServMount /examples/servlet /examples

# (6) Optional, direct servlet only contexts to Tomcat.

ApJServMount /servlet /ROOT

</IfModule>

As you can see, the beginning of this configuration file is the same as seen in the previous example. The last step (mounting a context), however, was replaced in a long series of Apache and ApJServ configuration directives that will now be explained:

This step informs Apache of the context location and aliases it to an Apache virtual directory. This way Apache can serve files from this directory.

This optional step instructs Apache more about how to serve the context; for example you can decide if Apache will allow directory indexing (listing) or set a special index file.

This step instructs Apache to protect the WEB-INF directory from client access. For security reasons it is important to prevent visitors from viewing the content of the WEB-INF directory, for example web.xml can provide valuable information for intruders. This step blocks the WEB-INF content from visitors.

This step instructs Apache to serve all the jsp locations within the context using the jserv servlet handler. The servlet handler redirects these requests based on the default host and port.

This step mounts specific servlet URLs to Tomcat. You should note that you should have as many such mount directives as the number of specific servlet URLs.

This last step is an example for the addition of servlet only context to Tomcat. It is easy to see that this configuration is much more complex and error prone then the first example, this however is the price that you should (for now) pay for improved performance.

Configuring for Multiple Tomcat JVMs

Sometimes it is useful to have different contexts handled by different JVMs, for example:

When each context serves a different, specific task and runs on a different machine.

When we want to have multiple developers work on a private Tomcat process but use the same web server. Implementing such schemes where different contexts are served by different JVMs is very easy and the following configuration file demonstrates this:

Apache-Tomcat Configuration with per Context JVM

######################################################################

# Apache-Tomcat with JVM per Context #

######################################################################

LoadModule jserv_module modules/ApacheModuleJServ.dll

<IfModule mod_jserv.c>

ApJServManual on

ApJServDefaultProtocol ajpv12

ApJServSecretKey DISABLED

ApJServMountCopy on

ApJServLogLevel notice

ApJServDefaultHost localhost

ApJServDefaultPort 8007

# Mounting the first context.

ApJServMount /joe ajpv12://joe.corp.com:8007/joe

# Mounting the second context.

ApJServMount /bill ajpv12://bill.corp.com:8007/bill

</IfModule>

As you can see in the previous example, using several JVMs (even even those that run on different machines) can be accomplished easily by using a full ajp URL mount. In this full URL we actually specify the host where the Tomcat process is located and it's port.

Had the two Tomcat processes run on the same machine, we would have to configure each of them with different connector ports. For example, assuming that the two JVMs runs on localhost, the Apache-Tomcat configuration should have something that looks like:

Same Machine Multiple JVM Apache-Tomcat Configuration

######################################################################

# Apache-Tomcat with Same Machine JVM per Context #

######################################################################

LoadModule jserv_module modules/ApacheModuleJServ.dll

<IfModule mod_jserv.c>

ApJServManual on

ApJServDefaultProtocol ajpv12

ApJServSecretKey DISABLED

ApJServMountCopy on

ApJServLogLevel notice

ApJServDefaultHost localhost

ApJServDefaultPort 8007

# Mounting the first context.

ApJServMount /joe ajpv12://localhost:8007/joe

# Mounting the second context.

ApJServMount /bill ajpv12://localhost:8009/bill

</IfModule>

Looking at the above file you can see that we have two explicit ApJServ mount points each pointing to a different port on the same machine. It is clear that this configuration requires support from the configuration found in the server.xml files. We will need in these files different <Connector> configurations, for the different Tomcat processes. We will actually need two different server.xml files (lets call them server_joe.xml and server_bill.xml) with different <Connector> entries as shown in the next two samples:

Joe's server.xml file

<?xml version="1.0" encoding="ISO-8859-1"?>

<Server>

<!-- Debug low-level events in XmlMapper startup -->

<xmlmapper:debug level="0" />

<!-- @@@

Note, the log files are suffixed with _joe to distinguish

them from the bill files.

-->

<Logger name="tc_log"

path="logs/tomcat_joe.log"

customOutput="yes" />

<Logger name="servlet_log"

path="logs/servlet_joe.log"

customOutput="yes" />

<Logger name="JASPER_LOG"

path="logs/jasper_joe.log"

verbosityLevel = "INFORMATION" />

<!-- @@@

Note, the work directory is suffixed with _joe to distinguish

it from the bill work directory.

-->

<ContextManager debug="0" workDir="work_joe" >

<!-- Context level Setup -->

<ContextInterceptor

className="org.apache.tomcat.context.AutoSetup" />

<ContextInterceptor

className="org.apache.tomcat.context.DefaultCMSetter" />

<ContextInterceptor

className="org.apache.tomcat.context.WorkDirInterceptor" />

<ContextInterceptor

className="org.apache.tomcat.context.WebXmlReader" />

<ContextInterceptor

className="org.apache.tomcat.context.LoadOnStartupInterceptor" />

<!-- Request processing -->

<RequestInterceptor

className="org.apache.tomcat.request.SimpleMapper" debug="0" />

<RequestInterceptor

className="org.apache.tomcat.request.SessionInterceptor" />

<RequestInterceptor

className="org.apache.tomcat.request.SecurityCheck" />

<RequestInterceptor

className="org.apache.tomcat.request.FixHeaders" />

<!-- @@@ This connector uses port number 8007 for it's ajp communication -->

<Connector

className="org.apache.tomcat.service.SimpleTcpConnector">

<Parameter

name="handler"

value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>

<Parameter name="port" value="8007"/>

</Connector>

<!-- @@@ the /jow context -->

<Context path="/joe" docBase="webapps/joe" debug="0" reloadable="true" >

</Context>

</ContextManager>

</Server>

When looking at server_joe.xml you can see that the <Connector> is configured for port 8007. In server_bill.xml (see next) on the other hand the <Connector> is configured for port 8009.

Bill's server.xml file

<?xml version="1.0" encoding="ISO-8859-1"?>

<Server>

<!-- Debug low-level events in XmlMapper startup -->

<xmlmapper:debug level="0" />

<!-- @@@

Note, the log files are suffixed with _bill to distinguish

them from the joe files.

-->

<Logger name="tc_log"

path="logs/tomcat_bill.log"

customOutput="yes" />

<Logger name="servlet_log"

path="logs/servlet_bill.log"

customOutput="yes" />

<Logger name="JASPER_LOG"

path="logs/jasper_bill.log"

verbosityLevel = "INFORMATION" />

<!-- @@@

Note, the work directory is suffixed with _bill to distinguish

it from the joe work directory.

-->

<ContextManager debug="0" workDir="work_bill" >

<!-- Context level Setup -->

<ContextInterceptor

className="org.apache.tomcat.context.AutoSetup" />

<ContextInterceptor

className="org.apache.tomcat.context.DefaultCMSetter" />

<ContextInterceptor

className="org.apache.tomcat.context.WorkDirInterceptor" />

<ContextInterceptor

className="org.apache.tomcat.context.WebXmlReader" />

<ContextInterceptor

className="org.apache.tomcat.context.LoadOnStartupInterceptor" />

<!-- Request processing -->

<RequestInterceptor

className="org.apache.tomcat.request.SimpleMapper" debug="0" />

<RequestInterceptor

className="org.apache.tomcat.request.SessionInterceptor" />

<RequestInterceptor

className="org.apache.tomcat.request.SecurityCheck" />

<RequestInterceptor

className="org.apache.tomcat.request.FixHeaders" />

<!-- @@@ This connector uses port number 8009 for it's ajp communication -->

<Connector className="org.apache.tomcat.service.SimpleTcpConnector">

<Parameter

name="handler"

value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>

<Parameter name="port" value="8009"/>

</Connector>

<!-- @@@ the /bill context -->

<Context path="/bill" docBase="webapps/bill" debug="0" reloadable="true" >

</Context>

</ContextManager>

</Server>

The port configuration is not the only place where the joe and bill configuration differs. We have @@@ marks in the xml files marking the four places where changes had to be made. As you can see, this difference is necessary to avoid the two Tomcat processes from overwriting each other's logs and workspace.

Then we should start the two tomcat processes using the -f command line option:

bin\starup -f conf\server_joe.xml

bin\starup -f conf\server_bill.xml

and then access them from Apache based on the different URL path prefixes.

Configuring Virtual Hosting

It is possible to support virtual hosts under Tomcat Ver3.1, in fact the virtual host configuration is very similar to configuring for multiple JVM (as explained in the previous section) and the reason is simple; in Tomcat 3.1 each virtual host is implemented by a different Tomcat process.

With the current (Ver3.1) Tomcat, virtual hosting awareness is provided by the web server (Apache/Netscape…). The web server virtual hosting support is used by the Tomcat adapter to redirect requests belonging to a certain virtual host to the JVM(s) containing the contexts of this virtual host. This means that if (for example) we have two virtual hosts (vhost1 and vhost2), we will have two JVMs: one running the contexts of vhost1 and the other running the contexts of vhost2. These JVMs are not aware of each others existence, in fact, they are not aware of the concept of virtual hosting. All the virtual hosting logic is inside the web-server adapter. To make things clearer, lets look at the following sample Apache-Tomcat configuration file:

Apache-Tomcat Configuration with Virtual Hosts Support

######################################################################

# Apache Tomcat Virtual Hosts Sample Configuration #

######################################################################

LoadModule jserv_module modules/ApacheModuleJServ.dll

<IfModule mod_jserv.c>

ApJServManual on

ApJServDefaultProtocol ajpv12

ApJServSecretKey DISABLED

ApJServMountCopy on

ApJServLogLevel notice

ApJServDefaultHost localhost

ApJServDefaultPort 8007

# 1 Creating an Apache virtual host configuration

NameVirtualHost 9.148.16.139

# 2 Mounting the first virtual host

<VirtualHost 9.148.16.139>

ServerName www.vhost1.com

ApJServMount /examples ajpv12://localhost:8007/examples

</VirtualHost>

# 3 Mounting the second virtual host

<VirtualHost 9.148.16.139>

ServerName www.vhost2.com

ApJServMount /examples ajpv12://localhost:8009/examples

</VirtualHost>

</IfModule>

As can be seen, steps 1,2 and 3 define two Apache virtual hosts and for each of them, mount the /examples context to a certain ajpv12 URL. Each such ajpv12 URL points to a JVM that contains the virtual host. The configuration of the two JVMs is very similar to the one demonstrated in the previous section, we will need again to use two different server.xml files (one for each virtual host process) and we will need to start the Tomcat processes with the -f command line option. After doing that we will be able to approach Apache, each time with a different host name, and the adapter will redirect us to the appropriate JVM.

The need for improved virtual host support

Having each virtual host implemented by a different JVM is a huge scalability problem. The next versions of Tomcat will make it possible to support several virtual hosts within the same Tomcat JVM.

CreditsThis document was created by Gal Shachor. It was split off into a separate document and revised by Alex Chaffee and Rob Slifka.

With help from (in alphabetical order):

Jonathan Bnayahu

Alex Chaffee

Fiona Czuczman

Costin Manolache

Rob Slifka

Copyright ©1999-2001 The Apache Software Foundation

Legal Stuff They Make Us Say

Contact Information

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有