Servlet深入+JSP的使用

目录

一、Servlet的生命周期

        1.1 什么是生命周期

 二、处理请求

三、Get请求和Post请求

        3.1 get请求

        3.2 Post请求

四、JSP的使用

一、jsp的概念

 二、语法

 三、指令

四、改造类别列表实现

五、EL表达式

        1.1 核心语法

        1.2 Servlet代码

        1.3 el.jsp

六、JSTL

        1.1 JstlServlet代码

        1.2 jstl 的 jsp

七、会话跟踪

           Cookie   由服务器生产保存到客户端的一段文本信息

                示例:

                经典案例:免登录

        Session

        经典案例:控制用户访问

                总结:


  • Servlet接口定义Servlet基础规范:初始化,销毁,获取配置信息 ,Service()方法提供服务
  • GenericServlet实现Service接口,提供初始化,销毁,获取配置信息的默认实现
  • HttpServlet专门处理HTTP请求的Servlet,里面主要根据HTTP协议的特点实现Service规范
  • HttpServletRequest代表客户端的请求,里面保存了客户端请求的所有信息,当一个请求处理方法被调用时服务器会创建这个对象
返回值方法声明说明
StringgetParameter(String name)根据请求参数名称获取请求参数值,若该参数不存在,则返回一个null
voidsetAttribute(String name,Object value)向请求对象(作用域)存一个键值
ObjectgetAttribute(String name)通过键从请求对象(作用域)获取一个值
voidsetCharacterEncoding(String encoding)设置请求的字符集
Cookie[]getCookies()获取客户端的所有Cookie
RequestDispatchergetRequestDispatcher(Stirng path)获取请求转发对象
  • HttpServletResponse代表服务器向客户端的相应,里面可以保存响应的信息,当一个请求处理方法被调用时服务器会创建这个对象
返回值方法声明说明
voidsendRedirect(java.lang.String location)转向(重定向)到指定的资源location
voidaddCookie(Cookie c)向客户端保存有个Cookie
voidsetContentType(String type)设置响应文档类型

一、Servlet的生命周期

        1.1 什么是生命周期

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/8/31 19:05
 * @Version 1.0
 */
package com.wjk.service;

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 LifeServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("2.这是Servlet初始化  ");
    }

    public LifeServlet() {
        System.out.println("1.这是Servlet的构造方法,当Servlet被调用时创建");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("3.当Servlet处理请求时使用");
    }

    @Override
    public void destroy() {
        System.out.println("4.当Servlet销毁时");
    }
}

就是servlet从创建到初始化再到服务最后到销毁的过程。就是servlet的生命周期。
servlet会在不同的阶段执行不同的方法。
(1)构造方法---->servlet被创建时执行
(2)初始化方法--->servlet创建完成后要初始化一些参数时该方法会被执行。
(3)执行方法--->servlet被调用时。
(4)销毁方法--->servlet被关闭。

                浏览器访问的结果

发现:无论发送多少次请求,构造方法和初始化方法只会执行一次。而service每次请求都会被执行

证明servlet为单例模式. 节约内存空间。

当服务器tomcat重启或者重写部署项目,那么servlet就会被销毁

 二、处理请求

               一、 以注册为例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <!--method用来设置请求方式,默认是get,如果要使用post请求,必须设置-->
    <!--
        这里的/带表服务器的根路径,把应用路径给去掉了

        解决:加上应用路径/javaweb/RegServlet
        1.以/开头的路径称为绝对路径
        2.不以/或http协议开头称为相对路径(相对于地址栏)
     -->
    <form action="RegServlet" method="post">
        邮箱:<input name="email"><br>
        密码:<input type="password" name="password"><br>
        昵称:<input name="nk"><br>
        <input type="submit" value="注册">
    </form>
</body>
</html>

        二、处理注册的Servlet,用来处理注册请求

