热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

浅谈web服务器项目中request请求和response的相关响应处理

这篇文章主要介绍了浅谈web服务器项目中request请求和response的相关响应处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  我们经常使用别人的服务器进行构建网站,现在我们就自己来写一个自己的服务来使用。

准备工作:下载所需的题材及文档

注:完整项目下载

一、request请求获取

 1、了解request请求

在写服务器之前,我们需要知道客户端发送给我们哪些信息?以及要求我们返回哪些信息?经过测试我们能够知道用户客户端发送的信息有以下几点:

客户端发送到服务器端的请求消息,我们称之为请求(request),其实就是一个按照http协议的规则拼接而成的字符串,Request请求消息包含三部分: 请求行 消息报头 请求正文
        第一部 请求行
            格式:
            Method Request-URI HTTP-Version CRLF
             各部分分别为:
            Method表示请求方法;一般为GET或者POST ;Request-URI是一个统一资源标识符; HTTP-Version表示请求的HTTP协议版本; CRLF表示回车和换行
            例如:
            GET /test.html HTTP/1.1  

        第二部 消息报头 http header
            例如:
            GET /test.html HTTP/1.1
            Host: 127.0.0.1:9999
            User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
            Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
            Accept-Language: zh-CN,en;q=0.8,zh;q=0.5,en-US;q=0.3
            Accept-Encoding: gzip, deflate
            Connection: keep-alive 

        第三部 请求正文 http body
            请求头和请求正文之间是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。请求正文中可以包含客户提交的字符串信息

        注意:在第二部分header和第三部分body之间有个空行,除非没有请求正文(如果你想要亲自看到效果,请参考:浏览器中GET和POST的区别),这是因为用户在浏览网页时提交给服务器的信息是不同的

 2、实现

         经过以上分析,我们就能够清楚的知道,客户端发送给服务器的请求,请求信息有使用的协议、请求的方法、请求的资源路径、请求的消息报头、判断请求的内容是否为静态资源、判断请求的内容是否为动态资源、判断是否为空请求,为了使用的方便,我们需要将其封装起来,总不能使用一次读取一次吧,这样做实在是太浪费系统资源与时间了,如下代码,就是一个接口类,用于获取客户端发送过来的属性

package com.sample.http;
import java.util.Map;
 // http协议的请求
public interface HttpRequest {
 //获得请求的协议
 public String getProtocol();
 //获得请求的方法
 public String getRequestMethod();
 //获得请求的路径
 public String getRequestPath();
 //获得请求的消息报头
 public Map getRequestHeader();
 //根据参数的名字获得请求带过来的参数值
 public String getParameter(String parameterName);
 //判断当前请求的否是静态资源
 public boolean isStaticResource();
 //判断当前请求的否是动态资源
 public boolean isDynamicResource();
 //判断当前请求的否是为空请求(有些浏览器会自动发送空请求)
 public boolean isNullRequest();
}

有了接口类之后,我们就可以创建类进行实现,下面就是实现类,用于对各个方法进行处理:

