文字大小:

xlang webserver 用法详解

未分类2025-03-23 17:51:54




概述:

    在 xlang 的 webserver 开发中,具有以下和 javaWeb 类似的三大组件

 

  1. HttpServer Http服务器容器主类
  2. Website  站点主类
  3. HttpServlet  用于处理Http 和 Websocket 请求的接口

 

一. HttpServer

      HttpServer 类负责整个服务器的运行,类声明如下:

 

class HttpServer{
    public static const int DEFAULT_MODEL;
    public static const int SELECT_MODEL;
    public static const int POLL_MODEL;
    public static const int EPOLL_MODEL;
    public static const int ALLOW_UPGRADE;
    
    public HttpServer();
    public bool setMaxConnection(int max);
    public bool setConnectionTimeout(int millisec);
    public bool setIpConnectionLimit(int limit);
    public bool setThreadPoolSize(int size);
    public int addWebsite(String domain, Website website);
    public void quiesce();
    public void close();
    public bool stop();
    public bool isRunning();
    public bool start(int flags, int port);
    public bool configHttps(bool enable, String certContent, String keyContent);
};

 

成员释义
名称 类型 说明
DEFAULT_MODEL 常量 指示以默认的模式运行(不同平台默认可能不同,一般是 select 模式)
SELECT_MODEL 常量 指示服务器以 select 模式运行
POLL_MODEL 常量 指示服务器以 poll 模式运行(linux)
EPOLL_MODEL 常量 指示服务器以 epoll 模式运行(linux)
ALLOW_UPGRADE 常量 启用websocket, 指示服务器可以将 http 连接升级为 websocket连接
HttpServer() 构造方法 创建一个 HttpServer 实例
bool setMaxConnection(int max) 方法 限制最大连接数为max
boolsetConnectionTimeout(int millisec) 方法 连接超时时间(客户端连接后超过时间未传输数据将被断开)
boolsetIpConnectionLimit(int limit) 方法 限制单IP的最大并发连接数
boolsetThreadPoolSize(int size) 方法 设置工作线程数量
int addWebsite(String domain, Website website) 方法 向服务器容器中添加站点,
void quiesce() 方法 允许现有连接继续,但不再接受新
bool stop() 方法 停止服务
void close() 方法 关闭服务器,并清理资源
bool isRunning() 方法 返回值指示服务器是否在运行中
bool start(int flags, int port) 方法 在端口 port 上启动服务器, flags 参数为表中常量
bool configHttps(bool enable, String certContent, String keyContent) 方法 已弃用,不再生效

 

 

二. Website

    Website 负责站点业务,类声明如下:

class Website{
    public Website();
    public bool registryServlet(HttpServlet servlet);
    public void setRootDirectory(String path);
    public String getRootDirectory();
    public String getTempDirectory();
    public void setEnabled(bool on);
    public void setTempDirectory(String path);
    public void configCacher(bool on, int singlemax, long totalmax);
    public void configSession(int sessionMax, int timeout);
    public void clearCacher();
    public void clearSession();
    public bool setHeader(String pattern, String key, String value);
    public bool setFooter(String pattern, String key, String value);
    public bool addDefaultPage(String indexname);
    public bool addMimeType(String pattern, String key);
    public String mapServerPath(String local, String host);
    public String mapLocalPath(String url, String host);
    public bool removeCache(String localpath);
};

 

成员释义
名称 类型 说明
Website 方法 创建 WebSite 实例
registryServlet 方法 注册 Servlet
setRootDirectory 方法 设置网站根目录
getRootDirectory 方法 获取网站根目录
getTempDirectory 方法 获取临时目录
setEnabled(bool on) 方法 启用或禁用网站
setTempDirectory(String path) 方法 设置临时目录
configCacher(bool on, int singlemax, long totalmax) 方法 设置缓存,主要指静态文件缓存,on 指示启用或禁用,singlemax 指适用缓存的单个文件最大上限,totalmax是总的缓存最大上限
configSession(int sessionMax, int timeout) 方法 设置session的最大数量和超时限制(毫秒)
clearCacher() 方法 清理静态文件缓存
clearSession() 方法 清理所有session
setHeader(String pattern, String key, String value) 方法 设置对匹配 pattern 规则的 uri 响应中添加 Header 
setFooter(String pattern, String key, String value) 方法 设置对匹配 pattern 规则的uri 响应中添加 Footer
bool addDefaultPage(String indexname) 方法 指定索引页
addMimeType(String ext, String key) 方法 设置指定扩展名的mimetype
String mapServerPath(String local, String host) 方法 将服务器上的本地路径转换为网站路径
String mapLocalPath(String url, String host) 方法 将网站路径转换为服务器上的本地路径
removeCache(String localpath) 方法 移除指定静态文件缓存

 