public class RegServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求参数
        //请求页面表单里input的name值
        String email = req.getParameter("email");
        String password = req.getParameter("password");
        String nikename = req.getParameter("nk");

        //2.业务处理
        UserDao userDao = new UserDaoImpl();

        User user = new User();
        user.setNikename(nikename) ;
        user.setEmail(email);
        user.setPassword(password);

        int rows = userDao.saveUser(user);
        //3.转向
        //根据业务处理结果给用户响应(一般用转向)
        
        if(rows > 0){
            //注册成功,跳转到登录页面
            resp.sendRedirect("login.html");
        } else  {
            //注册失败,从新注册
            resp.sendRedirect("reg.html");
        }
    }
 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

        三、转向页面

                发送是post请求,但是servlet重写的是doGet方法,出现

三、Get请求和Post请求

        3.1 get请求

        3.2 Post请求

  • 参数不在地址栏中,安全性增加
  • 参数在请求体中,可以存放大量的数据
  • 缺点是不使用缓存 每次都需要重新加载

四、JSP的使用

一、jsp的概念

        JSP(Java Server Page): Java服务器页面,运行在服务器里实现动态网页。就是在HTML里面嵌入Java代码。把JSP里面的代码分成量部分,一部分是静态HTML代码,一部分Java代码。       

HTML代码
<%

java代码

%>

分成两部分,但是JSP运行需要经过 翻译(把JSP变成Java代码,第一次请求翻译,如果内容没有改变,不用再翻译,当改变内容要重新翻译)->编译(.class)->运行。

JSP本质上就是一个Servlet,里面的HTML代码直接使用out.write()输出,Java代码在服务器运行。

 二、语法

                嵌入的Java代码称为JSP脚本

  • 脚本段(一段脚本)
<%

//脚本段:一段Java代码,只要原来方法里能写的代码都可以
 for (int i = 0; i < 10; i++) {
 }

%>
  •  表达式:输出一个变量的值

<%= %>

=后面是一个变量或表达式,不能加 ;

  • 声明

<%!
    //声明变量,方法
%>

 三、指令

<%@    指令名称    %>
<%@    page          %> 设置JSP页面
<%@    include      %> 包含其他JSP页面
<%@    taglib         %> 导标签库

 

        内置对象

在JSP里不用声明就可以直接使用的对象。

1、out 来源于Java.io.Writer类,它用于发送输出流到客户端。

2、request 来源于javax.servlet.http.HttpServletRequest接口。它被关联到每一个HTTP请求。

3、response 来源于javax.servlet.http.HttpServletResponse。response对象用于把取得的数据返回到客户端。

4、pageContext 提供访问JSP页面的命名空间。它也提供用来访问其他的JSP隐含对象。

5、session 来源于javax.servlet.http.HttpSession。它用于存储客户端请求的信息,因此它是有状态交互式的。

6、application 来源于javax.servlet.ServletContext。

7、config 来源于ServletConfig,它包含了当前JSP/Servlet所在的WEB应用的配置信息。

8、page 来源于当前被访问JSP页面的实例化。它实际使用的是JSP转换成的Servlet。

9、exception 用于捕获JSP抛出的异常。它只有在JSP页面属性isErrorPage=true时才可用。

四、改造类别列表实现

        4.1 Servlet

@WebServlet("/CategoryListServlet2") //使用注解配置访问路径
public class CategoryListServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        CategoryDao categoryDao = new CategoryDaoImpl();
        List<Category> categories = categoryDao.queryAll();

        //要想办法送到JSP里
        //先存到作用域里(page->request->session->application)
        request.setAttribute("clist", categories);
        //转发
        request.getRequestDispatcher("account_book.jsp").forward(request, response);
    }
}

        4.2  JSP页面遍历类别列表

