自定义简单的(tomcat)web服务器
自从JSP发布之后,推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器,当然同时也支持Servlet, 这样Tomcat就诞生了。Tomcat是jakarta项目中的一个重要的子项目,其被JavaWorld杂志的编辑选为2001年度最具创新的java产品,同时它又是sun公司官方推荐的servlet和jsp容器,因此其越来越多的受到软件公司和开发人员的喜爱。servlet和jsp的最新规范都可以在tomcat的新版本中得到实现。其次,Tomcat是完全免费的软件,任何人都可以从互联网上自由地下载。Tomcat与Apache的组合相当完美。
当然这次我自定义的tomcat是很简单的,只解析出普通的html页面进行响应然后回送的是字符串到浏览器,其他的css什么的自然是不不支持的,一个基于Java的web服务器用到的两个重要类:java.net.Socket和java.net.ServerSock,当然通信用的是http协议。
好的,首先我们先新建一个tomcatServer入口类,这个类自然就是用serverSocket进行对socket的连接进行监听,然后再在线程中操作与浏览器的请求和响应:
- <span style="font-size:18px;">import java.io.IOException;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class TomcatServer {
- /**
- * @param args
- *
- * tomcatserver一有客户端上来就监听
- * @throws IOException
- */
- public static void main(String[] args) {
- int port=Integer.parseInt((String)WebProperties.getInstance().get("port"));
- ServerSocket ss=null;
- try {
- ss = new ServerSocket(port);
- } catch (IOException e) {
- Utils.printException(e);
- }
- System.out.println(Utils.formatDate()+"\t服务器启动,监听"+ss.getLocalPort()+"端口");
- while(true){
- Socket s=null;
- try {
- s=ss.accept();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- Utils.printException(e);
- }
- System.out.println("客户端"+s.getRemoteSocketAddress()+"登陆上了服务器");
- //这是一个连接会话任务类,实现Runnable接口,网络操作需要启用线程
- //在会话任务类中
- HttpSessionTask hst=new HttpSessionTask(s);
- new Thread(hst).start();
- }
- }
- }</span>
浏览器此时是客户端,我们监听了一个端口,然后只要有客户端连接上来我们就要在HttpSession中对浏览器的请求做处理了,在这里我们要建一个配置文件用来定义资源文件的位置和端口号,这样就可以容易修改这些配置项了:
- path:c:\\
- defaultpage=index.html
- port=10000
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
- //要求单例
- public class WebProperties extends Properties {
- private static WebProperties myProperties;
- private WebProperties() {
- //在这里完成读取db.properties文件
- InputStream iis=WebProperties.class.getClassLoader().getResourceAsStream( "web.properties");
- try {
- this.load( iis );
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- //多个客户端上来时,防止多线程
- public synchronized static WebProperties getInstance() {
- if( myProperties==null){
- myProperties=new WebProperties();
- }
- return myProperties;
- }
- }
HttpServletRequest类要做的是解析浏览器发来的http协议拿到请求头里的资源地址,然后HttpServletResponse得到资源地址后解析资源进行拼接协议响应头回送给客户端,这样一次请求到响应浏览器就可以显示出资源地址的内容了。
自定义的HttpServletRequest类:
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * 这个请求类对浏览器发送的协议进行解析,得到资源地址(这里只考虑get方法,参数拚在请求头中,这里解析出来后不做处理)
- * @author Administrator
- *
- */
- public class HttpServletRequest {
- private String uri;
- private String method;
- private String protocolVersion;
- private Map<String,String> parameter=new HashMap<String,String>();
- private InputStream iis;
- //这个构造函数的iis是从socket中得到的输入流
- public HttpServletRequest( InputStream iis) throws IOException{
- this.iis=iis;
- parse();
- }
- //解析协议的方法 GET /company/index.html HTTP/1.1
- private void parse() throws IOException {
- BufferedReader br=new BufferedReader(new InputStreamReader(iis));
- String line=null;
- int i=0;
- if((line=br.readLine())!=null){
- if(i==0){
- parseCommandLine(line);
- }
- i++;
- }
- }
- private void parseCommandLine(String line) {
- if(line!=null&&!"".equals(line)){
- String [] strs=line.split(" ");
- method=strs[0];
- protocolVersion=strs[2];
- if("GET".equals(method)){
- doGet(strs[1]);
- }
- }
- }
- private void doGet(String str) {
- //解析是否有参数
- if(str.contains("?")){
- String[] strs=str.split("?");
- uri=strs[0];
- String[] ps=strs[1].split("&");
- for(String s:ps){
- String[] pp=s.split("=");
- parameter.put(pp[0], pp[1]);
- }
- }else{
- uri=str;
- }
- }
- //get方法参数的类
- public String getParameter(String key) {
- String value=parameter.get(key);
- if(!value.equals("")||!(value==null)){
- return value;
- }else{
- return null;
- }
- }
- public String getUri() {
- return uri;
- }
- public String getMethod() {
- return method;
- }
- public String getProtocolVersion() {
- return protocolVersion;
- }
- }
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- /**
- * 服务器响应类,这个类得到资源地址后对文件进行解析(这里只当字符全部输出),
- * 然后拼接响应头给浏览器浏览器接收后显示信息
- * @author Administrator
- *
- */
- public class HttpServletResponse {
- private OutputStream oos;
- public HttpServletResponse(OutputStream oos){
- this.oos=oos;
- }
- public void redirect(String pageUrl){
- //输出流到客户端
- byte[] bs=new byte[1024];
- FileInputStream fis=null;
- File f=new File(pageUrl);
- if(!f.exists()){
- out404();
- return;
- }
- try {
- fis=new FileInputStream(f);
- StringBuffer sb=new StringBuffer();
- int length=-1;
- while((length=fis.read(bs,0,bs.length))!=-1){
- sb.append(new String(bs,0,length,"gbk"));
- }
- //正常的时候响应的协议
- String responseHead="HTTP/1.1 200 OK\r\nContent-Type: text/html;charset=gbk\r\nContent-Length: "+sb.toString().getBytes().length+"\r\n\r\n";
- out(responseHead,sb.toString());
- } catch (Exception e) {
- // TODO Auto-generated catch block
- Utils.printException(e);
- }
- }
- private void out404() {
- String responseBody="<h1>没有页面</h1>";
- //TODO:
- String responseHead="HTTP/1.1 404 Not Found\r\nContent-Type: text/html;charset=utf-8\r\nContent=Length: "
- +responseBody.getBytes().length+"\r\n\r\n";
- try{
- out(responseBody,responseHead);
- }catch(Exception e){
- Utils.printException(e);
- }
- }
- private void out(String responseHead,String responseBody) throws IOException{
- oos.write(responseHead.getBytes());
- oos.write(responseBody.getBytes());
- oos.flush();
- }
- }
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.Socket;
- /**
- *
- * @author Administrator
- *获取输入流,得到客户端传来的协议
- *将协议解析一个HttpServerletRequest对象(http://localhost/compay/index.html)
- *协议 GET /company/index.html HTTP/1.1
- */
- public class HttpSessionTask implements Runnable {
- private Socket s;
- private InputStream iis;
- private OutputStream oos;
- private boolean flag=true;
- public HttpSessionTask(Socket s){
- this.s=s;
- try {
- iis=s.getInputStream();
- oos=s.getOutputStream();
- } catch (IOException e) {
- Utils.printException(e);
- flag=false;
- }
- }
- //因为http协议是一个无状态的,请求完后回应一次断开
- public void run() {
- if(flag==false){
- return;
- }
- try {
- //创建requset对象解析http协议的请求部分 GET /company/index.html HTTP/1.1
- //得到资源地址 /kaw/index.html
- //通过配置文件找到path c:\kaw\index.html
- //再创建response对象,调用redirect(path);
- HttpServletRequest request=new HttpServletRequest(iis);
- String uri=request.getUri();
- String filepath=WebProperties.getInstance().getProperty("path")+uri;
- HttpServletResponse response=new HttpServletResponse(oos);
- response.redirect(filepath);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- Utils.printException(e);
- out500(e);
- }finally{
- if(this.s!=null){
- try {
- s.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- private void out500(Exception e) {
- //拼接协议输出错误信息
- //略
- }
- }
用浏览器访问地址:
网页就被读取出来了,当然这是个很简单的服务器,也只能操作普通文本,后续的学习希望可以深入服务器的学习,多多交流!
相关推荐
- web简单题的思路
- Linux下的Tomcat7 web项目一直404
- CentOS与Ubuntu - 为您的Web服务器选择谁
- WEB12:Eclipse与Tomcat的绑定以及发布项目
- 网络安全学习篇36_第二阶段_简单介绍Java Web框架之Tomcat服务、Nginx负载均衡、Linux包过滤防火墙IPtables、NAT网络地址转换
- 了不起的Node.js: 将JavaScript进行到底(Web开发首选,实时,跨多服务器,高并发)...
- 可用于企业的 7 个最佳开源 Web 服务器
- web_day33_tomcat服务器
- Nginx + Membase(memcache)+ tomcat配置共享的session web服务集群详解
- 【Java】基于敏捷开发的简易Web服务器(附下载)
- AngularJS 是否能满足企业应用的安全需求
- 2021年CFA全面机考!20年12月CFA考试是最后一次绝版笔考!