【Servlet】-Javaweb项目的快速使用

Servlet

1.Servlet

Servlet 是 JavaWeb 三大组件之一。 三大组件分别是: Servlet 程序、 Filter 过滤器、 Listener 监听器.可以接收客户端发送过来的请求, 并响应数据给客户端。

2.获取参数

首先要加入Tomcat依赖

idea过程:Project Structure -->Modules --> 当前项目 --> Dependencies --> + -->lib -->Application Server Libraries -->Tomcat

//以水果商城为例
//要继承HttpServlet
public class AddServlet extends HttpServlet {
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String fname = request.getParameter("fname");
        String priceStr = request.getParameter("price");
        Integer price = Integer.parseInt(priceStr);
        String fcountStr = request.getParameter("fcount");
        Integer fcount = Integer.parseInt(fcountStr);
        String remark = request.getParameter("remark");
        System.out.println("fname = " + fname);
        System.out.println("price = " + price);
        System.out.println("fcount = " + fcount);
        System.out.println("remark = " + remark);
        
        //添加进数据库,加上JDBC的代码可以将数据放入数据库中
         FruitDAO fruitDAO = new FruitDAOImpl();
        boolean flag = fruitDAO.addFruit(new Fruit(0, fname, price, fcount, remark));
        System.out.println(flag? "添加成功": "添加失败");

    }

}

add.html的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form  action="add" method="post">
    名称: <input type="text" name="fname"/><br/>
    价格: <input type="text" name="price"/><br/>
    库存: <input type="text" name="fcount"/><br/>
    备注: <input type="text" name="remark"/><br/>
    <input type="submit" value="提交">
</form>
</body>
</html>

web.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_4_0.xsd"
         version="4.0">
    <!-- servlet 标签给 Tomcat 配置 Servlet 程序 -->
    <servlet>
        <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
       <servlet-name>AddServlet</servlet-name>
        <!--servlet-class 是 Servlet 程序的全类名-->
        <servlet-class>com.serein.servlets.AddServlet</servlet-class>
    </servlet>
    <!--servlet-class 是 Servlet 程序的全类名-->
    <servlet-mapping>
        <!--servlet-name 标签的作用是告诉服务器, 我当前配置的地址给哪个 Servlet 程序使用-->
        <servlet-name>AddServlet</servlet-name>
        <!--url-pattern 标签配置访问地址 <br/>
/ 斜杠在服务器解析的时候, 表示地址为: http://ip:port/工程路径 <br/>
/add 表示地址为: http://ip:port/工程路径/add <br/>
-->
        <url-pattern>/add</url-pattern>
    </servlet-mapping>
</web-app>

url地址访问到Servlet程序的过程:

①用户发请求,action=add

②项目中,web.xml中找到url-pattern = /add -> 第12行

③找第11行的servlet-name = AddServlet

④找和servlet-mapping中servlet-name一致的servlet , 找到第7行

⑤找第8行的servlet-class -> com.atguigu.servlets.AddServlet

⑥用户发送的是post请求(method=post) , 因此 tomcat会执行AddServlet中的doPost方法

3.设置编码

注意:设置编码代码需在所有的获取参数之前

(1)get请求

​ 基于Tomcat8下,get方式下目前不需要设置编码

​ 在Tomcat之前,get请求发送的中文数据,转码如下

String fname = request.getParameter("fname");
//1.将字符串打散成字节数组
byte[] bytes = fname.getBytes("ISO-8859-1");
//2.将字节数组按照设定的编码重新组装成字符串
fname = new String(bytes,"UTF-8");

(2)post请求

 request.setCharacterEncoding("UTF-8");
4.Servlet的继承关系

–javax.servlet.Servlet接口
— javax.servlet.GenericServlet抽象类
---- javax.servlet.http.HttpServlet抽象子类

5.Servlet的相关方法
 javax.servlet.Servlet接口:
        void init(config) - 初始化方法
        void service(request,response) - 服务方法
        void destory() - 销毁方法
  javax.servlet.GenericServlet抽象类:
    void service(request,response) - 仍然是抽象的
  javax.servlet.http.HttpServlet 抽象子类:
        void service(request,response) - 不是抽象的
        1. String method = req.getMethod(); 获取请求的方式
        2. 各种if判断,根据请求方式不同,决定去调用不同的do方法
            if (method.equals("GET")) {
                this.doGet(req,resp);
            } else if (method.equals("HEAD")) {
                this.doHead(req, resp);
            } else if (method.equals("POST")) {
                this.doPost(req, resp);
            } else if (method.equals("PUT")) {
        3.HttpServlet这个抽象类中,do方法都差不多:
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_get_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(405, msg);
            } else {
                resp.sendError(400, msg);
            }
        }

服务方法: 当有请求过来时,service方法会自动响应(其实是tomcat容器调用的)。

在HttpServlet中我们会去分析请求的方式:到底是get、post、head还是delete等等。

然后再决定调用的是哪个do开头的方法,那么在HttpServlet中这些do方法默认都是405的实现风格-