<%@ page import="com.aaa.javaweb.entity.Category" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>帐单列表</title>
  </head>
  <body>
  <table>
    <tr>
      <th>编号</th>
      <th>名称</th>
      <th>图片</th>
      <th>类型</th>
    </tr>

    <%
      List<Category> list = (List<Category>) request.getAttribute("clist");
      for (Category c : list) {
    %>
      <tr>
        <td><%=c.getCid()%></td>
        <td><%=c.getName()%></td>
        <td>
          <img width="40" src="res/images/cat/<%=c.getPic()%>_1.png">
        </td>
        <td><%=c.getType() == 0 ? "支出" : "收入" %></td>
      </tr>
    <%
      }
    %>
  </table>
  </body>
</html>

五、EL表达式

EL(expression language):表达式语言,在JSP里面取值(一般是作用域里的值),现在服务器都支持EL,所以使用它不需要任何配置和导入。

        1.1 核心语法

        ${  表达式  }

        1.2 Servlet代码

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/9/1 19:34
 * @Version 1.0
 */
package com.wjk.service;

import com.wjk.entity.AccountBook;
import com.wjk.entity.Category;

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;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Random;

@WebServlet("/ElServlet")
public class ElServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        //简单的字符串
        req.setAttribute("nstr","普通字符串");
        req.getSession().setAttribute("nstr","session里的字符串");


        //特殊的字符串
        req.setAttribute("fstr","<font color='red'>AAA欢迎你</font>");


        //自定义对象
        AccountBook ab = new AccountBook();
        ab.setDetails("喝酒钱");
        ab.setMoney(new BigDecimal("900"));
        Category c = new Category();
        c.setName("娱乐");
        ab.setCategory(c);
        req.setAttribute("accountBook",ab);


        //自定义对象List
        ArrayList<AccountBook> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            AccountBook book = new AccountBook();
            book.setDetails("详情"+i);
            book.setMoney(BigDecimal.valueOf(new Random().nextLong()));
            book.setCategory(c);
            list.add(book);
        }
        req.setAttribute("booklist",list);

        //计算
        req.setAttribute("num",100);


        //判断是否为空
        req.setAttribute("a2","");
        req.setAttribute("a3",new ArrayList<>());
        req.setAttribute("a4",new Object());


        req.getRequestDispatcher("el.jsp").forward(req,resp);

    }
}

        1.3 el.jsp

<%--
  Created by IntelliJ IDEA.
  User: 王俊凯
  Date: 2022/9/1
  Time: 19:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <fieldset>
        <legend>EL取值</legend>
        ${nstr}
    </fieldset>

    <fieldset>
        <legend>特殊的字符串</legend>
        ${fstr}
    </fieldset>

    <fieldset>
        <legend>自定义对象:通过.取属性值</legend>
        ${accountBook.details},${accountBook.money},${accountBook.category.name}
    </fieldset>

    <fieldset>
        <legend>自定义List</legend>
        ${booklist[0].details},${booklist[0].money},${booklist[0].category.name}<br>
        ${booklist[1].details},${booklist[1].money},${booklist[1].category.name}<br>
    </fieldset>

    <fieldset>
        <legend>计算</legend>
        num:${num*100}
    </fieldset>

    <fieldset>
        <legend>判断是否为空</legend>
        a1:${empty a1}<br>
        a2:${empty a2}<br>
        a3:${empty a3}<br>
        a4:${empty a4}<br>
    </fieldset>
</body>
</html>

六、JSTL

这里需要下载 jar 包          jstl-1.2.jar

(JSTL)(Java server pages standarded tag library,即JSP标准标签库)JSP标准标签库是一个JSP标签集合,它封装了JSP应用的通用核心功能。

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

根据JSTL标签所提供的功能,可以将其分为5个类别。

  • 核心标签
  • 格式化标签
  • SQL标签
  • XML标签
  • JSTL标签

        1.1 JstlServlet代码

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/9/1 20:15
 * @Version 1.0
 */
package com.wjk.service;

import com.wjk.entity.AccountBook;
import com.wjk.entity.Category;

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;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Random;