三. HttpServlet

HttpServlet 负责处理指定 uri 的业务, 接口声明如下

class HttpServlet{
    static const int FLAG_POSTSTREAM;
    static const int FLAG_LOGERROR;
    static const int FLAG_SERVLET;
    static const int FLAG_WEBSOCKETLET;

    HttpServlet(int flags, String pattern);
    HttpServlet(int httpcode);
    void doGet(HttpServletRequest request, HttpServletResponse resp);
    void doPost(HttpServletRequest request, HttpServletResponse resp);
    void onOpen(WebSocketSession  session);
    void onClose(WebSocketSession session, String reason);
    void onError(WebSocketSession session);
    void onMessage(WebSocketSession session, String message);
    void onBinary(WebSocketSession session, byte [] message);
};

 

常量说明:

  • FLAG_POSTSTREAM
    • 指示该 uri 的 post 数据流操作全部由手动接管
    • 注意: 设置此 flags 后,post的 form 以及 multipart 数据将不会自动解析,需要手动编码处理。
  • FLAG_LOGERROR
    • 指示将异常信息打印到页面
  • FLAG_SERVLET
    • 指示该接口响应 http 请求
  • FLAG_WEBSOCKETLET
    • 指示该请求响应 websocket 请求

 

构造:

  • HttpServlet(int flags, String pattern);
    • 创建实例, flags 使用上面常量组合, pattern 指示处理哪些 uri 请求,该参数为正则表达式, 所有能被此表达式匹配的 uri 均交由此接口处理。
  • HttpServlet(int httpcode);
    • 创建实例, 参数指示了在发生 Http 哪种错误(代码)时,将交由此接口进行处理,比如 404。

 

Http 请求处理:

  • void doGet(HttpServletRequest request, HttpServletResponse resp);
    • 响应 get 请求
  • void doPost(HttpServletRequest request, HttpServletResponse resp);
    • 响应 post请求

 

WebSocket 请求处理:

  • void onOpen(WebSocketSession  session);
    • 响应 WebSocket 的连接事件
  • void onClose(WebSocketSession session, String reason);
    • 响应 Websoket 关闭事件
  • void onError(WebSocketSession session);
    • 响应 WebSocket 错误事件
  • void onMessage(WebSocketSession session, String message);
    • 响应 WebSocket 文本消息事件
  • void onBinary(WebSocketSession session, byte [] message);
    • 响应 WebSocket 数据流事件
    •  

*注意事项

  • 构造参数中 若 flags 为 0 时, 默认为 FLAG_SERVLET。
  •  
  • 当未使用 FLAG_POSTSTREAM 标志时, 接口将自动处理 Content-Type formmultipart 的数据,并将结果存入 request 中,使用 getParam() 进行提取,而Content-Type 为此两种以外的类型时,则不会处理,需要通过接口上对应方法的HttpServletRequest参数的成员方法 readPostData 进行读取。
  •  
  • 当使用了 FLAG_POSTSTREAM 标志, 该接口上的所有 post 数据将不会被自动处理, 需要通过接口上对应方法的HttpServletRequest参数的成员方法 readPostData 进行读取并手动处理。
  •  
  • 当使用了 FLAG_POSTSTREAM 标志时,用户需要自行编写处理逻辑, 也可以使用HttpServletRequest 类提供的处理 post 数据的内置方法(仅用于解析 Content-Type 为 form 和 multipart 的数据流), 用法如下:
  •  
  • 对应要处理的 HttpServletRequest  request 需要通过 setOnParseListener 设置解析回调:
  • _request.setOnParseListener(new RequestParseListener(){
        void onItemParsed(String key, String filename, String contentType, String transferEncoding, byte [] data, long dateInOffset)override{
            // todo 添加解析结果
        }
    });
  •  
  • 然后通过循环读取post流并调用解析方法,解析结果将会通过上述回调函数送达:
  • byte [] data = new byte [1024];
    int readed = 0;
    while (0 < (readed = _request.readPostData(data, 0, data.length))){
        _request.parsePostedData(data, 0, readed);
    }

 

