




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、基于Java的Web服务器工作原理1基于Java的Web服务器工作原理1一个Web服务器也被称为HTTP服务器,它通过HTTP协议与客户端通信。这个客户端通常指的是Web浏览器。一个基于Java的Web服务器用到二个重要的类,.Socket与.ServerSocket,并通过HTTP消息通信。因此,本文从讨论HTTP与这二个类开始,然后我将解释一个与本文相关的简单的Web应用。The Hypertext Transfer Protocol(HTTP)HTTP是一种让Web服务器与浏览器(客户端)通过Internet发送与接收数据的协议。它是一个请求、响应协议-客
2、户端发出一个请求,服务器响应这个请求。HTTP运用可靠的TCP连接,通常用的TCP 80端口。它的第一个版本是HTTP/0.9,然后被HTTP/1.0取代。当前的版本是HTTP/1.1,由RFC2616(.pdf)定义。本节主要对应HTTP 1.1,足够使你充分理解由Web服务器程序发出的消息。如果你对更加详细的知识有兴趣,可以参考RFC2616。在HTTP中,客户端总是通过建立一个连接与发送一个HTTP请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回叫连接。客户端与服务器端都可以提前中断一个连接。例如,当用一个浏览器下载一个文件时,你可以通过点击停止键来中断文件的下
3、载,关闭与服务器的HTTP连接。HTTP请求一个HTTP请求包含三个部分:Method-URI-Protocol/Version方法-地址-版本Request header请求头Entity body请求实体下面是一个HTTP请求实例:POST/servlet/default.jsp HTTP/1.1 Accept:text/plain;text/html Accept-Language:en-gb Connection:Keep-Alive Host:localhost Referer:Mozilla/4.0(compatible;MSIE 4.01;Windows 98)Content-L
4、ength:33 Content-Type:application/x-www-form-urlencoded Accept-Encoding:gzip,deflate LastName=Franks&FirstName=Michael The Method-URI-Protocol/Version在这个请求的第一行:POST/servlet/default.jsp HTTP/1.1其中POST是请求的类型。每个客户端HTTP请求可以是HTTP规范中指定的许多请求类型中的一种。HTTP 1.1支持七种类型的请求,它们是GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE
5、。其中GET与POST是Internet应用中经常用到的二种请求类型。URI完整地指定了Internet资源。一个URI通常被解析为相对服务器的根目录。这样,它应该总是以一个/前缀开始。一个URL实际上是URI的一种类型。Version指的是该HTTP请求所用到的HTTP协议版本。请求头包含了客户端环境与请求实体的一些有用的信息。例如它包含浏览器设定的语言、实体的长度等等。每条请求头用回车换行符(CRLF)分开。一个非常重要的空行分开了请求头与实体,它标志着实体内容的开始。一些Internet开发书籍认为这个CRLF空行是HTTP请求的第四个部分。在上面的HTTP请求中,实体只是简单以下的一行
6、:LastName=Franks&FirstName=Michael在一个典型的HTTP请求中,请求实体内容会长得多。HTTP响应与请求相似,HTTP响应也由三部分组成:Protocol-Status code-Description协议状态描述代码Response headers响应头Entity body响应实体以下是一个HTTP响应的实例:HTTP/1.1 200 OK Server:Microsoft-IIS/4.0 Date:Mon,3 Jan 1998 13:13:33 GMT Content-Type:text/html Last-Modified:Mon,11 Jan 1998
7、 13:23:42 GMT Content-Length:112 html head title HTTP Response Example/title/head body Welcome to Brainy Software/body/html响应头的第一行类似请求头的第一行,告诉你所用的协议是HTTP 1.1,请求成功(200=success),以及没有任何问题。响应头类似请求头也包含了一些有用的信息。响应的实体响应本身的HTML内容。头与实体之间由回车换行的空行(CRLF)分开。Socket类一个socket是一个网络连接的端点,它使得一个应用可以从网络读与写。在不同电脑上的二个应用软件
8、能够通过收发字节流而彼此通信。要发一个信息到另一个应用程序,你需要知道它的IP地址,以及它的socket端口号。在Java中,一个socket用.Socket来实现。要创建一个socket,你可以用Socket类中几个构建方法中的一个。其中一个接受主机名与端口号作为参数:new Socket(,80);一旦你成功地创建了一个Socket类的实例,你就可以用它去发送与接收字节流了。要发送字节流,你需要呼叫Socket类的getOutputStream方法来得到一个java.io.OutputSteam对象。要发送文本到远程的程序,你通常需要从返回的OutputS
9、tream创建一个java.io.PrintWriter对象。要从连接的另一端接收字节流,你需要呼叫Socket类的getInputStream方法,它返回一个java.io.InputStream对象。以下代码创建一个可以与本地HTTP服务器通信的socket(表示一个本地的主机),发送一个HTTP请求,并接收从服务器的响应。它还创建一个StringBuffer对象来接受响应,并打印到控制台。Socket socket=new Socket(,8080);OutputStream os=socket.getOutputStream();boolean au
10、toflush=true;PrintWriter out=new PrintWriter(socket.getOutputStream(),autoflush);BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream();/send an HTTP request to the web server out.println(GET/index.jsp HTTP/1.1);out.println(Host:localhost:8080);out.println(Connection:Clos
11、e);out.println();/read the response boolean loop=true;StringBuffer sb=new StringBuffer(8096);while(loop)if(in.ready()int i=0;while(i!=-1)i=in.read();sb.append(char)i);loop=false;Thread.currentThread().sleep(50);/display the response to the out console System.out.println(sb.toString();socket.close();
12、注意要从web服务器得到正确的响应,你必须要发送用HTTP协议编译了的HTTP请求。如果你看了上面的HTTP部分,你应该能够理解上面代码中的HTTP请求。编者注:这篇文章节选自budi自己出版的书。你可以在他的网站得到更多的相关资料。基于Java的Web服务器工作原理2作者:fajaven译发文时间:2003.09.12 17:00:38 ServerSocket类Socket类描述的是客户端socket,当你需要创建与远程服务程序连接时需要用到它。如果你想实现一个服务程序,如HTTP服务器或者FTP服务器,则需要另外不同的方法。这是因为你的服务器必须随时服务,它不知道什么时候会有一个客户端程
13、序需要连接它。因为这个目的,你需要用到.ServerSocket这个类,它是服务器端socket的一个实现。服务器端socket等待来自客户端的连接请求。一旦它收到一个连接请求,它创建一个socket实例来与客户端进行通信。要创建服务器端socket,需要用到ServerSocket类提供的四个构建方法中的一个。你需要指定服务器端socket侦听的IP地址与端口号。比较典型地,这个IP地址可以是,意思是该服务器端socket侦听的是本地机器。服务器端socket侦听的IP地址指的是绑定地址。服务器端socket另一个重要的属性是队列长度,即它拒绝请求前所接受的
14、最大请求排队长度。ServerSocket类的构建方法之一如下:public ServerSocket(int port,int backLog,InetAddress bindingAddress);对于这个构建方法,绑定地址必须是.InetAddress类的实例。创建一个InetAddress类的对象的简单方法是呼叫其静态方法getByName,传递一个包含主机名的字符串。InetAddress.getByName();以下行的代码创建了一个服务器端socket,它侦听本地机器的8080端口,限制队列长度为1。new ServerSocket(8080,1
15、,InetAddress.getByName();一旦有了一个ServerSocket实例,就可以通过呼叫其accept方法来让它等待进来的链接请求。这个方法只有当接收到请求时才返回,它返回的是Socket类的实例。这个Socket对象就可以用来从客户端应用程序发送与接收字节流,正如上节据说的那样。实际上,accept方法是本文例子中用到的唯一方法。应用实例我们的web服务器程序是ex01.pyrmont包的一部分,它包含三个类:HttpServer;Request;Response。整个程序的入口(静态main方法)是HttpServer类。它创建一个HttpServer的
16、实例,并呼叫其await方法。正如名字表达的,await在一个特定的端口等待HTTP请求,处理它们,并返回响应给客户端。它保持等待状态,直到收到停止命令。(用方法名await代替wait,是因为System中有一个重要的与线程相关的方法)这个程序只从一个特定的目录发送静态资源,如HTML与图像文件。它只支持没有文件头(如日期与cookie)的情况。现在我们将在如下的几节中看一下这三个类。HttpServer类HttpServer实现了一个web服务器,它可以提供(serve)特定目录及其子目录下的静态资源。这个特定的目录由public static final WEB_ROOT指定。WEB_R
17、OOT初始化如下:public static final String WEB_ROOT=System.getProperty(user.dir)+File.separator+webroot;代码列表中包含了一具叫做webroot的目录,里面有一些静态的资源,你可以用来测试本应用。你也可以看到一个servlet,在我的下一篇文章将会被用到:Servlets容器是怎样工作的。为了请求一个静态的资源,在浏览器的地址栏输入如是地址:如果你从不同的机器上发送请求到运行本应用的机器,则machinename是运行应用机器的机器名或IP地址,port是8080,staticResources是被请求的文
18、件名称,它必须包含在WEB_ROOT目录内。例如,如果你用同一台电脑来测试这个应用,你想要HttpServer发送index.html这个文件,用以下的地址:要停止服务,只需要从浏览器发送一个停止(shutdown)命令,即在浏览器的地址栏输入host:port字段后,加上预先定义好的字符串。在我们的HttpServer类中,停止命令被定义为SHUTDOWN,一个static final变量。private static final String SHUTDOWN_COMMAND=/SHUTDOWN;因此,要停止服务,你可以这样:现在,让我们看一下列表1.1中给出的await方法。代码列表后面
19、将对这段代码做一些解释。Listing 1.1.The HttpServer classawait method public void await()ServerSocket serverSocket=null;int port=8080;tryserverSocket=new ServerSocket(port,1,InetAddress.getByName();catch(IOException e)e.printStackTrace();System.exit(1);/Loop waiting for arequest while(!shutdown)Socket s
20、ocket=null;InputStream input=null;OutputStream output=null;trysocket=serverSocket.accept();input=socket.getInputStream();output=socket.getOutputStream();/create Request object and parse Request request=new Request(input);request.parse();/create Response object Response response=new Response(output);
21、response.setRequest(request);response.sendStaticResource();/Close the socket socket.close();/check if the previous URI is ashutdown command shutdown=request.getUri().equals(SHUTDOWN_COMMAND);catch(Exception e)e.printStackTrace();continue;await方法以创建一个ServerSocket实例开始,然后进入一个while的循环。serverSocket=new S
22、erverSocket(port,1,InetAddress.getByName();./Loop waiting for arequest while(!shutdown).在while循环中的代码,运行到ServerSocket的accept方法即停止。这个方法只有在8080端口接收到HTTP请求才返回:socket=serverSocket.accept();收到请求后,await方法从accept方法返回的Socket实例中等到java.io.InputStream与java.io.OutputStream:input=socket.getInputStream();
23、output=socket.getOutputStream();然后await方法创建一个Request对象,呼叫它的parse方法来解析这个原始的HTTP请求:/create Request object and parse Request request=new Request(input);request.parse();下一步,await方法创建一个Response对象并把Request对象设置给它,呼叫它的sendStaticResource方法:/create Response object Response response=new Response(output);respon
24、se.setRequest(request);response.sendStaticResource();最后,await方法关闭Socket,呼叫Request的getUri方法来检查HTTP请求的地址是否是一个停止命令。如果是,则shutdown变量被设置为true,程序退出while循环:/Close the socket socket.close();/check if the previous URI is ashutdown command shutdown=request.getUri().equals(SHUTDOWN_COMMAND);基于Java的Web服务器工作原理3作者
25、:fajaven发文时间:2003.09.12 17:11:54 Request类Request类对应HTTP请求。创建这个类的实例,并传给它从Socket获得的InputStream对象,从而捕获与客户端的通信。呼叫InputStream对象的read方法中的一个就可以得到HTTP请求的原始数据。Request类有二个public方法parse与getUri。parse方法解析HTTP请求的原始数据。它做的事情不多-唯一它使之有效的信息是HTTP请求的URI,这个通过呼叫私有方法parseUri来获得。parseUri方法把URI作为一个变量。调用getUri方法可以得到HTTP请求的URI
26、。要明白parse与parseUri的工作原理,你需要知道HTTP请求的结构,由RFC2616定义。一个HTTP请求包括三个部分:Request line;Headers;Message body。现在,我们只需要关注HTTP请求的第一部分-请求行。请求行以方法记号开始,接着是请求的URI与协议版本,以回车换行符结束。请求行的元素之间以空格分开。例如,一个用GET方法的index.html文件的请求行如下:?GET/index.html HTTP/1.1?parse方法从socket的InputStream传递给Request对象中读取字节流,把这个字节数组存在缓冲里。然后,它把buffer字
27、节数组里的字节放入叫做request的StringBuffer对象中,再把StringBuffer替换成String传递给parseUri方法。parse方法的代码如列表1.2 Listing 1.2.The Request classparse method?public void parse()/Read aset of characters from the socket StringBuffer request=new StringBuffer(2048);int i;byte buffer=new byte2048;tryi=input.read(buffer);catch(IOEx
28、ception e)e.printStackTrace();i=-1;for(int j=0;j i;j+)request.append(char)bufferj);System.out.print(request.toString();uri=parseUri(request.toString();parseUri方法查找请求行的第一个与第二个空格,从而从请求行获得了URI。列表1.3展示了parseUri方法的代码。Listing 1.3.The Request classparseUri method private String parseUri(String requestStrin
29、g)int index1,index2;index1=requestString.indexOf();if(index1!=-1)index2=requestString.indexOf(,index1+1);if(index2 index1)return requestString.substring(index1+1,index2);return null;Response类Response类描述HTTP响应。它的构建方法接受OutputStream对象,如下:public Response(OutputStream output)this.output=output;Response对象
30、通过传递从socket获得的OutputStream对象到HttpServer类的await方法而创建。Response类有二个公共方法setRequest与setStaticResource。setRequest用来传递Request对象到Response对象。它比较简单,代码如列表1.4所示:Listing 1.4.The Response classsetRequest method public void setRequest(Request request)this.request=request;sendStaticResource方法用来发送静态的资源,例如HTML文件。它的实现
31、如列表1.5所示:Listing 1.5.The Response classsendStaticResource method public void sendStaticResource()throws IOExceptionbyte bytes=new byteBUFFER_SIZE;FileInputStream fis=null;tryFile file=new File(HttpServer.WEB_ROOT,request.getUri();if(file.exists()fis=new FileInputStream(file);int ch=fis.read(bytes,0,
32、BUFFER_SIZE);while(ch!=-1)output.write(bytes,0,ch);ch=fis.read(bytes,0,BUFFER_SIZE);else/file not found String errorMessage=HTTP/1.1 404 File Not Foundrn+Content-Type:text/htmlrn+Content-Length:23rn+rn+h1 File Not Found/h1;output.write(errorMessage.getBytes();catch(Exception e)/thrown if cannot inst
33、antiate aFile object System.out.println(e.toString();finallyif(fis!=null)fis.close();SendStaticResource方法非常简单。它首先通过传递父与子目录到File类的构建方法从而实例化java.io.File类。File file new File(HttpServer.WEB_ROOT,request.getUri();然后检查这个文件是否存在。如果存在,则sendStaticResource方法传递File对象创建java.io.FileInputStream对象。然后调用FileInputStre
34、am的read方法,并把字节数组写到OutputStream对象output。就这样,静态资源的内容作为原始数据被发送到浏览器。if(file.exists()fis=new FileInputStream(file);int ch=fis.read(bytes,0,BUFFER_SIZE);while(ch!=-1)output.write(bytes,0,ch);ch=fis.read(bytes,0,BUFFER_SIZE);如果文件不存在,sendStaticResource发送一个错误信息到浏览器。String errorMessage=HTTP/1.1 404 File Not F
35、oundrn+Content-Type:text/htmlrn+Content-Length:23rn+rn+h1 File Not Found/h1;output.write(errorMessage.getBytes();编译与运行应用程序要编辑与运行本文的应用,首先你需要解压源码zip文件。直接解压出来的目录被称为工作目录,它有三个子目录:src/,classes/,lib/。要编译应用,从工作目录输入如下命令:javac-d.src/ex01/pyrmont/*.java-d选项把结果写到当前目录,而不是src/目录。要运行应用,在当前工作目录输入如下命令:java ex01.pyrm
36、ont.HttpServer测试这个应用,打开你的浏览器,在地址栏输入如下地址:你将在你的浏览器看到index.html显示出来,如图1所示。图1:web服务器的输出显示在控制台,你看到如下的内容:GET/index.html HTTP/1.1 Accept:*/*Accept-Language:en-us Accept-Encoding:gzip,deflate User-Agent:Mozilla/4.0(compatible;MSIE 4.01;Windows 98)Host:localhost:8080 Connection:Keep-Alive GET/images/logo.gif
37、 HTTP/1.1 Accept:*/*Referer:en-us Accept-Encoding:gzip,deflate User-Agent:Mozilla/4.0(compatible;MSIE 4.01;Windows 98)Host:localhost:8080 Connection:Keep-Alive总结在这篇文章中(分为三个部分),你看到了一个简单的web服务器的工作原理。本文相关的应用只包括了三个类,功能是不全面的。然而,它仍不失为一个好的学习工具。(责任编辑:张明燕)Java的网络编程:用Java实现Web服务器作者:谷和启发文时间:2002.12.26 15:35:57
38、 HTTP协议超文本传输协议(HTTP)是位于TCP/IP协议的应用层,是最广为人知的协议,也是互连网中最核心的协议之一,同样,HTTP也是基于C/S或B/S模型实现的。事实上,我们使用的浏览器如Netscape或IE是实现HTTP协议中的客户端,而一些常用的Web服务器软件如Apache、IIS和iPlanet Web Server等是实现HTTP协议中的服务器端。Web页由服务端资源定位,传输到浏览器,经过浏览器的解释后,被客户所看到。Web的工作基于客户机/服务器计算模型,由Web浏览器(客户机)和Web服务器(服务器)构成,两者之间采用超文本传送协议(HTTP)进行通信。HTTP协议是
39、Web浏览器和Web服务器之间的应用层协议,是通用的、无状态的、面向对象的协议。一个完整的HTTP协议会话过程包括四个步骤:连接,Web浏览器与Web服务器建立连接,打开一个称为Socket(套接字)的虚拟文件,此文件的建立标志着连接建立成功;请求,Web浏览器通过Socket向Web服务器提交请求。HTTP的请求一般是GET或POST命令(POST用于FORM参数的传递);应答,Web浏览器提交请求后,通过HTTP协议传送给Web服务器。Web服务器接到后,进行事务处理,处理结果又通过HTTP传回给Web浏览器,从而在Web浏览器上显示出所请求的页面;关闭连接,应答结束后Web浏览器与Web
40、服务器必须断开,以保证其它Web浏览器能够与Web服务器建立连接。Java实现Web服务器功能的程序设计编程思路根据上述HTTP协议的会话过程,本实例中实现了GET请求的Web服务器程序的方法,方法如下:通过创建ServerSocket类对象,侦听用户指定的端口(为8080),等待并接受客户机请求到端口。创建与Socket相关联的输入流和输出流,然后读取客户机的请求信息。若请求类型是GET,则从请求信息中获取所访问的HTML文件名;如果HTML文件存在,则打开HTML文件,把HTTP头信息和HTML文件内容通过Socket传回给Web浏览器,然后关闭文件,否则发送错误信息给Web浏览器。最后关
41、闭与相应Web浏览器连接的Socket。用Java编写Web服务器httpServer.java文件的源代码如下:/httpServer.java import .*;import java.io.*;import java.util.*;import java.lang.*;public class httpServerpublic static void main(String args)int port;ServerSocket server_socket;/读取服务器端口号tryport=Integer.parseInt(args0);catch(Exception e
42、)port=8080;try/监听服务器端口,等待连接请求server_socket=new ServerSocket(port);System.out.println(httpServer running on port+server_socket.getLocalPort();/显示启动信息while(true)Socket socket=server_socket.accept();System.out.println(New connection accepted+socket.getInetAddress()+:+socket.getPort();/创建分线程tryhttpReque
43、stHandler request=new httpRequestHandler(socket);Thread thread=new Thread(request);/启动线程thread.start();catch(Exception e)System.out.println;catch(IOException e)System.out.println;class httpRequestHandler implements Runnablefinal static String CRLF=rn;Socket socket;InputStream input;OutputStream outp
44、ut;BufferedReader br;/构造方法public httpRequestHandler(Socket socket)throws Exceptionthis.socket=socket;this.input=socket.getInputStream();this.output=socket.getOutputStream();this.br=new BufferedReader(new InputStreamReader(socket.getInputStream();/实现Runnable接口的run()方法public void run()tryprocessReques
45、t();catch(Exception e)System.out.println;private void processRequest()throws Exceptionwhile(true)/读取并显示Web浏览器提交的请求信息String headerLine=br.readLine();System.out.println(The client request is+headerLine);if(headerLine.equals(CRLF)|headerLine.equals()break;StringTokenizer s=new StringTokenizer(headerLin
46、e);String temp=s.nextToken();if(temp.equals(GET)String fileName=s.nextToken();fileName=.+fileName;/打开所请求的文件FileInputStream fis=null;boolean fileExists=true;tryfis=new FileInputStream(fileName);catch(FileNotFoundException e)fileExists=false;/完成回应消息String serverLine=Server:a simple java httpServer;Str
47、ing statusLine=null;String contentTypeLine=null;String entityBody=null;String contentLengthLine=error;if(fileExists)statusLine=HTTP/1.0 200 OK+CRLF;contentTypeLine=Content-type:+contentType(fileName)+CRLF;contentLengthLine=Content-Length:+(new Integer(fis.available().toString()+CRLF;elsestatusLine=H
48、TTP/1.0 404 Not Found+CRLF;contentTypeLine=text/html;entityBody=HTML+HEAD TITLE 404 Not Found/TITLE/HEAD+BODY 404 Not Found+br usage:+fileName.html/BODY/HTML;/发送到服务器信息output.write(statusLine.getBytes();output.write(serverLine.getBytes();output.write(contentTypeLine.getBytes();output.write(contentLen
49、gthLine.getBytes();output.write(CRLF.getBytes();/发送信息内容if(fileExists)sendBytes(fis,output);fis.close();elseoutput.write(entityBody.getBytes();/关闭套接字和流tryoutput.close();br.close();socket.close();catch(Exception e)private static void sendBytes(FileInputStream fis,OutputStream os)throws Exception/创建一个1
50、K buffer byte buffer=new byte1024;int bytes=0;/将文件输出到套接字输出流中while(bytes=fis.read(buffer)!=-1)os.write(buffer,0,bytes);private static String contentType(String fileName)if(fileName.endsWith(.htm)|fileName.endsWith(.html)returntext/html;returnfileName;编程技巧说明主线程设计主线程的设计就是在主线程httpServer类中实现了服务器端口的侦听,服务器
51、接受一个客户端请求之后创建一个线程实例处理请求,代码如下:import .*;import java.io.*;import java.util.*;import java.lang.*;public class httpServerpublic static void main(String args)port;ServerSocket server_socket;/读取服务器端口号tryport=Integer.parseInt(args0);catch(Exception e)port=8080;try/监听服务器端口,等待连接请求server_socket=new ServerSocket(port);System.out.println(httpServer running on port+server_socket.getLocalPort();.连接处理分线程设计在分线程httpRequestHandler类中实现了HTTP协议的处理,这个类实现了Runnable接口,代码如下:class httpRequestHa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030年中国麦克风支架和动臂行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年中国韩国土工合成材料行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年中国阿司匹林肠溶片行业市场深度分析及发展趋势与投资研究报告
- 2025-2030年中国铁路线束行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年中国茶包行业市场现状供需分析及投资评估规划分析研究报告
- 遂宁工程职业学院《固体化学导论》2023-2024学年第二学期期末试卷
- 贵州黔南科技学院《刑法学(二)》2023-2024学年第二学期期末试卷
- 上饶卫生健康职业学院《纪实写作与公共说理》2023-2024学年第二学期期末试卷
- 桂林旅游学院《国学与管理》2023-2024学年第二学期期末试卷
- 江西制造职业技术学院《工程项目管理软件》2023-2024学年第二学期期末试卷
- 铸造工程师资格考试题及答案
- 2023年广西三类人员B证继续教育网络学习试题及答案分DOC
- 人教版七年级上生命的思考珍视生命微课
- 数学手册(高清版)
- 《安井食品采购成本管理问题研究【开题报告+文献综述+正文】》17000字
- 义务教育语文课程标准(2022)测试题带答案(20套)
- 招聘与配置课程心得体会5篇
- 东芝电梯紧急救出操作指南
- 保护性约束完整版
- 外贸发票 PI 形式发票模板范例
- 2022年新人教版高中生物选择性必修三答案与提示
评论
0/150
提交评论