@WebServlet("/JstlServlet")
public class JstlServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        //特殊字符串
        req.setAttribute("ystr","<font color='red'>八嘎八嘎</font>");

        //判断
        req.setAttribute("num",200);

        //多重判断
        req.setAttribute("haha",15);

        //循环遍历
        ArrayList<AccountBook> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            AccountBook book = new AccountBook();
            Category category = new Category();
            book.setDetails("详情"+i);
            book.setMoney(BigDecimal.valueOf(new Random().nextLong()));
            book.setCategory(category);
            list.add(book);
        }
        req.setAttribute("booklist",list);

        req.getRequestDispatcher("jstl.jsp").forward(req,resp);
    }
}

        1.2 jstl 的 jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: 王俊凯
  Date: 2022/9/1
  Time: 20:13
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <fieldset>
        <legend>特殊字符</legend>
        <c:out value="${ystr}"></c:out>
    </fieldset>


    <fieldset>
        <legend>判断</legend>
        <c:if test="${num>100}">
            num大于1
        </c:if>
    </fieldset>


    <fieldset>
        <legend>多重判断</legend>
        <c:choose>
            <c:when test="${haha<3}">
                haha小于3
            </c:when>
            <c:when test="${haha>10}">
                haha大于10
            </c:when>
        </c:choose>
    </fieldset>


    <fieldset>
        <legend>循环遍历</legend>
        <c:forEach items="${booklist}" var="a">
            ${a.details},${a.money},${a.category.name}<br>
        </c:forEach>
    </fieldset>
</body>
</html>

七、会话跟踪

        为什么要会话跟踪

HTTP是一种短连接、无状态的协议。

会话:客户端打开到关闭和服务器一系列(多次)请求和响应过程。

会话跟踪:记录下客户端的状态。

                怎么实现会话跟踪

           Cookie   由服务器生产保存到客户端的一段文本信息

                1.服务器生成

Cookie c = new Cookie(字符串名字,字符串值);

                 2.保存到客户端

resp.addCookie(c);

                3.一般服务器在客户端保存了Cookie,那么客户端在请求必须Cookie,服务器可以取得这些所有Cookie

Cookie[] cookies = req.getCookies();

                示例:

                        1. 设置Cookie

@WebServlet("/SetCookie")
public class SetCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.服务器生成
        //第一种:临时Cookie,浏览器一关就失效了
        Cookie c = new Cookie("c1","hellocookie");
        //第二章:长久有效,设置一个有效时间,单位是秒
        c.setMaxAge(60*60*24*7);
        //2.发送到客户端
        resp.addCookie(c);

        resp.getWriter().println("设置Cookie成功");

    }
}

                2. 读取Cookie

@WebServlet("/GetCookie")
public class GetCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        //3.读取客户端所有的Cookie
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies) {
            out.println(cookie.getName()+":"+cookie.getValue());
        }

    }
}

                经典案例:免登录

                1.登陆页面

<%
    //获取Cookie
    Cookie[] cookies = request.getCookies();
    for (Cookie c : cookies){
        String name = c.getName();
        //已经记录下了登录用户的Cookie
        if(name.equals("loginUser") && !c.getValue().trim().equals("")){
            response.sendRedirect("CategoryListServlet2");
        }
    }
%>
<!--method用来设置请求方式,默认是get,如果要使用post请求,必须设置-->
<form action="AutoLoginServlet" method="post">
    邮箱:<input name="email"><br>
    密码:<input type="password" name="password"><br>
    <input type="checkbox" name="rememberMe"> 两周内自动登录
    <hr>
    <input type="submit" value="登录"> <input type="reset" value="取消"><br>
    没有账号?请<a href="reg.html">注册</a>
