JavaWeb的冷知识,你了解吗?

1、Tomcat服务器

        Tomcat服务器是一个免费的开放源代码的Web应用服务器,较轻量级应用服务器,具有处理HTML页面的功能,还是一个Servlet和JavaScript的容器。默认模式为独立的Servlet容器。

            那么,来了解一下Tomcat的目录下存储的都是什么?

            

2.常见的服务器错误

        101 – 切换协议。

        200 – 确定。客户端请求已成功。

        201 – 已创建。
        202 – 已接受。
        203 – 非权威性信息。
        204 – 无内容。
        205 – 重置内容。
        206 – 部分内容。

        302 – 对象已移动。

        304 – 未修改。
        307 – 临时重定向。

        HTTP 400 – 请求无效
        HTTP 401.1 – 未授权:登录失败
        HTTP 401.2 – 未授权:服务器配置问题导致登录失败
        HTTP 401.3 – ACL 禁止访问资源
        HTTP 401.4 – 未授权:授权被筛选器拒绝
        HTTP 401.5 – 未授权:ISAPI 或 CGI 授权失败

        HTTP 403 – 禁止访问
        HTTP 403 – 对 Internet 服务管理器 的访问仅限于 Localhost
        HTTP 403.1 禁止访问:禁止可执行访问
        HTTP 403.2 – 禁止访问:禁止读访问
        HTTP 403.3 – 禁止访问:禁止写访问
        HTTP 403.4 – 禁止访问:要求 SSL
        HTTP 403.5 – 禁止访问:要求 SSL 128
        HTTP 403.6 – 禁止访问:IP 地址被拒绝
        HTTP 403.7 – 禁止访问:要求客户证书
        HTTP 403.8 – 禁止访问:禁止站点访问
        HTTP 403.9 – 禁止访问:连接的用户过多
        HTTP 403.10 – 禁止访问:配置无效
        HTTP 403.11 – 禁止访问:密码更改
        HTTP 403.12 – 禁止访问:映射器拒绝访问
        HTTP 403.13 – 禁止访问:客户证书已被吊销
        HTTP 403.15 – 禁止访问:客户访问许可过多
        HTTP 403.16 – 禁止访问:客户证书不可信或者无效
        HTTP 403.17 – 禁止访问:客户证书已经到期或者尚未生效 HTTP 404.1 -

                                                无法找到 Web 站点
        HTTP 404- 无法找到文件
        HTTP 405 – 资源被禁止
        HTTP 406 – 无法接受
        HTTP 407 – 要求代理身份验证
        HTTP 410 – 永远不可用
        HTTP 412 – 先决条件失败
        HTTP 414 – 请求 – URI 太长

        HTTP 500 – 内部服务器错误
        HTTP 500.100 – 内部服务器错误 – ASP 错误
        HTTP 500-11 服务器关闭
        HTTP 500-12 应用程序重新启动
        HTTP 500-13 – 服务器太忙
        HTTP 500-14 – 应用程序无效
        HTTP 500-15 – 不允许请求 global.asa
        Error 501 – 未实现
        HTTP 502 – 网关错误

3、Servlet生命周期

      随着服务器的启动,客户第一次访问,创建Servlet对象,后面访问的是该对象,不会再重新创建,随着服务器的关闭而销毁。

什么时候被创建的?

        当第一次访问的时候被创建的,而且只执行一次。只要访问就会。       

什么时候销毁?

        当服务器停止的时候销毁(没有办法手动销毁,只要访问了就一直存在Tomcat服务器里面)

Servlet生命周期指的是Servlet对象从创建到销毁的过程:

        1.构造器:public login(){}

                       当Service第一次处理请求的时候被调用,用来创建service对象,只会调用一次。

        2.init:在构造器调用之后马上被调用,用来初始化Servlet对象,只会调用一次。

                  

public void init(ServletConfigconfig) throws ServletException {
    String name =config.getInitParameter("name");//键
    System.out.println(name+"书写了该Servlet");//通过键去获取值
    super.init(config);
}

