中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java怎么實現HttpServer模擬前端接口調用

發布時間:2023-04-15 16:20:29 來源:億速云 閱讀:109 作者:iii 欄目:開發技術

這篇文章主要講解了“Java怎么實現HttpServer模擬前端接口調用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java怎么實現HttpServer模擬前端接口調用”吧!

    執行結果展示

    這里是兩個簡單的測試展示,最后有更多的測試示例。

    訪問根目錄,然后會返回一句話(字符串)(注意:那條綠色的龍,只有使用瀏覽器訪問才能看到的,圖片本身也是屬于一個請求的。) Content-Type: application/json

    Java怎么實現HttpServer模擬前端接口調用

    單獨訪問這張圖片,返回值是圖片(二進制數據)

    Java怎么實現HttpServer模擬前端接口調用

    請求和響應配置文件

    所以只要用戶提前設置好請求信息和響應信息,在訪問特定請求時,就能返回特定數據。所以,我設計了一個簡單的 xml 文件用來配置這些信息,使用 xml 配置比較方便,properties 配置文件無法表達層次信息,只能適用于簡單的配置要求。

    一個大的 request_and_responses 代表許多個請求和響應配置,每一個 request_and_response 節點代表一個request 請求和 response 響應信息,里面包含了請求和響應的基本信息。GET 方式請求主要包括:(method) 請求方法 和 (path) 請求路徑和參數。 POST 方法請求還包括一個 (param )請求參數。 response 包括:content_type(響應內容類型) 和 value(響應內容)。

    GET 和 POST 方式的區別在于,GET 方式的請求路徑和請求參數是在一起的(都在請求頭中,沒有請求體),而 POST 方式的請求參數則是在請求體里面的,請求頭和請求體之間有一個 CRLF 分隔。

    xml 文件
    <?xml version="1.0" encoding="UTF-8"?>
    <request_and_responses>
    	<!-- & 需要使用轉義字符 &amp; -->
    		
    	<request_and_response>
    		<request>
    			<method>GET</method>
    			<path>/</path>
    		</request>
    		<response>
    			<content_type>application/json</content_type>
    			<value>I love you yesterday and today!</value>
    		</response>
    	</request_and_response>
    	
    	<request_and_response>
    		<request>
    			<method>GET</method>
    			<path>/login?account=123&amp;pwd=456</path>
    		</request>
    		
    		<response>
    			<content_type>application/json</content_type>
    			<value>success</value>
    		</response>
    	</request_and_response>
    	
    	<request_and_response>
    		<request>
    			<method>GET</method>
    			<path>/query/龍</path>
    		</request>
    		<response>
    			<content_type>application/json</content_type>
    			<value>龍是中國等東亞國家古代神話傳說生活于海中的神異生物。</value>
    		</response>
    	</request_and_response>
    	
    	<request_and_response>
    		<request>
    			<method>POST</method>
    			<path>/login</path>
    			<param>account=123&amp;pwd=456</param>
    		</request>
    		
    		<response>
    			<content_type>application/json</content_type>
    			<value>{"result":success}</value>
    		</response>
    	</request_and_response>
    	
    	
    	<request_and_response>
    		<request>
    			<method>POST</method>
    			<path>/login</path>
    			<param>workId=12345</param>
    		</request>
    		
    		<response>
    			<content_type>application/json</content_type>
    			<value>{"result":"success", "data":{"name":"李工", "sex":"男", "age":35}}</value>
    		</response> 
    	</request_and_response>
    	
    	
    	<request_and_response>
    		<request>
    			<method>GET</method>
    			<path>/pictures/husky.jpeg</path>
    		</request>
    		
    		<response>
    			<content_type>image/jpeg</content_type>
    			<value>D:/DB/husky.jpeg</value>
    		</response> 
    	</request_and_response>
    	
    	<!-- 瀏覽器訪問時的圖標 -->
    	<request_and_response>
    		<request>
    			<method>GET</method>
    			<path>/favicon.ico</path>
    		</request>
    		
    		<response>
    			<content_type>image/webp</content_type>
    			<value>D:/DB/favicon.ico</value>
    		</response> 
    	</request_and_response>
    	
    </request_and_responses>
    xml 映射的實體類

    xml 中的信息,讀取到內存中,使用一個實體類來對信息進行封裝。

    package com.dragon;
    
    public class RequestAndResponse {
    	private String method;
    	private String path;
    	private String param;
    	private String content_type;
    	private String value;
    	
    	public String getMethod() {
    		return method;
    	}
    	public void setMethod(String method) {
    		this.method = method;
    	}
    	public String getPath() {
    		return path;
    	}
    	public void setPath(String path) {
    		this.path = path;
    	}
    	public String getParam() {
    		return param;
    	}
    	public void setParam(String param) {
    		this.param = param;
    	}
    	public String getContent_type() {
    		return content_type;
    	}
    	public void setContent_type(String content_type) {
    		this.content_type = content_type;
    	}
    	public String getValue() {
    		return value;
    	}
    	public void setValue(String value) {
    		this.value = value;
    	}
    	
    	@Override
    	public String toString() {
    		return "RequestAndResponse [method=" + method + ", path=" + path + ", param=" + param + ", content_type="
    				+ content_type + ", value=" + value + "]";
    	}
    }
    xml 文件解析器類

    使用一個類專門解析 xml 文件為Java 對象,然后使用一個 List 集合來存儲所有的對象。

    注:不太會取名字,有點太長了,湊合著看吧!哈哈。 注:這里使用一個xml解析的jar包:dom4j。

    package com.dragon;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    /**
     * 解析 xml 文件中配置的用戶請求和響應數據。
     * */
    public class RequestAndResponseResolver {
    	private static final String method = "method";
    	private static final String path = "path";
    	private static final String param = "param";
    	private static final String content_type = "content_type";
    	private static final String value = "value";
    	
    	public static List<RequestAndResponse> listRequestAndResponse(String filePath) throws DocumentException{
    		File file = new File(filePath); 
    		SAXReader reader = new SAXReader();
    		Document doc = reader.read(file);
    		
    		Element root = doc.getRootElement();
    		//獲取根元素下面所有的子元素,利用迭代器方式
    		Iterator<?> it = root.elementIterator();
    		
    		List<RequestAndResponse> requestAndResponses = new ArrayList<>();
    		while (it.hasNext()) {
    			//取出元素request_and_response
    			Element e = (Element)it.next();
    			//依次遍歷每一個 request_and_response,獲取相應的信息
    			Element request = e.element("request");
    			Element response = e.element("response");
    			
    			RequestAndResponse requestAndResponse = new RequestAndResponse();
    			requestAndResponse.setMethod(request.elementText(method));
    			requestAndResponse.setPath(request.elementText(path));
    			requestAndResponse.setParam(request.elementText(param));   //GET 方式,這個屬性為 null
    			requestAndResponse.setContent_type(response.elementText(content_type));
    			requestAndResponse.setValue(response.elementText(value));
    			
    			requestAndResponses.add(requestAndResponse);
    		}
    		
    		return requestAndResponses;
    	}
    }

    接收請求并處理的部分

    下面介紹一下,使用 Socket 接收并處理請求的部分。 這里涉及的知識和使用 Socket 基本上都是一樣的,唯一的區別就是對于內容本身的處理,因為內容本身是包含數據和非數據部分的。(站在 HTTP 的角度,只能看到數據部分。) 使用 Socket 編程,簡單來說就是監聽一個端口,一旦有連接到來,就進行處理。(這里使用傳統的 BIO,NIO 那部分我不會。)

    這里我的處理是,使用一個線程池進行處理,每一個連接使用一個線程進行處理。關于這個類(Server 類)的完整代碼,見下面。

    	public void receive() {
    		//使用線程池處理請求
    		ExecutorService pool = Executors.newFixedThreadPool(THREAD_NUMBER);
    		
    		while (true) {
    			try {
    				Socket connection = server.accept();
    				pool.submit(new UserConnection(connection));
    			} catch (IOException e) {
    				System.out.println(this.getDate()+" 用戶連接斷開");
    				e.printStackTrace();
    			}
    		}
    	}
    接收請求的代碼:Server 類
    package com.dragon;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Server {
    	private static final int THREAD_NUMBER = 10;
    	private ServerSocket server;
    	private int port;
    	
    	public Server(int port) {
    		this.port = port;
    	}
    	
    	//啟動服務。
    	public void start() {
    		try {
    			server = new ServerSocket(port);
    			System.out.println(this.getDate()+" 服務啟動!");
    			this.receive();
    		} catch (IOException e) {
    			System.out.println(this.getDate()+" 服務啟動失敗!");
    			e.printStackTrace();
    		}
    	}
    	
    	public void receive() {
    		//使用線程池處理請求
    		ExecutorService pool = Executors.newFixedThreadPool(THREAD_NUMBER);
    		
    		while (true) {
    			try {
    				Socket connection = server.accept();
    				pool.submit(new UserConnection(connection));
    			} catch (IOException e) {
    				System.out.println(this.getDate()+" 用戶連接斷開");
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	
    	
    	private String getDate() {
    		String format = "yyyy-MM-dd HH:mm:ss";
    		Date now = new Date();
    		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
    		return dateFormat.format(now);
    	}
    }

    Http 請求報文從 TCP 的層次來看就是一段二進制數據流(網絡是分層的),所以我們可以直接使用 TCP 接收這個流, 因為涉及二進制數據(如文件上傳)的報文解析比較復雜,我也不知道該怎么做,所以這里我只是測試簡單的不含有二進制文件的請求。)

    注:因為具體的解析也是很復雜的,這涉及到 HTTP 報文的結構,但是如果不涉及文件上傳,那么整個報文都是一些字符數據,所以一次性讀取全部請求報文,然后轉成字符串,使用字符串來進行解析。

    in = connection.getInputStream();
    out = connection.getOutputStream();
    			
    //這個數字是隨便設置的,因為要一次性讀取整個請求報文,不能太小。(但是其實這個也很大了)
    byte[] b = new byte[5*1024];
    BufferedInputStream input = new BufferedInputStream(in);
    int count = input.read(b);
    String requestMessage = new String(b, 0, count);
    System.out.println("====================報文分隔符上界===================");
    System.out.println(requestMessage);
    System.out.println("====================報文分隔符下界===================");
    處理請求代碼:UserConnection 類

    請求和響應信息初始化 說明:使用靜態初始化塊來初始化信息,將用戶提前配置好的 xml 信息讀取入內存,前面提到過這部分。

    // 初始化配置好的信息
    	static {
    		try {
    			requestAndResponses = RequestAndResponseResolver.listRequestAndResponse("./src/com/dragon/request_and_response.xml");
    		} catch (DocumentException e) {
    			e.printStackTrace();
    		}
    	}

    請求處理和獲取響應信息 因為這里是模擬調用,所以我主要關注請求頭中的三個部分數據:請求方法(method)、請求路徑(path)、請求參數(param)。 對于 GET 方式和 POST 方式分開進行處理,上面簡單介紹了 GET 和 POST 的區別(但是不夠詳細,可以去參考網上的其它資料了解)。

    通過這段代碼,如果是 GET 方式,就將 RequestAndResponse 對象中的 content_type(返回值數據類型) 和 value (返回值數據)取出來,并賦值給局部變量 content_type 和 value。

    if ("GET".compareTo(method) == 0) {
    	for (RequestAndResponse r : requestAndResponses) {
    		//這里需要對 get 方式時的請求進行解碼,因為一些非 ASCII 碼字符會被編碼,比如漢字。
    		path = URLDecoder.decode(path, ENCODE);
    		if (r.getMethod().equals(method) && r.getPath().equals(path)) {
    			content_type = r.getContent_type();
    			value = r.getValue();
    			break;
    		}
    	}
    } else {
    	//POST 方式,請求參數是在請求體中的,請求頭和請求體中間有一個換行符。
    	String param = requestMessage.substring(requestMessage.lastIndexOf(CRLF) + 2); //這里是不包括 CRLF 的兩個字符的。
    	for (RequestAndResponse r : requestAndResponses) {                 //因為這個get方式的 參數為空,所以這里必須是 param 在前。
    		if (r.getMethod().equals(method) && r.getPath().equals(path) && param.equals(r.getParam())) {
    			content_type = r.getContent_type();
    			value = r.getValue();
    			break;
    		}
    	}
    }

    這里介紹一個知識:URL 中的字符是特定的,不允許中文等字符的出現,所以發送請求時會對中文等字符進行編碼,如果直接使用 equals 方法的,當然不會相等了,所以需要先對數據進行解碼,然后再調用 equals 方法進行處理。這個是我們平時廣泛使用 的東西,有時候使用瀏覽器可以看到帶很多奇怪字符 URL,它們都是被處理過的。

    舉一個簡單的例子:

    String str = "我愛你";
    String en_str = java.net.URLEncoder.encode(str, "UTF-8");
    String de_str = java.net.URLDecoder.decode(en_str, "UTF-8");
    System.out.println("編碼字符:" + en_str);
    System.out.println("解碼字符:" + de_str);

    Java怎么實現HttpServer模擬前端接口調用

    注意:這里有一個特殊的情況,如果發起了沒有配置的請求方法和路徑,那么程序會出錯。所以,這里的 content_type 和 value 有一個默認的值,而且非常有趣!

    Java怎么實現HttpServer模擬前端接口調用

    執行響應 響應信息主要關注幾點:響應信息長度(Content-Length)(按字節數計算)、響應內容類型(Content-Type)。

    雖然發送的請求里不能帶二進制文件,但是響應信息是可以返回文件的,而且使用 Content-Length (一次性發送),不使用 Chunked 分塊發送(這里我還不太明白,而且只是模擬,應該使用一些簡單的小文件。)。

    下面是區分響應類型為 json (字符串) 還是 文件(二進制數據) 的代碼:

    如果是字符串,則 value 的值是字符串的值,如果是文件,則 value 的值為一個具體的本地路徑。(不應該使用網絡圖片,即使修改程序可以做到也沒有必要,因為這樣就需要依賴網絡了。)

    	//這里我只處理字符串類和文件類兩種響應體
    	//響應體
    	int len = 0;
    	String responseBody = null;   //響應值是 json 數據
    	File file = null; //響應值是 文件
    	if (content_type.equals("application/json")) {  //如果是 json 數據,否則就是 文件類數據(圖片、文檔或其它文件)
    		 responseBody = value;
    		 len = responseBody.getBytes().length;   //響應體的字節數,注意是字節數!
    	} else {
    		 file = new File(value);
    		 len = (int) file.length();
    	}

    然后就可以準備發送響應數據了,下面是發送響應的代碼,注意報文的具體結構。

    	//響應頭
    	responseHeader.append("HTTP/1.1").append(BLANK);
    	responseHeader.append(200).append(BLANK);
    	responseHeader.append("OK").append(CRLF);
    	responseHeader.append("Server:"+"CrazyDragon").append(CRLF);
    	responseHeader.append("Date:").append(BLANK).append(date).append(CRLF);
    	responseHeader.append("Content-Type:").append(BLANK).append(content_type).append(CRLF);
    	responseHeader.append("Content-Length:").append(BLANK).append(len).append(CRLF);
    	responseHeader.append(CRLF);
    	
    	//如果 字符串變量 responseBody 不為空,則說明返回值是 json 數據(字符串)
    	//否則就是文件類的流了。
    	if (responseBody != null) {
    		String response = responseHeader.toString() + responseBody;
    		out.write(response.getBytes("UTF-8"));    
    	} else {
    		out.write(responseHeader.toString().getBytes("UTF-8"));  
    		
    		int hasRead = 0;
    		byte[] data = new byte[4*1024];
    		try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
    			while ((hasRead = inputStream.read(data)) != -1) {
    				out.write(data, 0, hasRead);
    			}
    		}
    	}
    	out.flush();   //必要的刷新流操作。

    User Connection 的完整代碼:

    package com.dragon;
    
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.net.URLDecoder;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Locale;
    import java.util.TimeZone;
    
    import org.dom4j.DocumentException;
    
    public class UserConnection implements Runnable{
    	private static final String BLANK = " ";
    	private static final String CRLF = "\r\n"; //換行符,不能寫反了!
    	private static final String ENCODE = "UTF-8";
    	private static final String default_content_type = "application/json";   //當任何匹配路徑都沒有時。
    	private static final String default_value = "404 NOT FOUND!\n沒有找到你配置的請求!";
    	
    	
    	private static List<RequestAndResponse> requestAndResponses;
    	private Socket connection;
    	
    	
    	// 初始化配置好的信息
    	static {
    		try {
    			requestAndResponses = RequestAndResponseResolver.listRequestAndResponse("./src/com/dragon/request_and_response.xml");
    		} catch (DocumentException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	
    	
    	public UserConnection(Socket connection) {
    		this.connection = connection;
    	}
    	
    	@Override
    	public void run() {
    		InputStream in = null;
    		OutputStream out = null;
    		try {
    			in = connection.getInputStream();
    			out = connection.getOutputStream();
    			
    			//這個數字是隨便設置的,因為要一次性讀取整個請求報文,不能太小。(但是其實這個也很大了)
    			byte[] b = new byte[5*1024];
    			BufferedInputStream input = new BufferedInputStream(in);
    			int count = input.read(b);
    			String requestMessage = new String(b, 0, count);
    			System.out.println("====================報文分隔符上界===================");
    			System.out.println(requestMessage);
    			System.out.println("====================報文分隔符下界===================");
    
    			//以第一個 換行符 CRLF 為界限取出 請求路徑和請求參數
    			String requestLine = requestMessage.substring(0, requestMessage.indexOf(CRLF));
    			String[] line = requestLine.split("\\s");
    			String method = line[0];  //考慮大小寫。
    			String path = line[1];  
    			//這個數組是有三個元素,最后一個是 協議的版本,這里不需要,就不處理了。
    			String content_type = default_content_type;
    			String value = default_value;
    			if ("GET".compareTo(method) == 0) {
    			//	System.out.println("請求方式:" + method + " 請求路徑(含參數):" + path);
    				for (RequestAndResponse r : requestAndResponses) {
    					//這里需要對 get 方式時的請求進行解碼,因為一些非 ASCII 碼字符會被編碼,比如漢字。
    					path = URLDecoder.decode(path, ENCODE);
    					if (r.getMethod().equals(method) && r.getPath().equals(path)) {
    						content_type = r.getContent_type();
    						value = r.getValue();
    						break;
    					}
    				}
    			} else {
    				//POST 方式,請求參數是在請求體中的,請求頭和請求體中間有一個換行符。
    				String param = requestMessage.substring(requestMessage.lastIndexOf(CRLF) + 2); //這里是不包括 CRLF 的兩個字符的。
    				for (RequestAndResponse r : requestAndResponses) {                 //因為這個get方式的 參數為空,所以這里必須是 param 在前。
    					if (r.getMethod().equals(method) && r.getPath().equals(path) && param.equals(r.getParam())) {
    						content_type = r.getContent_type();
    						value = r.getValue();
    						System.out.println(content_type+" "+value);
    						break;
    					}
    				}
    			}
    		
    			StringBuilder responseHeader = new StringBuilder();
    			String date = this.getDate();
    			
    			
    			//這里我只處理字符串類和文件類兩種響應體
    			//響應體
    			int len = 0;
    			String responseBody = null;   //響應值是 json 數據
    			File file = null; //響應值是 文件
    			if (content_type.equals("application/json")) {  //如果是 json 數據,否則就是 文件類數據(圖片、文檔或其它文件)
    				 responseBody = value;
    				 len = responseBody.getBytes().length;   //響應體的字節數,注意是字節數!
    			} else {
    				 file = new File(value);
    				 len = (int) file.length();
    			}
    			
    			//響應頭
    			responseHeader.append("HTTP/1.1").append(BLANK);
    			responseHeader.append(200).append(BLANK);
    			responseHeader.append("OK").append(CRLF);
    			responseHeader.append("Server:"+"CrazyDragon").append(CRLF);
    			responseHeader.append("Date:").append(BLANK).append(date).append(CRLF);
    			responseHeader.append("Content-Type:").append(BLANK).append(content_type).append(CRLF);
    			responseHeader.append("Content-Length:").append(BLANK).append(len).append(CRLF);
    			responseHeader.append(CRLF);
    			
    			//如果 字符串變量 responseBody 不為空,則說明返回值是 json 數據(字符串)
    			//否則就是文件類的流了。
    			if (responseBody != null) {
    				String response = responseHeader.toString() + responseBody;
    				out.write(response.getBytes("UTF-8"));    
    			} else {
    				out.write(responseHeader.toString().getBytes("UTF-8"));  
    				
    				int hasRead = 0;
    				byte[] data = new byte[4*1024];
    				try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
    					while ((hasRead = inputStream.read(data)) != -1) {
    						out.write(data, 0, hasRead);
    					}
    				}
    			}
    			out.flush();   //必要的刷新流操作。
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (in != null)
    					in.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	private String getDate() {
    		Date date = new Date();
    		SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.CHINA);
    		format.setTimeZone(TimeZone.getTimeZone("GMT")); // 設置時區為GMT  
    		return format.format(date);
    	}
    }

    主程序類:Main

    package com.dragon;
    
    public class Main {
    	public static void main(String[] args) {
    		Server server = new Server(9000);
    		server.start();		
    	}
    }

    更多的測試示例

    請求方式:GET 請求路徑和參數:/query/龍 預期的響應類型:application/json 預期的響應值:龍是中國等東亞國家古代神話傳說生活于海中的神異生物。 測試結果:

    Java怎么實現HttpServer模擬前端接口調用

    請求方式:GET 請求路徑和參數:/login?account=123&pwd=456 預期的響應類型:application/json 預期的響應值:success 測試結果:

    Java怎么實現HttpServer模擬前端接口調用

    請求方式:GET 請求路徑和參數:/pictures/husky.jpeg 預期的響應類型:image/jpeg 預期的響應值:一張圖片(地址為:D:/DB/husky.jpeg)

    請求方式:POST 請求路徑:/login 請求參數:account=123&pwd=456 預期的響應類型:application/json 預期的響應值:{“result”:success} 測試結果:

    Java怎么實現HttpServer模擬前端接口調用

    注:這是使用 HttpClient 發送的 POST 請求。

    Java怎么實現HttpServer模擬前端接口調用

    接收到的 POST 請求:

    Java怎么實現HttpServer模擬前端接口調用

    接收到的 GET 請求(含中文參數): /query/龍 注意:“龍” 已經被編碼了。

    Java怎么實現HttpServer模擬前端接口調用

    感謝各位的閱讀,以上就是“Java怎么實現HttpServer模擬前端接口調用”的內容了,經過本文的學習后,相信大家對Java怎么實現HttpServer模擬前端接口調用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    海丰县| 东乡族自治县| 鹤庆县| 卢湾区| 阳泉市| 称多县| 新营市| 越西县| 宁国市| 丰原市| 云和县| 宣威市| 商都县| 宜春市| 苍梧县| 噶尔县| 彩票| 长治市| 松溪县| 乐至县| 西安市| 黄平县| 宝兴县| 巧家县| 宜阳县| 修水县| 卓资县| 扎囊县| 醴陵市| 浦江县| 同仁县| 东明县| 杭锦后旗| 金昌市| 时尚| 临泽县| 厦门市| 耿马| 惠安县| 西贡区| 盱眙县|