package com.sample.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HttpRequestImpl implements HttpRequest{
	//客户端的Socket
	private Socket s;
	private InputStream is=null;//输入流
	private BufferedReader br=null;
	private HashMap hmHeader=new HashMap();//消息报头
	private HashMap hmparameters=new HashMap();//参数集合
	private boolean isNullRequest=false;//是否为空请求,默认false
	private String protocol=null;//请求协议
	private String requestMethod=null;//请求方法
	private String requestPath=null;//请求路径
	public HttpRequestImpl(Socket s) {
		this.s=s;
		getInfos();//调用方法
	 }
	private void getInfos()//定义一个方法,用于处理获取的客户端信息
	{
		try {
			is=s.getInputStream();
			br=new BufferedReader(new InputStreamReader(is));
			//解析第一行
			String str;
			str=br.readLine();//readLine使用回车换行判断一行是否结束
			if(str==null)
			{
				isNullRequest=true;
				return;
			}
			parseRequestMethodPathProtocol(str);//调用自己创建在本类里边的方法处理第一行信息,方法在后面
		//解析第二行---第八行
			String header=null;  
  //判断是否结束,如果结束就退出,这里的判断按较为饶人
  //首先应该明确br.readLine()的内容,当为true是对应的情况
  //也就是说当“”(中间没有空格)与br.readLine()相等时,就进入到while中
  while(!"".equals((header=br.readLine()))){
			parseRequestHeader(header);
			}
		//post和get
		if(br.ready())//post//POST提交方式判断,如果还有下一行就继续读取信息
		{
			char[] buf=new char[1024];
			int len=br.read(buf);//使用字节进行读取,因为这一行没有回车换行,readLine无法判断是否结束
			String parameter=new String(buf,0,len);
			parseRequestParamByPost(parameter);//调用自己创建在本类里边的方法处理POST方式提交的正文信息	
		}
		else
		{//get,get参数的位置在第一行连接处
			parseRequestParamByGet(requestPath);//调用自己创建在本类里边的方法处理GET方式提交的正文信息	
		}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 //GET方法处理
 private void parseRequestParamByGet(String requestPath2) {
		String []str1=requestPath2.split("[?]");//使用“?”分割字符串
		if(str1.length==2)
		{
				parseRequestParamByPost(str1[1]);
		}
		this.requestPath=str1[0];
	}
 //POST方法处理
 private void parseRequestParamByPost(String parameter) {
		 String[] strs=parameter.split("&");
		 if(strs.length>=1)
		 {
			 for(String str:strs)
			 {
				 String [] sp=str.split("=");
  hmparameters.put(sp[0],sp[1]); 
			 }
		 }
	}
	//解析第二行到第八行
	private void parseRequestHeader(String header) throws Exception{
		String[] headHost=header.split(": ");
		 if(headHost.length!=2)
	 {
			 throw new Exception("消息报头异常,请重新提交");		 
		 }
		 hmHeader.put(headHost[0],headHost[1]);
	}
	//解析第一行
	private void parseRequestMethodPathProtocol(String str) throws Exception {
		 String[] protocolMethodPath=new String[3];//由于第一行含有三个内容,分割后需要三个String存储
		 protocolMethodPath=str.split(" ");//使用空格分割
		 if(protocolMethodPath.length==3)
		 {
		 requestMethod=protocolMethodPath[0];
		 requestPath=protocolMethodPath[1];
		 protocol=protocolMethodPath[2];
		 }
		 else
		 {
			 throw new Exception("首行参数不合适,请重新提交");
		 }
	}
	//获得请求的协议
	public String getProtocol()
	{
		return protocol;
	}
	//获得请求的方法
	public String getRequestMethod(){
		return requestMethod;
	}
	//获得请求的路径
	public String getRequestPath(){
		return requestPath;
	}
	//获得请求的消息报头
	public Map getRequestHeader(){
		return this.hmHeader;
	}
	//根据参数的名字获得请求带过来的参数值
	public String getParameter(String parameterName){
		return hmparameters.get(parameterName);
	}
	//判断当前请求的否是静态资源
	public boolean isStaticResource(){
		return true;
	}
	//判断当前请求的否是动态资源
	public boolean isDynamicResource(){
		return true;
	}
	//判断当前请求的否是为空请求(有些浏览器会自动发送空请求)
	public boolean isNullRequest(){
 return isNullRequest;
	}
}

以上内容是对客户端(浏览器)请求内容的处理,即如何进行包装客户端请求的信息,并且将其包装成一个统一的整体,既然能够获取浏览器的内容,那么,我们就必须采取一定的措施告诉浏览器我们找到了你想要的文件,并且将返回给客户端,下面我们就来实现如何返回给客户端想要的信息

二、response响应处理

 1、了解response响应 

    服务器在接收和解释客户端的请求消息后,服务器会返回给客户端一个HTTP响应消息,我们称之为响应(response)。其实也是一个按照http协议的规则拼接而成的一个字符串
    HTTP响应也是由三个部分组成,分别是: 响应状态行、消息报头、响应正文 
    

第一部分 响应状态行 

        格式如下:
        HTTP-Version Status-Code Reason-Phrase CRLF
例如:
        HTTP/1.1 200 OK
        各部分分别为:
        HTTP-Version表示服务器HTTP协议的版本;
        Status-Code表示服务器发回的响应状态代码; 
        Reason-Phrase表示状态代码的文本描述。
        CRLF表示回车和换行

    第二部分 消息报头

        HTTP消息报头包括普通报头、请求报头、响应报头、实体报头这四大类。
  每一个 报头域 都是由 名字+冒号+空格+值 组成,消息报头域的名字不区分大小写。它们的作用是描述 客户端或者服务器 的属性
                 1.普通报头:即可用于请求,也可用于响应,是作为一个整体而不是特定资源与事务相关联。
                 2.请求报头:允许客户端传递关于自身信息和希望的响应形式。
                 3.响应报头:允许服务器传递关于自身信息的响应。
                 4.实体报头:定义被传送资源的信息。即可用于请求,也可用于响应。 

 什么是 MIME Type?

        首先,我们要了解浏览器是如何处理内容的。在浏览器中显示的内容有 HTML、有 XML、有 GIF、还有 Flash ……那么,浏览器是如何区分它们,决定什么内容用什么形式来显示呢?答案是 MIME Type,也就是该资源的媒体类型。媒体类型通常是通过 HTTP 协议,由 Web 服务器告知浏览器的,更准确地说,是通过响应的消息报头里面的属性 Content-Type 来表示的,例如:Content-Type: text/HTML表示内容是 text/HTML 类型,也就是超文本文件。为什么是“text/HTML”而不是“HTML/text”或者别的什么?MIME Type 不是个人指定的,是经过 ietf 组织协商,以 RFC 的形式作为建议的标准发布在网上的,大多数的 Web 服务器和用户代理都会支持这个规范 (顺便说一句,Email 附件的类型也是通过 MIME Type 指定的)。

      通常只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。XHTML 正是一个获得广泛应用的格式,因此,在 RFC 3236 中,说明了 XHTML 格式文件的 MIME Type 应该是 application/xHTML+XML。当然,处理本地的文件,在没有人告诉浏览器某个文件的 MIME Type 的情况下,浏览器也会做一些默认的处理,这可能和你在操作系统中给文件配置的 MIME Type 有关。比如在 Windows 下,打开注册表的“HKEY_LOCAL_MACHINESOFTWAREClassesMIMEDatabaseContent Type”主键,你可以看到所有 MIME Type 的配置信息

每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类。

常见的MIME类型

超文本标记语言文本 .html,.html text/html
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
GIF图形 .gif image/gif
JPEG图形 .ipeg,.jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar

    第三部分 响应正文

        响应正文就是服务器返回的资源的内容 

 2、实现

      首先,我们需要进行抽象,即将浏览器想要的信息,即如下内容包装起来,如下所示,我们将其包装成一个接口,在抽象时我们必须认识到用户可能会犯的错误,所以尽量使用重载的方法进行避免,在下面的接口中,使用了重载进行处理部分方法:

package com.sample.http;
import java.io.OutputStream;
import java.io.PrintWriter;
//http协议的响应
public interface HttpResponse {
	//获得一个指向客户端的字节流
	public OutputStream getOutputStream()throws Exception;
	//获得一个指向客户端的字符流
	public PrintWriter getPrintWriter()throws Exception;
	//设置响应的状态行 参数为String类型
	public void setStatusLine(String statusCode);
	//设置响应的状态行 参数为int类型
	public void setStatusLine(int statusCode);
	//设置响应消息报头
	public void setResponseHeader(String hName,String hValue);
	//设置响应消息报头中Content-Type属性
	public void setContentType(String contentType);
	//设置响应消息报头中Content-Type属性 并且同时设置编码
	public void setContentType(String contentType,String charsetName);
	//设置CRLF 回车换行 \r\n
	public void setCRLF();
	//把设置好的响应状态行、响应消息报头、固定空行这三部分写给浏览器
	public void printResponseHeader();
	//把响应正文写给浏览器
	public void printResponseContent(String requestPath);		
}

在接口中,我们能够看到详细的解释,下面我们就来实现接口中的方法:

package com.sample.http;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
 
import com.sample.utils.ConfigUtils;
import com.sample.utils.StatusCodeUtils;
//http协议的响应
public class HttpResponseImpl implements HttpResponse {
	 //声明初始变量
	Socket s;//客户端socket
	OutputStream os;//输出端字节流
	BufferedWriter bw;//输出端字符流
	PrintWriter pw;
	StringBuffer sbuffer;//放状态行,\r\n ,
	FileInputStream fis;
	File file;
	//构造器
	public HttpResponseImpl(Socket s) {
  this.s=s;
  System.out.println("HttpRequestImpl(Socket s)");
  os=null;
  bw=null;
  pw=null;
  sbuffer=new StringBuffer();//初始化,记得,否则以下的操作会遇见空指针异常
  fis=null;
  file=null; 			
  getInfos();
	}
	 
	private void getInfos() {
			try {
				os=s.getOutputStream();
				bw=new BufferedWriter(new OutputStreamWriter(os,"GBK"));
				pw=new PrintWriter(bw);
			} catch (Exception e) {
				e.printStackTrace();
			}
	}
	//获得一个指向客户端的字节流
	public OutputStream getOutputStream()throws Exception
	{
		return os;
	}
	//获得一个指向客户端的字符流
	public PrintWriter getPrintWriter()throws Exception
	{
		return pw;
	}
	//设置响应的状态行 参数为String类型
	public void setStatusLine(String statusCode)
	{
		String str=StatusCodeUtils.getStatusCodeValue(statusCode);
		//System.out.println(str+"------"+str.length());
		sbuffer.append("HTTP/1.1 "+statusCode+" "+str);
		setCRLF();
	}
	//设置响应的状态行 参数为int类型
	public void setStatusLine(int statusCode)
	{
		setStatusLine(statusCode+"");//将int类型转化为String类型
	}
	//设置响应消息报头
	public void setResponseHeader(String hName,String hValue)
	{
		sbuffer.append(hName+": "+hValue);
		setCRLF();
	}
	//设置响应消息报头中Content-Type属性
	public void setContentType(String contentType)
	{
		setResponseHeader("Content-Type",contentType);
	}
	//设置响应消息报头中Content-Type属性 并且同时设置编码
	public void setContentType(String contentType,String charsetName)
	{//text/html;charset=utf-8
		setContentType(";charset= "+charsetName);
	}
	//设置CRLF 回车换行 \r\n
	public void setCRLF()
	{
		sbuffer.append("\r\n");
	}
	//把设置好的响应状态行、响应消息报头、固定空行这三部分写给浏览器
	public void printResponseHeader()
	{
		//设置setResponseLine,setResponseHeader,setResponseType
		String res=sbuffer.toString();
		pw.print(res);
		pw.flush();
	}
	//把响应正文写给浏览器
	public void printResponseContent(String requestPath)
	{
		//响应正文
		String getPath= requestPath;//客户请求的地址
		String webHome=(new ConfigUtils()).getConfigValue("rootPath");	
		System.out.println("配置文件中目录:"+webHome);//输出从配置文件中获取的地址
		file=new File(webHome+getPath);
		if(file.exists())//如果文件存在就执行
		{
		try {
			fis=new FileInputStream(file);
			byte[] buf=new byte[1024];
			int len=-1;
			while((len=fis.read(buf))!=-1)
			{
				//String str=buf.toString();
				//bw.write(str);//字符流写过去是一个地址,因为写过去之后需要浏览器解析,如果是图片或者其他(图片或视频是字节流)的该怎么解析呢?
				//System.out.println(str);
				os.write(buf, 0, len);
			}
			bw.flush();
			os.flush();//os要不要关???
		} catch (IOException e) {
			e.printStackTrace();
		}finally
		{
			try {
				if(bw!=null)
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		}
	}
}

在Eclipse中写完以上代码我们会发现,其中有多处错误信息,其原因是我们没有进行创建以上代码所要求的类,现在我们进行创建,其使用方法请参见:java.util 类 Properties    ,使用参考中的方法,我们能够进行对所需要的信息进行配置,在以上代码中使用的地方有两处,分别是【注意:这样做的好处是增减了项目的灵活性,用户能够在不查看代码的情况下随时更改配置文件等一些文件的信息,】:

(1)设置状态行处

//设置响应的状态行 参数为String类型
	public void setStatusLine(String statusCode)
	{
		String str=StatusCodeUtils.getStatusCodeValue(statusCode);
		//System.out.println(str+"------"+str.length());
		sbuffer.append("HTTP/1.1 "+statusCode+" "+str);
		setCRLF();
	}

其中StatusCodeUtils类创建如下所示,而对于status_code.properties文件存放在下载的准备文件中的/webservlet/project/中,直接复制到项目中即可:

package com.sample.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class StatusCodeUtils {
	private static Properties p;
	static 
	{
		InputStream in=null;
		p=new Properties();
		try {
			//读了xx.properties文件
			in=StatusCodeUtils.class.getResourceAsStream("status_code.properties");
			//放置到p中,即放properties文件中的key,value
			p.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally
		{
			if(in!=null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}
	public static String getStatusCodeValue(String status)
	{ 
		return p.getProperty(status);
	}
	public static String getStatusCodeValue(int status)
	{ 
		return getStatusCodeValue(status+"");//没有空格
	}
	/*public static void main(String[] args) {//输出测试
	//Properties p=new Properties();
	// p.setProperty("rootPath","ddd");
	//System.out.println(p.get("rootPath"));
		System.out.println(getStatusCodeValue("304"));
		System.out.println(getStatusCodeValue("200"));
	}*/
}

(2)响应正文处:

//响应正文
		String getPath= requestPath;//客户请求的地址
		String webHome=(new ConfigUtils()).getConfigValue("rootPath");	
		System.out.println("配置文件中目录:"+webHome);//输出从配置文件中获取的地址
		file=new File(webHome+getPath);

 在响应正文中使用了ConfigUtils类进行了项目路径的获取,代码如下所示,对于config.properties(注意:此文件中文件路径应该注意,我使用的是Linux系统,文件结构是/home/***,而对于windows系统,目录结构为:"C://webapps/*****,最好在地址栏复制地址,写到配置中")文件也在准备文件中,请自行下载,然后复制到项目中:就是下面这个东西,路径配置合适,然后你就可以将自己的项目放在webapps目录下,让自己的电脑作为服务器供其他人访问自己的网站了

ConfigUtils路径配置类,用于获取项目文件目录位置

package com.sample.utils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
public class ConfigUtils {
	private static Properties p;
	static 
	{
		InputStream in=null;
		OutputStream on=null;
		p=new Properties();
		try {
			//读了xx.properties文件
			in=ConfigUtils.class.getResourceAsStream("config.properties");
			//放置到p中,即放properties文件中的key,value
			p.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally
		{
			if(in!=null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}
	public static String getConfigValue(String config)
	{ 
		return p.getProperty(config);
	}
	public static void main(String[] args) {//输出测试
	//	Properties p=new Properties();
	//	p.setProperty("rootPath","ddd");
	//	System.out.println(p.get("rootPath"));
		System.out.println(getConfigValue("rootPath"));
	}
}

到此为止,我们已经实现了服务器的主要任务,接受请求和处理请求,下面我们进行测试:

写一个测试类如下:

package com.sample.http;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class ServerTest {
	public static void main(String[] args) {
		//声明变量
 ServerSocket ss=null;
 Socket s=null;
 boolean flag=true;
 try {
 	int port=10002;
 	System.out.println("Server Port:"+port);
					ss=new ServerSocket(port);
					//while(flag)
					{
						//接受客户端发送过来的Socket
						s=ss.accept();
						HttpRequestImpl request=new HttpRequestImpl(s);							
						//	用于测试收到的信息
						System.out.println("获取的路径:"+request.getRequestPath());
						System.out.println("获取的:"+request.getProtocol());
						System.out.println("获取的:"+request.getRequestMethod());
						System.out.println(request.getParameter("name"));
						System.out.println(request.getParameter("id"));					
						Map m=request.getRequestHeader();
						Set> set=m.entrySet();
						Iterator it=set.iterator();
						while(it.hasNext())
						{
							Entry entry=(Entry )it.next();
							System.out.println(entry.getKey()+"----"+entry.getValue());
						}
					 //写响应给浏览器
						/*
						 * 封装:
						 * */
						//输出流
						HttpResponseImpl respOnse=new HttpResponseImpl(s);												
						response.setStatusLine(200);
						response.setContentType("text/html");
						response.printResponseHeader();
						response.setCRLF();
						response.printResponseHeader();
						response.printResponseContent(request.getRequestPath());
						//用于输出信息
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
	}
}

在浏览器中输入地址回车:http://127.0.0.1:10002/test.html?id=1212&name=suguniang ,能够看到浏览器解析后的界面,当其他电脑访问时(其他电脑指的是同一个域内的),只要将127.0.0.1修改为本地的ip地址即可

此时控制台上也输出相应的信息:

web服务器项目中静态请求和动态请求处理:https://www.jb51.net/article/191243.htm

到此这篇关于浅谈web服务器项目中request请求和response的相关响应处理的文章就介绍到这了,更多相关web服务器 request请求 response响应处理内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
  • 本文介绍了在Ubuntu 11.10 x64环境下安装Android开发环境的步骤,并提供了解决常见问题的方法。其中包括安装Eclipse的ADT插件、解决缺少GEF插件的问题以及解决无法找到'userdata.img'文件的问题。此外,还提供了相关插件和系统镜像的下载链接。 ... [详细]
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
  • android ... [详细]
author-avatar
fyy1784502
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有