ServletConfig对象可以读取Servlet的配置信息,通过键值对的方式。

        1、在xml文件中去配置init-param参数,以键值对的形式创建

        2、config   getInitParam这个方法去获取

        3、Config能够获取ServletContext对象

        这个对象是用来管理所有的Servlet,也就是说一个web应用只有一个ServletContext对象。    这个对象是一个容器,它就可以存储数据,可以实现Servlet之间的交互,也就说一个Servlet中可以获取另外一个Servlet中的数据。

3.service():   

        用户再次发送请求,service都会被调用,调用多次,用来处理用户请求。

4.destory():

        service对象被销毁前调用,用来执行一些收尾工作,只会执行一次。

JAVA代码如下:

package servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HttpServletDemo extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
        /*String name = config.getInitParameter("name");//键
        System.out.println(name+"书写了该Servlet");//通过键去获取值*/

        ServletContext servletContext = config.getServletContext();
        servletContext.setAttribute("count",0);//以键值对的形式存储,用来记录所有Servlet被访问的次数
        super.init(config);
    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        super.service(req, res);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        ServletContext servletContext = this.getServletContext();
        int count = (int) servletContext.getAttribute("count");
        count++;
        servletContext.setAttribute("count",count);
        resp.getWriter().write("网页被访问了"+count+"次");
    }

    @Override
    public void destroy() {
        super.destroy();
    }
}
xml配置文件代码如下:
        
<?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_3_1.xsd"
         version="3.1">
        <servlet>
            <servlet-name>HttpServletDemo</servlet-name>
            <servlet-class>servlet.HttpServletDemo</servlet-class>
            <init-param>
                <param-name>name</param-name>
                <param-value>cpf</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>HttpServletDemo</servlet-name>
            <url-pattern>/httpServletDemo</url-pattern>
        </servlet-mapping>
</web-app>
4、线程安全

        首先什么是线程安全? 
                引用概念:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

那么我们都知道servlet是多线程的,同时一个servlet实现类只会有一个实例对象,也就是它是Singleton的,所以多个线程是可能会访问同一个servlet实例对象的。

每个线程都会为数据实例对象开辟单独的引用,那么servlet会是线程安全的吗?

要判断是否是线程安全,我们需要知道线程安全问题是由什么引起的。
搜索得到答案:线程安全问题都是由全局变量及静态变量引起的。
看到这个答案,突然想起很多年前调查过的一个bug, 那时我们系统中遗留的代码中写了很多全局变量,有一次发布后,客户反馈,当有多人同时进行某个操作时,我们的数据出了问题,那时我们调查后的结果就是:多人同步操作时,有些全局变量的值不对了,之后我们专门设一个人花了很多工夫来将所有全局变量都改成了局部变量了,并且项目要求以后不允许用全局变量。原来那时侯我就已经碰到过线程不安全的情况了啊,不过处理方式或者不用全局,或者加入同步,若加入同步同时也要考虑一下对程序效率会不会产生影响。

由此可知,servlet是否线程安全是由它的实现来决定的,如果它内部的属性或方法会被多个线程改变,它就是线程不安全的,反之,就是线程安全的。

在网上找到一个例子,如下:

public class TestServlet extends HttpServlet {
     private int count = 0;  
      
     @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>"); 
         for(int i=0;i<5;i++){
             response.getWriter().println("count = " + count + "<BR>");
             try {
                 Thread.sleep(1000);  
                 count++;  
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }


当同时打开多个浏览器,输入http://localhost:8080/ServletTest/TestServlet时,他们显示的结果不同,这就说明了对于属性count来说,它是线程不安全的,
为了解决这个问题,将代码重构,如下:

public class TestServlet extends HttpServlet {
      private int count = 0;  
      private String synchronizeStr = ""; 
      @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>"); 
         synchronized (synchronizeStr){
             for(int i=0;i<5;i++){
                 response.getWriter().println("count = " + count + "<BR>");
                 try {
                     Thread.sleep(1000);  
                     count++;  
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }

        

猜你喜欢

转载自blog.csdn.net/weixin_42047611/article/details/80670138
今日推荐