HttpServletRequest 类

class HttpServletRequest{
    public InetAddress getClientAddress(); 
    public String getHeader(String name); 
    public String getCookie(String key);
    public Object getSession(String key);
    public void setSession(String key, Object value);
    public String getParam(String key);
    public ServletRequestItem [] getParameter(String key);
    public String [] getParams(String key);
    public String [] getParamKeys();
    public String getArg(String key);
    public String [] getArgs(String key);
    public String [] getArgKeys();
    public String [] getLocalFilepath(String key);
    public String [] getFileName(String key);
    public Website getWebsite();
    public String getUrl();
    public String getHost();
    public String getMethod();
    public void setUserData(Object data);
    public Object getUserData();
    public String getServerName();
    public int getServerPort();
    public String getQueryString();
    public String getScheme();
    public int readPostData(byte [] data, int offset, int len);
    public bool setOnParseListener(RequestParseListener listener);
    public bool parsePostedData(byte [] data, int offset, int length);
};

 

 

名称 说明
InetAddress getClientAddress() 获取客户端地址
String getHeader(String name) 获取请求头参数
String getCookie(String key) 获取 cookie
Object getSession(String key) 获取session对象
void setSession(String key, Object value) 设置session对象
String getParam(String key) 获取 post 数据中的参数值
ServletRequestItem [] getParameter(String key) 获取 post 数据中的参数对象
String [] getParams(String key) 获取 post 数据中的参数,可获取多个参数
String [] getParamKeys() 获取 post 数据中所有的参数 key
String getArg(String key) 获取 url 中的参数值
String [] getArgs(String key) 获取 url 数据中的参数,可获取多个参数
String [] getArgKeys() 获取 url 数据中所有的参数 key
String [] getLocalFilepath(String key) 获取 post 数据中上传的文件路径
String [] getFileName(String key) 获取 post 数据中上传的文件名
Website getWebsite() 获取 Website 对象
String getUrl() 获取参数 url 
String getHost() 获取 host 名称
String getMethod(); 获取请求方法
void setUserData(Object data); 设置用户数据, 与HttpServletRequest 对象生命周期绑定
Object getUserData() 获取设置的用户数据
String getServerName() 同 getHost
int getServerPort() 获取服务器端口
String getQueryString() 获取url参数字符串
String getScheme() 获取协议标识, * 注意:此方法可能获取不正确, 建议配合 nginx 前端获取 nginx 的转发头部字段。
int readPostData(byte [] data, int offset, int len) 读取post数据流
bool setOnParseListener(RequestParseListener listener) 设置 post 数据流解析结果回调
bool parsePostedData(byte [] data, int offset, int length); 解析 post 数据流, * 注意:请阅读上一节中的注意事项

 

HttpServletResponse 类

 

class HttpServletResponse{
    public void print(String text);
    public void write(byte []  buffer, int pos, int length);
    public void setOutputStream(Stream stream);
    public void setResponseCode(int code);
    public void setCookie(String key, String value);
    public void addHeader(String key, String value);
    public void setHeader(String key, String value);
    public void setContentType(String sType);
};

 

名称 说明
void print(String text) 输出字符串
void write(byte []  buffer, int pos, int length) 向响应流写入数据
void setOutputStream(Stream stream) 向响应流插入数据流
void setResponseCode(int code) 设置 HTTP 响应代码
void setCookie(String key, String value) 设置 cookie 数据
void addHeader(String key, String value) 添加响应头
void setHeader(String key, String value) 设置响应头, * 注意:将删除key对应的旧响应头数据
void setContentType(String sType) 设置ContentType

 

*注意事项

   print, write,  setOutputStream 均为输出响应数据,使用 print 和 write 输出的数据流会被短暂的缓存在内存中,待doGet 或者doPost 方法执行完毕后才会发送给客户端,而setOutputStream 设置的输出流则会在doGet 或者doPost方法调用结束后被回调读取流并即时发送给客户端,因此,数据量较少时使用 print, write,数据量较大时应使用 setOutputStream ,以免内存占用过高导致问题。

当  print, write,  setOutputStream 均有数据输出时,优先发送 print, write (按照两者调用顺序) 写入的数据,后处理 setOutputStream 的数据流.

 


Xlang Script Page 

xlang 动态页面,是为了兼容旧的动态页面技术,在 xsp 文件中 使用 <% %> 包裹起来的块为 xlang 代码,会被编译器进行编译。

