• Java Servlet介绍 1


    1. Servlet规范介绍

      处理请求和发送响应的过程是由Servlet完成的,在Servlet规范中,指定http服务器调用动态资源文件规则;指定http服务器管理动态资源文件示例对象规则。

    2. tomcat和Servlet的关系

      Tomcat是Web应用服务器,是一个Servlet/JSP容器。Tomcat作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传回给客户。Servlet是Web应用程序中的一个组件,扩展了Java Web服务器功能。

      在浏览器请求时,由tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有Http请求头数据可以通过request对象调用对应的方法查询到。

      在对浏览器响应时,会把响应信息封装到HttpServletRespons类型的respon对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器。

    3. 一个简单的Servlet

      HttpServletResponse(响应对象)应用

      分别创建4个servlet,配置web.xml文件,在浏览器中访问对应url

      OneServlet

       TwoServlet

       ThreeServlet

       FourServlet

        综上HttpServletRespson对象的作用: 

       (1)通过响应对象获取标准输出流,把执行结果以二进制形式写入响应体中(write()和print()区别);

       (2)通过响应对象设置content-type,控制浏览器使用对应编译器编译响应体的二进制数据;

       (3)设置location,控制浏览器向指定服务器发送请求;

      HttpServletRequest(请求对象)应用

      OneServlet

       在TwoServlet前,先写一个html,使用超链接访问TwoServlet,这样可以使用TwoServlet来获取参数信息

      two.html

       TwoServlet

      在ThreeServlet前同样先写一个three.html,在three.html中分别使用get和post方法访问ThreeServlet,在ThreeServlet中分别使用doGet和doPost来获取参数信息。

       ThreeServlet

       在使用request获取请求参数时,当请求信息是英文信息时使用get和post都可以正常获取,但是当请求信息是中文信息时get也可以正常获取,post获取的请求参数信息就是乱码了。

      这是因为当浏览器以get方式发送请求时,请求参数保存在请求头,在http请求协议包到达http服务器后由tomcat解码,tomcat默认使用utf-8解码,可以解码中文;当浏览器以post方式发送请求时,请求参数保存在请求体,请求体二进制由request解码,request默认使用ISO-8859-1解码,不能解码中文

      综上HttpServletRequest对象的作用:

      (1)获取http请求协议包中的请求行信息;

      (2)获取http请求协议包中的请求参数信息;

    4. Servlet接口实现类和生命周期

      接口实现类

      查看自定义OneServlet类的继承关系,可以看出自定义Servlet继承抽象类HttpServlet,HttpServlet继承抽象类GenericServlet,GenericServlet实现了Servlet接口,通过两个抽象类简化了Servlet的编写。

      而处理请求和响应其实是在HttpServlet中的Service()方法中,先判断请求方式,然后调用对应的方法执行,所以我们在编写Servlet时,可以直接重写doGet和doPost方法就可以了,不用在重写service方法了。

      Servlet实例创建

      (1)默认情况下,tomcat在初次发送请求后会创建servlet对象

       (2)如果使用<load-on-startup>1</load-on-startup>,load-on-startup大于0(默认为0,可以不写这个标签)的情况下,则会在tomcat启动时就会自动创建servlet对象

      Servlet的生命周期

      (1)服务器启动发送请求后,tomcat负责初始化一个Servlet对象,也就是会调用初始化方法init()方法;

      (2)创建封装Http请求的HttpServletRequest对象和Http响应的HttpServletResponse对象,然后调用Servlet的service()方法处理请求;

      (3)当服务器关闭后,销毁servlet对象,调用destroy()方法;

    5. 欢迎资源文件

      Tomcat的欢迎资源文件规则

      (1)规则位置:tomcat安装位置/conf/web.xml

      (2)规则命令:表示顺序查找标签中的文件

    <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

      

      设置当前网站的默认欢迎资源文件规则

      (1)规则位置:/web/WEB-INF/web.xml

      (2)规则命令:同tomcat的欢迎资源文件配置

      当网站设置自定义默认文件定位规则后,tomcat自带定位规则将失效

    6. 状态码

      302:浏览器获取状态码302后,不会在读取响应体内容,自动根据响应头中的location地址发起二次请求;

      405:Servlet不能对请求方式处理(请求方式是get,但是servlet中可能只定义了post方法);

      500:可以请求资源文件,也可以处理请求方式,但是请求过程中发生了异常;

      400:无法请求到资源文件;

    7. 多个Servlet之间调用规则

      由于来自于浏览器发送的请求往往需要多个Servlet协同处理,但是浏览器一次只能访问一个Servlet,导致用户需要手动通过浏览器多次发送请求才能得到服务,增加用户访问难度,于是可以通过多个Servlet之间调度来解决这个问题,多个Servlet之间调度有两种方案。

      (1)重定向  response.sendRedirect("请求地址");

      在对OneServlet发送请求后,会把TwoServlet地址/myWeb/two写入到响应头的location属性中,tomcat会写入状态码302到状态行中,浏览器根据状态码信息会对响应头的location属性地址发送二次请求。

      使用这种方式会在浏览器和服务器之间多次往返,大量的时间消耗在往返次数上,增加等待服务时间。

      (2)请求转发  request.getRequestDispatcher("/资源文件名").forward(request,response);

       在OneServlet中通过当前请求对象代替浏览器向tomcat申请资源TwoServlet,使用这种方式减少了浏览器与服务器之间的往返次数。

    8. 多个Servlet之间数据共享

      OneServlet工作完毕后,将产生的数据交给TwoServlet来使用

      Servlet规范中提供了四种数据共享方案:

      (1)ServletContext:Http服务器启动时会自动创建全局作用域对象,其他Servlet都可以从这个全局作用域对象中读取数据;

      在OneServlet中我们创建全局作用域对象,并向全局作用域对象中写入数据

      在TwoServlet中我们获取全局作用域对象中的数据

       ServletContext全局作用域对象可以在多个Servlet之间相互共享数据。

      在Http服务启动过程中,自动为当前网站在内存中创建一个全局作用域对象,并且在运行期间只有一个全局作用域对象,在http服务器关闭时,全局作用域对象会被销毁。

      (2)Cookie:当用户通过浏览器初次向网站发送请求申请OneServlet,OneServlet会在运行期间创建一个Cookie存储与当前用户相关的数据,OneServlet运行完毕后,会将Cookie信息写入到响应头交给浏览器;浏览器收到响应包后,将Cookie存储在浏览器的缓存中,一段时间后用户通过同一浏览器再次向同一网站发送申请TwoServlet时,浏览器会把之前推送的cookie信息写入到请求头发送,这样TwoServlet在运行时就可以通过读取请求头中的cookie信息与OneServlet共享数据。

      先写一个简单的页面

    <body>
        <center>
            <font style="color: red;font-size: 40px">新会员申请开卡</font>
            <form action="/myWeb/one">
                <table border="2">
                    <tr>
                        <td>用户名</td>
                        <td><input type="text" name="userName"></td>
                    </tr>
                    <tr>
                        <td>预存金额</td>
                        <td><input type="text" name="money"></td>
                    </tr>
                    <tr>
                        <td><input type="submit" value="申请开卡"></td>
                        <td><input type="reset"></td>
                    </tr>
                </table>
            </form>
    
        </center>
    </body>
    index.html

      用OneServlet来处理这个页面提交的请求,在Servlet中获取请求头的用户和金额参数信息,保存在用户coookie中写入响应头中,请求重新转发到下一个页面;

    public class OneServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 调用请求对象获取请求头参数信息
            String userName = request.getParameter("userName");
            String money = request.getParameter("money");
            //2. 创建cookie信息
            Cookie card1 = new Cookie("userName",userName);
            Cookie card2 = new Cookie("money",money);
            //3. 设置cookie的生命周期
            card2.setMaxAge(60);  //60ms
            //4. 将cookie信息写入到响应体中
            response.addCookie(card1);
            response.addCookie(card2);
            //5. 请求转发到点餐页面
            request.getRequestDispatcher("/index_2.html").forward(request,response);
        }
    }
    <body>
        <center>
            <font style="color: red; font-size: 40px">点餐页面</font>
            <form action="/myWeb/two">
                食物类型:<input type="radio" name="food" value="jiaozi">饺子(30元)
                <input type="radio" name="food" value="miantiao">面条(20元)
                <input type="radio" name="food" value="gaifan">盖饭(15元)<br/>
                <input type="submit" value="消费">
            </form>
    
        </center>
    </body>
    index_2.html

      用TwoServlet来处理index_2页面发送的请求信息,在Servlet中先从请求头中获取参数信息,然后从请求头中获取缓存的cookie信息,进行处理;

    public class TwoServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            int jiaozi_money = 30;
            int gaifan_money = 15;
            int miaotiao_money = 20;
            int money = 0,xiaofei = 0,balance = 0;
            String userName = null;
            response.setContentType("text/html;charset=utf-8");
            PrintWriter pw = response.getWriter();
            Cookie newCard = null;
            //1. 获取请求头信息
            String food = request.getParameter("food");
            //2. 获取cookie信息
            Cookie[] cookies = request.getCookies();
            //3. 根据食物消费
            for(Cookie cookie : cookies){
                String key = cookie.getName();
                String value = cookie.getValue();
                if("userName".equals(key)){
                    userName = value;
                }else if ("money".equals(key)){
                    money = Integer.valueOf(value);
                    if("jiaozi".equals(food)){
                        if(jiaozi_money > money){
                            pw.print("用户" + userName + "余额不足,请充值");
                        }else{
                            newCard = new Cookie("money",(money-jiaozi_money) + "");
                            xiaofei = jiaozi_money;
                            balance = money - jiaozi_money;
                        }
                    }else if("miaotiao".equals(food)){
                        if(miaotiao_money > money){
                            pw.print("用户" + userName + "余额不足,请充值");
                        }else{
                            newCard = new Cookie("money",(money-miaotiao_money) + "");
                            xiaofei = miaotiao_money;
                            balance = money - miaotiao_money;
                        }
                    }else if("gaifan".equals(food)){
                        if(gaifan_money > money){
                            pw.print("用户" + userName + "余额不足,请充值");
                        }else{
                            newCard = new Cookie("money",(money-gaifan_money) + "");
                            xiaofei = gaifan_money;
                            balance = money - gaifan_money;
                        }
                    }
                }
            }
            //4. cookie信息返回用户
            response.addCookie(newCard);
            //5. 返回消费记录
            pw.print("用户" + userName + "本次消费" + xiaofei + ",余额 : " + balance);
        }
    }

      a. 在index页面向OneServlet发送请求后,可以看到浏览器响应头cookie中已经保存了用户和金额的信息

      b. 在页面2中可以发送请求后可以直接从请求头中获取浏览器缓存的cookie信息,进行数据共享

       默认情况下cookies信息只保存在浏览器中,因此只要浏览器关闭cookies信息就会销毁,也可以手动设置cookies在硬盘上的存活时间,使用cookie.setMaxAge(时间)。

      (3)HttpSession:如果两个Servlet来自于同一个网站,并且为同一用户/浏览器服务,可以使用HttpSession对象进行数据共享;

      先写一个简单的html页面

    <body>
        <table border="2" align="center">
            <tr>
                <td>商品名称</td>
                <td>商品单价</td>
                <td>供货商</td>
                <td>加入购物车</td>
            </tr>
            <tr>
                <td>华为笔记本</td>
                <td>7000</td>
                <td>华为</td>
                <td><a href="/myWeb/one?goodsName=华为笔记本">加入购物车</a></td>
            </tr>
            <tr>
                <td>苹果</td>
                <td>10</td>
                <td>西安</td>
                <td><a href="/myWeb/one?goodsName=苹果">加入购物车</a></td>
            </tr>
            <tr>
                <td>衣服</td>
                <td>1000</td>
                <td>上海</td>
                <td><a href="/myWeb/one?goodsName=衣服">加入购物车</a></td>
            </tr>
            <tr align="center">
                <td colspan="4"><a href="/myWeb/two">查看购物车</a></td>
            </tr>
        </table>
    </body>
    View Code

      用OneServlet来处理每次加入购物车的请求,在Servlet中先获取session,然后将数据保存在session中

    public class OneServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 用请求参数获取参数信息
            String goodsName = request.getParameter("goodsName");
            //2. 用请求对象获取session
            HttpSession session = request.getSession();
            //3. 加入session
            Integer goodsNum = (Integer) session.getAttribute(goodsName);  //先获取商品的数量
            if(goodsNum == null){
                session.setAttribute(goodsName,1);
            }else {
                session.setAttribute(goodsName,goodsNum + 1);
            }
        }
    }

      在TwoServlet中可以从session中获取数据

    public class TwoServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 通过请求对象获取session
            HttpSession session = request.getSession();
            //2. 读取session中的key
            Enumeration goodsNames = session.getAttributeNames();    //返回一个枚举类型
            while (goodsNames.hasMoreElements()){
                String goodsName = (String)goodsNames.nextElement();
                int num = (int)session.getAttribute(goodsName);
                System.out.println("商品名:" + goodsName + " 商品数量:" + num);
            }
        }
    }

      HttpSession销毁时机:

      由于用户与HttpSession关联使用的cookie只能保存在浏览器缓存中,因此浏览器关闭时,用户与他的session也会切断;由于tomcat无法检查浏览器的关闭,因此不会导致tomcat对HttpSession的销毁,为了解决这一问题,Tomcat为HttpSession设置了空闲时间,默认30分钟,就会销毁到HttpSession。

      也可以手动设置这个空闲时间:

      在当前网站下/web/WEB-INF/web.xml

        <!--设置session的空闲时间-->
        <session-config>
            <session-timeout>5</session-timeout>  <!--设置session的空闲时间5分钟-->
        </session-config>

      (4)HttpServletRequest:两个Servlet之间通过请求转发方式调用,因为彼此共享请求协议包,而一个请求协议包对应一个请求对象,因此两个Servlet之间可以通过请求对象实现数据共享

      在OneServlet中设置请求对象的值,请求转发到TwoServlet

    public class OneServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //1. 把数据添加到请求对象中,作为共享数据
            req.setAttribute("key1","2021/09/14");
            //2. 请求转发到下一个Servlet
            req.getRequestDispatcher("/two").forward(req,resp);
        }
    }

      在TwoServlet中可以获取到请求对象共享的值

    public class TwoServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //从同一个请求作用域对象中得到共享数据
            String value = (String)req.getAttribute("key1");
            System.out.println("TwoServlet runing get value " +  value);
        }
    }
  • 相关阅读:
    iOS开发
    Xcode
    UITextField
    iOS
    过场动画
    iOS 网络状态监听和检查,
    线程互动,GCD小应用,(功能实现并代码聚集---加载动画,弹框AlertView定时消失。)
    drawRect: 小注
    FMDB_and_Sqlite3
    UIGestureRecognizer手势。
  • 原文地址:https://www.cnblogs.com/homle/p/15377433.html
Copyright © 2020-2023  润新知