Tomcat服务器和Web开发介绍

Tomcat服务器和Web开发介绍

一、开启Web开发

什么是web开发

WEB,即网页的意思,它用于表示Internet主机上供外界访问的资源。
Internet上供外界访问的Web资源分为:
静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。

问题:静态web资源开发技术和动态web资源开发技术分别有哪些?

在Java中,动态web资源开发技术统称为Javaweb,我们课程的重点也是教大家如何使用Java技术开发动态的web资源,即动态web页面。

二、Web容器_Tomcat

学习web开发,需要先安装一台web服务器,然后再在web服务器中开发相应的web资源,供用户使用浏览器访问。

目前有一款免费且应用广泛的web容器Tomcat,是我们学习的首选该服务器支持JSP以及Servlet规范。启动成功后,通过浏览器访问效果如下:
JSP:html+java
Servlet:技术

在这里插入图片描述

三、常见的启动问题及tomcat目录介绍

常见启动问题
使用startup.bat文件启动Tomcat
Catalina_home环境变量
Java_home环境变量

TOMCAT的启动需要一个环境变量JAVA_HOME

端口占用问题(更改默认端口)
其他程序占用了这个端口,修改这个端口
解决办法:
Conf/server.xml 搜8080 替换

Tomcat的目录层次
Bin:存放二进制文件,启动和关闭tomcat
Conf:配置文件,配置端口,配置数据库连接池,web.xml
Lib:jar文件,支撑tomcat运行
Logs:存放tomcat运行日志信息
Temp:临时目录,给tomcat自己用的
Webapps:存放我们要部署的项目
Work:工作目录,区别(jsp)

四、JavaWeb应用程序

WEB应用程序指供浏览器访问的程序,通常也简称为web应用。
一个web应用由多个静态web资源和动态web资源组成,如:
html、css、js文件
Jsp文件、java程序、支持jar包、相关的配置文件等等

Web应用开发好后,若想供外界访问,需要把web应用所在目录交给web服务器管理,这个过程称之为虚似目录的映射。

五、Web应用的组成结构

开发web应用时,不同类型的文件有严格的存放规则,否则不仅可能会使web应用无法访问,还会导致web服务器启动报错。下面我们使用eclipse来开发我们的第一个web应用程序

六、Tomcat的体系结构

Server代表整个Servlet容器组件,是最顶层元素,包含多个Service元素。

Service包含一个Engine元素以及多个Connector元素

Connector元素代表和客户端程序交互的组件,负责接收客户端请求和向客户端返回响应。

Engine中可以包含多个Host,Host表示一个虚拟主机,他可以包含多个web应用

Context代表运行在虚拟主机上的单个web应用

七、什么是Servlet

Servlet是sun公司提供的一门用于开发动态web资源的技术,可以实现和客户端的交互,接收客户端请求和给客户端返回响应。
Sun公司在其API中提供了一个servlet接口,用户若想开发一个动态web资源需要完成以下2个步骤:
编写一个Java类,实现servlet接口。
把开发好的Java类部署到web服务器中。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * 1.创建MyServlet类,继承HttpServlet(前提:先导入servlet_api.jar)
 * 2.重写service()
 * 3.在web.xml配置Servlet信息
 */
public class MyServlet01 extends HttpServlet {