要我们子类去实现对应的方法,否则默认会报405错误。因此,我们在新建Servlet时,我们才会去考虑请求方法,从而决定重写哪个do方法
建议表单使用post的方法,剩下的方法使用get方法

6.Servlet的生命周期

(1)生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init(),service(),destroy()

(2)默认情况下:

第一次接收请求时,这个Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())

从第二次请求开始,每一次都是服务。当容器关闭时,其中的所有的servlet实例会被销毁,调用销毁方法

(3)Servlet的初始化时机:

默认是第一次接收请求时,实例化,初始化

我们可以通过来设置servlet启动的先后顺序,数字越小,启动越靠前,最小值0

例:

  <servlet>
        <servlet-name>Demo02Servlet</servlet-name>
        <servlet-class>Demo02Servlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

(4)Servlet在容器中是:单例的、线程不安全的

单例:所有的请求都是同一个实例去响应

线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化

7.Http协议

(1)Http 称之为 超文本传输协议

(2) Http是无状态的

(3) Http请求响应包含两个部分:请求和响应

  • 请求:

    • 请求包含三个部分:1.请求行;2.请求消息头;3.请求主体

    • 请求行包含了三个信息:1.请求的方式;2.请求的URL;3.请求的协议(HTTP协议的版本,一般都是HTTP1.1)

    • 请求消息头包含了客户端需要告诉服务器的信息

      • 相对比较重要的请求消息头:
      名称功能
      Host服务器的主机地址
      Accept声明当前请求能够接受的『媒体类型』
      Referer当前请求来源页面的地址
      Content-Length请求体内容的长度
      Content-Type请求体的内容类型,这一项的具体值是媒体类型中的某一种
      Cookie浏览器访问服务器时携带的Cookie数据
    • 请求体,三种情况:

      • get方式,没有请求体,但是有一个queryString
      • post方式,有请求体,form data
      • json方式,有请求体,request payload
  • 响应:

    • 响应也包含三部分:1.响应状态行;2.响应消息头;3.响应头

    • 响应状态行:包含了三个信息:1.协议;2.响应状态码(200)3.响应状态(ok)

    • 响应消息头:包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)

      • 名称功能
        Content-Type响应体的内容类型
        Content-Length响应体的内容长度
        Set-Cookie服务器返回新的Cookie信息给浏览器
        location重定向的情况下,告诉浏览器访问下一个资源的地址
    • 响应体:响应的实际内容(比如请求add.html页面时,响应的内容就是…)

8.会话

(1)Http是无状态的

  • HTTP无状态:服务器无法判断这两次请求时同一个客户端发过来的,还是不同的客户端发过来的
  • 无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求时结账;如果这两次请求服务器无法区分是同一个用户的,那么就会导致混乱。
  • 通过会话跟踪问题来解决无状态问题

(2)会话跟踪技术

  • 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端

  • 下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这一次的请求和上一次的请求是同一个客户端,从而能够区分客户端

  • 常用的API:

    • request.getSession() --> 获取当前的会话,没有则创建一个新的会话

    • request.getSession(true) --> 效果和不带参数一致

    • request.getSession(false) --> 获取当前会话,没有则返回null,不会创建新的

    • session.getId() --> 获取sessionID

    • session.isNew() --> 判断当前session是否是新的

    • session.getMaxInactiveInterval() --> session的非激活间隔时长,默认1800秒

    • session.setMaxInactiveInterval() -->设置Session最大的过期时间

    • session.invalidate() --> 强制性让会话立即失效

(3)session保存作用域

  • session保存作用域是和具体的某一个session对应的
  • 常用的API:
    • void session.setAttribute(k,v) --> 设置
    • Object session.getAttribute(k) --> 获取
    • void removeAttribute(k) -->删除
9.服务器内部转发以及客户端重定向

(1)服务器内部转发:request.getRequestDispatcher("…").forward(request,response);

  • 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的
  • 地址栏没有变化

(2)客户端重定向:response.sendRedirect("…");

  • 两次请求响应的过程.客户端是知道请求URL有变化
  • 地址栏有变化
10.保存作用域

原始情况下,保存作用域我们可以认为有四个: page(页面级别,现在几乎不用) , request(一次请求响应范围) , session(一次会话范围) , application(整个应用程序范围)
1) request:一次请求响应范围

@WebServlet("/demo01")
public class demo01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.向request保存作用域保存数据
        request.setAttribute("uname","lili");
        //2.客户端重定向
//        response.sendRedirect("demo02");
        //3.服务器内部转发
        request.getRequestDispatcher("demo02").forward(request,response);
    }
}
@WebServlet("/demo02")
public class demo02 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取request保存作用域保存的数据,key为uname
        Object uname = request.getAttribute("uname");
        System.out.println("uname = " + uname);

    }
}

​ 在客户端重定向内,demo02无法获取带uname的值,但服务器内部转发可以获取到uname的值

2) session:一次会话范围有效

​ 只要sessionID没有过期就可获取到uname的值

3) application: 一次应用程序范围有效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值