使用 <xsp:include page="other.xsp" /> 包含的其他页面会在编译时被插入此代码的位置并进行编译。

使用 <%@PageFlags = FLAGS %> 改变页面默认行为,FLAGS 为HttpServlet 中的常量 FLAGS ,如将错误信息打印到页面,则使用 <%@ PageFlags = FLAG_SERVLET | FLAG_LOGERROR %> , 若不使用代码指定,则默认只有 FLAG_SERVLET 。

 

xsp 中的可用变量为 session 或者 request (两者等价,同为 HttpServletRequest 类型),用于处理请求,response 或者 out  (两者等价,同为 HttpServletResponse  类型)用于处理响应, WebSocket 请求在 xsp 页面中不可被处理,只能通过 Servlet 响应。

 

示例代码

//xlang 
package System{
	public class out{
		public static int println(String text){
			return _system_.consoleWrite(text + "\n");
		}
		public static int print(String text){
			return _system_.consoleWrite(text);
		}
	};
};


using { System; };


class XServlet : HttpServlet{
	public XServlet(){
		/** 
		@super 调用基类构造
		@XServlet.FLAG_LOGERROR 将错误打印到页面, 
		@url "/action/*" 正则表达式, 匹配的url请求将被此servlet接管.
		*/
		super(XServlet.FLAG_LOGERROR, "/api/*");
    }
        
	void doGet(HttpServletRequest request, HttpServletResponse response)override{
    
		//获取参数
		String [] args = request.getArgs("name");
        
		response.print("<html><head><meta charset=\"utf-8\" /></head><body>");

        if (args != nilptr){
			// 设置跨域
			/*response.addHeader("Access-Control-Allow-Origin", "*");
			response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Accept");
			response.addHeader("Access-Control-Allow-Methods", "HEAD,GET,POST,PUT,DELETE,OPTIONS");*/
			response.print("<b style=\"font-size:40px;\">Hello " + args[0] + "!</b>"); 
            response.print(" <br/>Welcome to xlang Webserver"); 
        }else{
			response.print("<b style=\"font-size:40px;\">Welcome to xlang Webserver!</b>"); 
        }
        response.print("</body></html>");
        
    }
    
	void doPost(HttpServletRequest request, HttpServletResponse response)override{
		doGet(request, response);
    }
    
};


int main(String [] args){
	/** #################################################################################*/
    /** 创建web站点*/
    Website wb = new Website();
    
    /** 设置站点的静态文件目录为工作目录下的wwwroot文件夹*/
    wb.setRootDirectory(_system_.getWorkDirector().appendPath("wwwroot"));
    
    /** 设置站点的临时目录为temp, 用于网站缓存上传的数据流
		注意:处理了onPostStream的servlet中不会保存临时文件,将回调onPostStream
	*/
    wb.setTempDirectory("temp");
    
    /** 开启设置静态文件缓存, 单个文件大小上限为1M, 整个网站缓存上限为100M*/
    wb.configCacher(true,1024*1024,100*1024*1024);
    
    /** 注册一个servlet处理动态事务*/
    wb.registryServlet(new XServlet()); 
    
    /** 设置站点的默认首页, 多个用分号分割*/
    wb.addDefaultPage("index.html");
    
    /** #################################################################################*/
    /** 创建http服务器*/
	HttpServer server = new HttpServer();
    
    /** 设置服务器的线程池大小为 4个*/
    server.setThreadPoolSize(4);
    
    /** 将站点添加到服务器中,参数1为IP或者域名,多个用分号分割*/
    server.addWebsite("*;127.0.0.1;localhost", wb);
    
    /** 开启服务器, 模式为默认模式,可选为POLL EPOLL SELECT, 端口8889*/
    if (server.start(HttpServer.DEFAULT_MODEL,8889)){

		/** #################################################################################*/
		System.out.println("start server success!\nopen URL with Webbrowser:\nhttp://localhost:8889/\nhttp://localhost:8889/api/?name=xlanguser\nhttp://localhost:8889/api/");
	    
		Thread.sleep(-1);
	}else{

		/** #################################################################################*/
		System.out.println("start server filed! please check port(8889) occupancy!");
	    
		Thread.sleep(3000);
	}

	return 0;
}

 






上一篇:tomcat 服务器问题排查及优化下一篇:xlang加解密算法支持说明

评论

写评论

点击刷新