    /**
     * 客户端发送请求到本Servlet中,Tomcat服务器就会调用service方法,并传进来请求对象和响应对象
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //设置编码格式
        req.setCharacterEncoding("UTF-8");//设置请求编码格式
        resp.setContentType("text/html;charset=UTF-8");//设置响应编码格式

        //获取请求中的数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println("接收到来自客户端的请求了... " + username + " -- " + password);

        //通过响应返回数据
        resp.getWriter().println("<h1>把微笑带回家</h1>");

    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>欢迎页面</h1>

    <a href="aaa?username=ggc&password=123123">MyServlet发送请求</a>
    <br>

    <input type="button" value="向MyServlet02发送请求" onclick="fun01()"/>
    <br>
    <a href="register.html">跳转到注册页面</a>

    <script type="text/javascript">
        function fun01() {
            location ="bbb?username=ggc&password=111222";
        }
    </script>


</body>
</html>

优化代码

/**
 * 1.创建MyServlet类,继承HttpServlet(前提:先导入servlet_api.jar)
 * 2.重写doGet()和doPost()
 * 3.在web.xml配置Servlet信息
 */
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyServlet02 extends HttpServlet {
    /**
     * 客户端发送Get请求到本Servlet中,Tomcat服务器就会调用doGet方法,并传进来请求对象和响应对象
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }
    /**
     * 客户端发送Post请求到本Servlet中,Tomcat服务器就会调用doPost方法,并传进来请求对象和响应对象
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //设置编码格式
        req.setCharacterEncoding("UTF-8");//设置请求编码格式
        resp.setContentType("text/html;charset=UTF-8");//设置响应编码格式

        //获取请求中的数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println("MyServlet02接收到来自客户端的请求了... "+ username + " -- " + password);

        //通过响应返回数据
        resp.getWriter().println("<h1>把微笑带回家</h1>");
    }
}

八、Servlet的实现类

Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法

第一步:创建一个类,继承HttpServlet,重写service方法
第二步:注册

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>注册页面</h1>

    <form action="ccc" method="post">

        账号:<input type="text" name="username"/><br>
        密码:<input type="password" name="password"/><br>
        性别:
        <input type="radio" name="sex" value="man" checked="checked"/><input type="radio" name="sex" value="woman"/><br>
        籍贯:
        <select id="province" name="province">
            <option value="sc">四川</option>
            <option value="hn">湖南</option>
            <option value="hb">湖北</option>
        </select><select id="city" name="city">
            <option value="cd">成都</option>
            <option value="nc">南充</option>
            <option value="yb">宜宾</option>
        </select><br>
        爱好:
        <input type="checkbox" name="hobbys" value="football"/>足球
        <input type="checkbox" name="hobbys" value="basketball"/>篮球
        <input type="checkbox" name="hobbys" value="shop"/>购物
        <br>

        <input type="submit" value="注册"/>
    </form>

    <script type="text/javascript">

        var province = document.getElementById("province");
        var city = document.getElementById("city");

        //改变事件
        province.onchange = function () {
            var v = this.value;
            if(v == "sc"){
                addCity(["成都","南充","宜宾"],["cd","nc","yb"]);
            }else if(v == "hn"){
                addCity(["长沙","娄底","怀化","益阳","永州"],["cs","ld","hh","yy","yz"]);
            }else if(v == "hb"){
                addCity(["武汉","仙桃","黄冈","孝感","十堰","咸宁","宜昌","恩施"],["wh","xt","hg","xg","sy","xn","yc","es"]);
            }
        }

        function addCity(cityArr,valueArr){

            //清空city下拉列表中的数据
            city.length = 0;

            for(var i = 0;i<cityArr.length;i++){
                var cityName = cityArr[i];
                var option = document.createElement("option");
                option.innerText = cityName;
                option.value = valueArr[i];
                city.appendChild(option);
            }
        }
    </script>
</body>
</html>
/**
 * 1.创建MyServlet类,继承HttpServlet(前提:先导入servlet_api.jar)
 * 2.重写doGet()和doPost()
 * 3.在web.xml配置Servlet信息
 */
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class MyServlet03 extends HttpServlet {
    /**
     * 客户端发送Get请求到本Servlet中,Tomcat服务器就会调用doGet方法,并传进来请求对象和响应对象
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }
    /**
     * 客户端发送Post请求到本Servlet中,Tomcat服务器就会调用doPost方法,并传进来请求对象和响应对象
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //设置编码格式
        req.setCharacterEncoding("UTF-8");//设置请求编码格式
        resp.setContentType("text/html;charset=UTF-8");//设置响应编码格式

        //获取请求中的数据集合
//        Map<String, String[]> parameterMap = req.getParameterMap();
//        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
//        for(Map.Entry<String, String[]> entry : entries){
//            System.out.println(entry.getKey() + " -- " + Arrays.toString(entry.getValue()));
//        }

        //获取请求中的数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String sex = req.getParameter("sex");
        String province = req.getParameter("province");
        String city = req.getParameter("city");
        String[] hobbys = req.getParameterValues("hobbys");
        System.out.println("MyServlet03接收到来自客户端的请求了... " + username + " -- " + password + " -- " + sex  + " -- " + province + " -- " + city + " -- " + Arrays.toString(hobbys));

        //通过响应返回数据
        resp.getWriter().println("<h1>把微笑带回家</h1>");
    }
}

九、解析过程

Tomcat在加载Web应用时,就会把相应的web.xml文件中的数据读入到内存中。因此当Tomcat在解析web请求的时候,需要参考web.xml文件时,实际上只需要从内存中读取相关数据就可以了,不需要再到文件系统中读取web.xml。

十、Servlet的运行过程

Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
1,Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则,执行第2步。
2,装载并创建该Servlet的一个实例对象。
3,调用Servlet实例对象的init()方法。
4,创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
5,WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

十一、Servlet的生命周期

Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
如果在元素中配置了一个元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。
用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的公共数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <a href="Servlet01">Servlet01发送请求</a>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <welcome-file-list>
        <welcome-file>welcome.html</welcome-file>
    </welcome-file-list>

    <!--<servlet>-->
        <!--<servlet-name>Servlet01</servlet-name>-->
        <!--<servlet-class>com.qf.servlet.Servlet01</servlet-class>-->
        <!--<init-param>-->
            <!--<param-name>code</param-name>-->
            <!--<param-value>UTF-8</param-value>-->
        <!--</init-param>-->
        <!--<load-on-startup>3</load-on-startup>-->
    <!--</servlet>-->
    <!--<servlet-mapping>-->
        <!--<servlet-name>Servlet01</servlet-name>-->
        <!--<url-pattern>/Servlet01</url-pattern>-->
    <!--</servlet-mapping>-->

</web-app>
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Servlet作用:
 *      1.接收来自客户端的请求,并且可以获取请求信息
 *      2.执行具体的业务(登录、注册、展示商品、加入购物车....)
 *      3.通过响应返回数据给客户端
 *
 * Servlet生命周期:
 *      1.第一次发送给该Servlet请求后,会创建该Servlet的对象,调用无参构造、init()
 *      2.服务器根据请求方式选择调用doGet()或doPost()
 *      3.关闭服务器时销毁Servlet对象,调用destroy()
 *  小结:在一般情况下,Servlet是单例的
 *
 * Servlet何时被创建?
 *      1.第一次发送请求时
 *      2.在web.xml -> servlet -> <load-on-startup>1</load-on-startup>,该Servlet在项目启动时就会创建对象
 *      3.在Servlet添加了@WebServlet(loadOnStartup=1),该Servlet在项目启动时就会创建对象
 */

@WebServlet(
        value = "/Servlet01",
        initParams={@WebInitParam(name="code",value="UTF-8")},
        loadOnStartup=1
)
public class Servlet01 extends HttpServlet {

    /**
     * Servlet构造方法
     */
    public Servlet01() {
        System.out.println("Servlet01 -- Servlet01()");
    }

    /**
     * Servlet初始化方法
     * @param  config Servlet的配置文件对象
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        String code = config.getInitParameter("code");
        System.out.println("Servlet01 -- init() :" + code);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("Servlet01接收到客户端的请求了...");
    }

    /**
     * Servlet销毁方法
     */
    @Override
    public void destroy() {
        System.out.println("Servlet01 -- destroy()");
    }
}

十二、ServletConfig对象

在Servlet的配置文件中,可以使用一个或多个标签为servlet配置一些初始化参数。

当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

阅读ServletConfig API,并举例说明该对象的作用:

获得字符集编码

获得数据库连接信息实际的Servlet开发中,可以直接通过getServletConfig()的到ServletConfig对象。

十三、Servlet线程安全问题

多个客户端访问同一个Servlet中的资源时,有可能会出现线程安全问题

解决方案

1.将Servlet实现SingleThreadModel(已过时),因为当线程阻塞,就会创建新的Servlet对象

2.利用线程锁机制, synchronized或lock

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

      <a href="MyServlet">MyServlet发送请求</a>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <welcome-file-list>
        <welcome-file>welcome.html</welcome-file>
    </welcome-file-list>
</web-app>
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Servlet是否是单例的?
 *      一般情况下,Servlet是单例的
 *      如果Servlet实现类实现了SingleThreadModel接口,Tomcat服务器发现Servlet线程阻塞了,就会新创建一个Servlet对象
 */
@WebServlet("/MyServlet")
//public class MyServlet extends HttpServlet implements SingleThreadModel {
public class MyServlet extends HttpServlet {

    private int num = 0;

    public MyServlet() {
        System.out.println("MyServlet被创建了");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        synchronized (this){
            num++;

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            response.getWriter().println(num);
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨霖先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值