</form>

                2. 登陆处理Servlet

  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求参数
        //请求页面表单里input的name值
        //获取请求参数中文乱码
        //解决:设置请求字符集为请求页面的字符集且要支持中文,这行代码必须在获取任意参数前
        req.setCharacterEncoding("UTF-8");
        String email = req.getParameter("email");
        String password = req.getParameter("password");
        String rememberMe = req.getParameter("rememberMe");

        //System.out.println("rememberMe = " + rememberMe);

        //2.业务处理
        UserDao userDao = new UserDaoImpl();

        User user = userDao.queryByEmailAndPassword(email, password);
        //3.转向
        //根据业务处理结果给用户响应(一般用转向)
        if(user != null){
            //登录成功,跳转到主页面
            //用户选择了自动登录
            if(rememberMe != null){
                Cookie c = new Cookie("loginUser", user.getEmail());
                c.setMaxAge(60*60*24*14);
                resp.addCookie(c);
            }
            resp.sendRedirect("CategoryListServlet2");
        } else  {
            //登录失败,从新登录
            resp.sendRedirect("login.jsp");
        }
    }

                3. 退出Servlt

@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //删除记录登录信息的Cookie
        //获取Cookie
        Cookie[] cookies = req.getCookies();
        for (Cookie c : cookies) {
            String name = c.getName();
            if(name.equals("loginUser")){
                //让Cookie失效
                c.setMaxAge(0);
                //再次写到客户端
                resp.addCookie(c);
            }
        }
        resp.sendRedirect("login.jsp");
    }

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

        Session

会话:从会话创建到销毁过程中多次请求响应过程就是一次会话,在一个会话里存的对象只要Session不失效都可以取出来。

销毁:1. 浏览器关闭Session销毁 2.到了最大有效时间(默认是30分钟) 3.也可以通过代码让session失效。

session一般记录的是一些用户信息。

很多功能需要判断登录用户:主页、添加帐单、帐单列表。

session数据保存在服务器里,比较安全。

        经典案例:控制用户访问

                1. 登录Sevlet

@WebServlet("/AutoLoginServlet")
public class AutoLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求参数
        //请求页面表单里input的name值
        //获取请求参数中文乱码
        //解决:设置请求字符集为请求页面的字符集且要支持中文,这行代码必须在获取任意参数前
        req.setCharacterEncoding("UTF-8");
        String email = req.getParameter("email");
        String password = req.getParameter("password");
        String rememberMe = req.getParameter("rememberMe");

        //System.out.println("rememberMe = " + rememberMe);

        //2.业务处理
        UserDao userDao = new UserDaoImpl();

        User user = userDao.queryByEmailAndPassword(email, password);
        //3.转向
        //根据业务处理结果给用户响应(一般用转向)
        if(user != null){
            //登录成功,跳转到主页面
            //用户选择了自动登录
            if(rememberMe != null){
                Cookie c = new Cookie("loginUser", user.getEmail());
                c.setMaxAge(60*60*24*14);
                resp.addCookie(c);
            }
          //后面能够从session取到
            HttpSession session = req.getSession();
            //把登录用户对象存到sesion里
            session.setAttribute("loginUser", user);
            resp.sendRedirect("CategoryListServlet2");
        } else  {
            //登录失败,从新登录
            resp.sendRedirect("login.jsp");
        }
    }

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

                2. 登录用户判断,没有登录返回登录页面,登陆后才执行业务代码

@WebServlet("/CategoryListServlet2")
public class CategoryListServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session
        HttpSession session = request.getSession();
        //获取登录用户对象
        User loginUser = (User) session.getAttribute("loginUser");
        //如果返回是null以为着session中没有
        if(loginUser == null){
            request.setAttribute("errorInfo", "请登录后再访问");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        } else {
            //已经登录
            CategoryDao categoryDao = new CategoryDaoImpl();
            List<Category> categories = categoryDao.queryAll();

            //要想办法送到JSP里
            //先存到作用域里(page->request->session->application)
            request.setAttribute("clist", categories);
            //转发
            request.getRequestDispatcher("account_book_jstl.jsp").forward(request, response);
        }
    }
}

                总结:

                为什么需要会话跟踪,http协议是无状态的

                实现技术:

                        1. Cookie

                                *保存在客户端

                                *里面只能在文本

                                *大小数量限制

                                *域名的限制

                        2. Session

                                *保存在服务器端

                                *任意对象

                                *大小无限制

                                *无域名限制              

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值