JavaWeb4


1. 会话技术

  • 会话:一次会话中包含多次请求和响应
    • 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
  • 功能:在一次会话的范围内的多次请求间共享数据
  • 方式:
    • 客户端会话技术:Cookie
    • 服务器端会话技术:Session

1.1.1 快速入门

  • 概念:客户端会话技术,将数据保存在客户端

  • 使用步骤:

    • 创建Cookie对象,绑定数据

      new Cookie(String name, String value)

    • 发送Cookie对象

      response.addCookie(Cookie cookie)

    • 获取所有Cookie,拿到数据

      Cookie[] getCookies()

    package com.mark.cookie;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    /**
     * Cookie快速入门
     */
    
    @WebServlet("/cookieDemo1")
    public class CookieDemo1 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1.创建Cookie对象,绑定数据
            Cookie cookie = new Cookie("msg", "HeHe");
            //2.发送Cookie对象
            response.addCookie(cookie);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    
    @WebServlet("/cookieDemo2")
    public class CookieDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //3.获取Cookie
            Cookie[] cookies = request.getCookies();
            //获取数据,遍历Cookies
            if (cookies != null) {
                for (Cookie c : cookies) {
                    String name = c.getName();
                    String value = c.getValue();
                    System.out.println(name + ": " + value);
                }
            }
            /*
            JSESSIONID: 5F22E6A6804B8AB0A5E144849D7E51C1
            msg: HeHe
            Webstorm-ec1c0726: 62f9d3ca-a2fa-4d36-aef6-9086650fec79
            */
        }
    }
    

1.1.2 实现原理分析

cookie原理

基于响应头set-cookie和请求体cookie实现

1.1.3 Cookie的细节

  • 一次可否发送多个Cookie?

    • 可以
    • 创建多个Cookie对象,使用response调用多次addCookie()方法即可
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie1 = new Cookie("msg", "HeHe");
        response.addCookie(cookie1);
    
        Cookie cookie2 = new Cookie("name","mark");
        response.addCookie(cookie2);
    }
    
  • Cookie在浏览器中保存时间?

    • 默认情况下当浏览器关闭后,Cookie数据被销毁
    • 持久化存储:
      • setMaxAge(int seconds)
        • 正数:将Cookie数据写到硬盘的文件中。持久化存储。正数代表存活时间。
        • 负数:默认值
        • 零:删除Cookie信息
    @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            Cookie cookie1 = new Cookie("msg", "setMaxAge");
    //        cookie1.setMaxAge(300);//设置存活时间,将cookie持久化硬盘,300s后删除cookie文件
    //        cookie1.setMaxAge(-1);//设置存活时间,默认值
            cookie1.setMaxAge(0);//设置存活时间,删除Cookie信息
            response.addCookie(cookie1);
        }
    
  • cookie能否存中文?

    • 在tomcat8之前,Cookie不能直接存储中文数据
      • 需要将中文数据转码—一般采用URL编码(%E3)
    • 在tomcat8之后,Cookie支持中文数据。不支持特殊字符,建议使用URL编码存储
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie1 = new Cookie("msg", "你好");
        response.addCookie(cookie1);
        //msg: 你好
    }
    
  • Cookie共享问题

    • 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享

      • 默认情况下Cookie不能共享
      • setPath(String path):设置Cookie的获取范围。默认情况下,会去设置当前的虚拟目录
      cookie1.setPath("/");//在当前服务器的根目录下的所有项目可共享数据
      
    • 不同的tomcat服务器间Cookie共享问题?

      • setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
        • eg:setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

1.1.4 Cookie的特点和作用

  • 特点
    • Cookie存储数据在客户端浏览器
    • 浏览器对于单个Cookie的大小有限制(4kb),以及对同一个域名下的总Cookie数量也有限制(20个)
  • 作用:
    • cookie一般用来存储少量的不太敏感的数据
    • 在不登陆的情况下,完成服务器对客户端的身份识别

1.1.5 案例:记住上次访问时间

  • 需求:

    1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
    2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
  • 分析:

    • 可以采用Cookie完成
    • 在服务器的Servlet中判断是否有一个名为lastTime的cooike
      • 有:不是第一次访问
        • 响应数据:欢迎回来,您上次访问时间为:
        • 写回Cookie:lastTime=
      • 没有:是第一次访问
        • 响应数据:您好,欢迎您首次访问
        • 写回Cookie:lastTime=
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        boolean flag = false;
        //获取所有Cookie
        Cookie[] cookies = request.getCookies();
        //遍历cookie数组
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                //获取cookie的名称
                String name = c.getName();
                if ("lastTime".equals(name)) {
                    flag = true;
    
                    //响应数据
                    String value = c.getValue();
                    value = URLDecoder.decode(value, "utf-8");
                    response.getWriter().write("欢迎回来,您上次访问时间为:" + value);
                  
                    //设置cookie的value
                    //获取当前时间字符串,重新设置cookie的值,重新发送cookie
                    Date date = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                    String str_date = sdf.format(date);
                    str_date = URLEncoder.encode(str_date, "UTF-8");
                    c.setValue(str_date);
                    c.setMaxAge(60 * 60 * 24 * 30);
                    response.addCookie(c);
    
                    break;
    
                }
            }
        }
    
        if (cookies == null || cookies.length == 0 || flag == false) {
            flag = true;
            //设置cookie的value
            //获取当前时间字符串,重新设置cookie的值,重新发送cookie
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
            String str_date = sdf.format(date);
            str_date = URLEncoder.encode(str_date, "UTF-8");
            Cookie c = new Cookie("lastTime", str_date);
            response.addCookie(c);
            response.getWriter().write("您好,欢迎您首次访问");
        }
    
    }
    

1.2 Session

概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession

1.2.1 快速入门

HttpSession对象:

Object getAttribute(String name)

void setAttribute(String name, Object value)

void removeAttribute(String name)

  • 步骤:

    1. 获取Session对象
    2. 存数据
    3. 获取Session对象
    4. 获取数据
    @WebServlet("/sessionDemo1")
    public class SessionDemo1 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //使用Session共享对象
    
            //1.获取session
            HttpSession session = request.getSession();
            //2.存数据
            session.setAttribute("msg","hello session");
        }
    }
    
    @WebServlet("/sessionDemo2")
    public class SessionDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //使用Session共享对象
    
            //1.获取session
            HttpSession session = request.getSession();
            //2.获取数据
            Object msg = session.getAttribute("msg");
            System.out.println(msg);
        }
    }
    

1.2.2 实现原理分析

Session原理

Session的实现依赖于Cookie,通过请求头和响应头实现

1.2.3 Session细节

  • 当客户端关闭后,服务器不关闭,两次获取Session是否为同一个?

    • 默认情况下不是
    //期望关闭客户端后,session也能相同:保存到客户端
    Cookie cookie = new Cookie("JSESSIONID",session.getId());
    cookie.setMaxAge(60*60);
    
  • 客户端不关闭,服务器关闭,两次获取的Session是否为同一个?

    • 不是同一个,但是要确保数据不丢失
      • Session的钝化
        • 在服务器正常关闭之前,将Session对象序列化到硬盘上
      • Session的活化
        • 在服务器启动后,将Session文件转化到内存中的Session对象即可
    • 服务器会自动完成Session的钝化和活化,但是IDEA不会
  • Session什么时候被销毁?

    • 服务器关闭
    • Session对象调用方法void invalidate()
    • Session的默认失效时间:30min(可以在Tomcat的配置文件D:/Tomcat/apache-tomcat-8.5.81/conf/web.xml中修改<session-config>标签的值)

1.2.4 Session的特点

  • Session用于存储一次会话的多次请求的数据,存在服务器端

    • 可以在重定向时代替ServletContext
  • Session可以存储任意类型、任意大小的数据

  • Session与Cookie的区别

    • Session存储在服务器端,Cookie在客户端
    • Session没有数据大小限制,而Cookie有
    • Session数据安全,Cookie相对于较不安全

1.2.5 案例:登陆案例2.0

  • 需求:

    1. 访问带有验证码的登录页面login.jsp
    2. 用户输入用户名,密码以及验证码。
    • 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
    • 如果验证码输入有误,跳转登录页面,提示:验证码错误
    • 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
  • 分析:

    登录案例

  • 实现:

    • 创建login.jsp登录页面

      <%--
        Created by IntelliJ IDEA.
        User: Mark
        Date: 2022/8/3
        Time: 18:28
        To change this template use File | Settings | File Templates.
      --%>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>Login</title>
          <script>
              window.onload = function () {
                  var img = document.getElementById("checkCode");
                  img.onclick = function () {
                      img.src = "/LoginTest2/CheckCodeServlet?" + new Date().getTime();
                  }
      
                  var a = document.getElementById("change");
                  a.onclick = function () {
                      img.src = "/LoginTest2/CheckCodeServlet?" + new Date().getTime();
                  }
              }
          </script>
      
          <style>
              div {
                  color: red;
              }
          </style>
      </head>
      <body>
      <form action="/LoginTest2/LoginServlet" method="post">
          <table>
              <tr>
                  <td>用户名</td>
                  <td><input type="text" name="username" placeholder="请输入用户名"></td>
              </tr>
              <tr>
                  <td>密码</td>
                  <td><input type="password" name="password" placeholder="请输入密码"></td>
              </tr>
              <tr>
                  <td>验证码</td>
                  <td><input type="text" name="checkCode" placeholder="请输入验证码"></td>
              </tr>
              <tr>
                  <td><img id="checkCode" src="/LoginTest2/CheckCodeServlet"></td>
                  <td><a id="change" href="#">看不清,换一张</a></td>
              </tr>
              <tr>
                  <td colspan="2"><input type="submit" value="登录"></td>
              </tr>
          </table>
      </form>
      
      <div>
          <%=request.getAttribute("cc_error") == null ? "" : request.getAttribute("cc_error")%>
      </div>
      
      <div>
          <%=request.getAttribute("login_error") == null ? "" : request.getAttribute("login_error")%>
      </div>
      </body>
      </html>
      
      
    • 创建验证码img

      package com.mark.web;
      
      import javax.imageio.ImageIO;
      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.awt.*;
      import java.awt.image.BufferedImage;
      import java.io.IOException;
      import java.util.Random;
      
      @WebServlet("/CheckCodeServlet")
      public class CheckCodeServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //创建一个对象,在内存中代表图片(验证码图片对象)
              int width = 100;
              int height = 50;
              BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
              //美化图片
              //填充背景色
              Graphics g = image.getGraphics();//画笔对象
              g.setColor(Color.PINK);//设置画笔颜色
              g.fillRect(0, 0, width, height);//填充颜色
              //画边框
              g.setColor(Color.BLUE);
              g.drawRect(0, 0, width - 1, height - 1);
              //写验证码
              String str = "QWERTYUIOPASDGFHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm0123456789";
              //生成随机角标
              Random random = new Random();
              StringBuilder sb=new StringBuilder();
              for (int i = 1; i <= 4; i++) {
                  int index = random.nextInt(str.length());
                  //获取字符
                  char ch = str.charAt(index);
                  sb.append(ch);
                  g.drawString(ch + "", width / 5 * i, height / 2);
              }
              String checkCode_session = sb.toString();
              request.getSession().setAttribute("checkCode_session",checkCode_session);
      
              //干扰线
              g.setColor(Color.GREEN);
              for (int i = 1; i < 10; i++) {
                  //随机生成坐标点
                  int x1 = random.nextInt(width);
                  int x2 = random.nextInt(width);
                  int y1 = random.nextInt(height);
                  int y2 = random.nextInt(height);
                  g.drawLine(x1, y1, x2, y2);
              }
      
              //将图片输出到页面展示
              ImageIO.write(image, "jpg", response.getOutputStream());
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      
    • 创建JavaBean

      package com.mark.domain;
      

      /**

      • @ClassName User

      • @Description TODO 用户的JavaBean(实体类)

      • @Author Mark

      • @Date 2022/7/31 20:44

      • @Version 1.0
        */
        public class User {
        private int id;
        private String username;
        private String password;

        public int getId() {
        return id;
        }

        public void setId(int id) {
        this.id = id;
        }

        public String getUsername() {
        return username;
        }

        public void setUsername(String username) {
        this.username = username;
        }

        public String getPassword() {
        return password;
        }

        public void setPassword(String password) {
        this.password = password;
        }

        @Override
        public String toString() {
        return “User{” +
        “id=” + id +
        “, username='” + username + ”’ +
        “, password='” + password + ”’ +
        ‘}’;
        }
        }

      ​“`

    • 创建JDBC工具类

      package com.mark.util;
      
      import com.alibaba.druid.pool.DruidDataSourceFactory;
      
      import javax.sql.DataSource;
      import java.io.IOException;
      import java.io.InputStream;
      import java.sql.Connection;
      import java.sql.SQLException;
      import java.util.Properties;
      
      /**
       * @ClassName JDBCUtils
       * @Description TODO JDBC工具类 使用Druid连接池
       * @Author Mark
       * @Date 2022/7/31 20:50
       * @Version 1.0
       */
      public class JDBCUtils {
          private static DataSource ds;
      
          static {
              //加载配置文件
              Properties pro =new Properties();
              //使用classLoader加载配置文件,获取字节输入流
              InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
              try {
                  pro.load(is);
              } catch (IOException e) {
                  e.printStackTrace();
              }
              //初始化连接池
              try {
                  ds = DruidDataSourceFactory.createDataSource(pro);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          //获取连接池对象
          public static DataSource getDataSource(){
              return ds;
          }
      
          //获取连接Connection对象
          public static Connection getConnection() throws SQLException {
              return ds.getConnection();
          }
      }
      
      
    • 操作数据库中User表

      package com.mark.dao;
      
      import com.mark.domain.User;
      import com.mark.util.JDBCUtils;
      import org.springframework.dao.DataAccessException;
      import org.springframework.jdbc.core.BeanPropertyRowMapper;
      import org.springframework.jdbc.core.JdbcTemplate;
      
      /**
       * @ClassName UserDao
       * @Description TODO 操纵数据库中User表的类
       * @Author Mark
       * @Date 2022/7/31 20:48
       * @Version 1.0
       */
      public class UserDao {
      
          //声明JDBCTemplate对象共用
          private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
      
          /**
           * 登陆方法
           * @param loginUser 只有用户名和密码
           * @return User包含用户全部数据, 没有查询到,返回null
           */
          public User login(User loginUser) {
              try {
                  String sql = "select * from user where username=? and password = ?";
                  User user = template.queryForObject(sql,
                          new BeanPropertyRowMapper<User>(User.class),
                          loginUser.getUsername(), loginUser.getPassword());
                  return user;
              } catch (DataAccessException e) {
                  e.printStackTrace();//记录日志
                  return null;
              }
          }
      }
      
      
    • 创建登录LoginServlet

      package com.mark.web;
      
      import com.mark.dao.UserDao;
      import com.mark.domain.User;
      import org.apache.commons.beanutils.BeanUtils;
      
      import javax.servlet.*;
      import javax.servlet.http.*;
      import javax.servlet.annotation.*;
      import java.io.IOException;
      import java.lang.reflect.InvocationTargetException;
      import java.util.Map;
      
      @WebServlet("/LoginServlet")
      public class LoginServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //设置request编码格式为utf-8
              request.setCharacterEncoding("utf-8");
              //获取所有参数的map集合
              Map<String, String[]> parameterMap = request.getParameterMap();
              //创建User集合
              User loginUser = new User();
              //使用BeanUtils封装JavaBean
              try {
                  BeanUtils.populate(loginUser, parameterMap);
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              } catch (InvocationTargetException e) {
                  e.printStackTrace();
              }
              //获取页面输入的验证码
              String checkCode = request.getParameter("checkCode");
              //获取Session
              HttpSession session = request.getSession();
              //获取绘制的验证码
              String checkCode_session = (String) session.getAttribute("checkCode_session");
              //在获取后就移除session防止在登录后回退验证码还能生效
              session.removeAttribute("checkCode_session");
              //判断验证码输入是否正确
              if (checkCode_session != null && checkCode_session.equalsIgnoreCase(checkCode)) {
                  //验证码正确
                  //查询数据库
                  UserDao dao = new UserDao();
                  User user = dao.login(loginUser);
                  if (user == null) {
                      //查询为空
                      //存储提示信息到request
                      request.setAttribute("login_error", "用户名或密码错误");
                      //转发到登录页面
                      request.getRequestDispatcher("/login.jsp").forward(request, response);
                  } else {
                      //登陆成功
                      session.setAttribute("user", user.getUsername());
                      response.sendRedirect(request.getContextPath() + "/success.jsp");
                  }
              } else {
                  //验证码正确
                  //存储提示信息到request
                  request.setAttribute("cc_error", "验证码错误");
                  //转发到登录页面
                  request.getRequestDispatcher("/login.jsp").forward(request, response);
              }
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
      

2. JSP(了解即可)

  • 概念:Java Server Pages:java服务器页面

    • 可理解为一个特殊的页面,其中既可以直接定义HTML的标签,又可以编写Java代码
    • 用于简化书写
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
          <%
            System.out.println("hello jsp");
          %>
    
          <h1>hi~jsp</h1>
      </body>
    </html>
    

2.1 原理

JSP原理

  • JSP本质上就是Servlet

2.2 JSP的脚本

JSP的脚本:JSP定义Java代码的方式

  • <& 代码 &>:定义的Java代码在service方法中。service中可以定义什么,该脚本就可以定义什么

    <%
      System.out.println("hello jsp");
      int i = 5;//局部变量
    %>
    
  • <&! 代码 &>:定义的Java代码在jsp转换后的java类的成员位置。

    <%!
      int i = 3;//成员变量
    %>
    
  • <&= 代码 &>:定义的Java代码会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。

    <%= i + "hello"   // 5hello 会打印局部变量%> 
    

2.3 JSP的内置对象

  • 在jsp页面中不需要获取和创建,直接可以使用的对象称为JSP的内置对象

  • 一共有9个内置对象

    • request

    • response

    • out:字符输出流对象。可以将数据输出到页面上。和response.getWrite()类似

      • response.getWrite()和out.write()区别:前者永远会先于后者输出

        在tomcat服务器真正给客户端浏览器做出响应前,会先找response缓冲区数据,再找out缓冲区数据

2.4 改造Cookie案例

<%@ page import="java.net.URLDecoder" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.net.URLEncoder" %><%--
  Created by IntelliJ IDEA.
  User: Mark
  Date: 2022/8/2
  Time: 19:39
  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>

<%
    boolean flag = false;
    //获取所有Cookie
    Cookie[] cookies = request.getCookies();
    //遍历cookie数组
    if (cookies != null && cookies.length > 0) {
        for (Cookie c : cookies) {
            //获取cookie的名称
            String name = c.getName();
            if ("lastTime".equals(name)) {
                flag = true;

                //响应数据
                String value = c.getValue();
                value = URLDecoder.decode(value, "utf-8");
%>
<h1>欢迎回来,您上次访问时间为:<%=value%>></h1>
<%
                //设置cookie的value
                //获取当前时间字符串,重新设置cookie的值,重新发送cookie
                Date date = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                String str_date = sdf.format(date);
                str_date = URLEncoder.encode(str_date, "UTF-8");
                c.setValue(str_date);
                c.setMaxAge(60 * 60 * 24 * 30);
                response.addCookie(c);

                break;

            }
        }
    }

    if (cookies == null || cookies.length == 0 || flag == false) {
        flag = true;
        //设置cookie的value
        //获取当前时间字符串,重新设置cookie的值,重新发送cookie
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String str_date = sdf.format(date);
        str_date = URLEncoder.encode(str_date, "UTF-8");
        Cookie c = new Cookie("lastTime", str_date);
        response.addCookie(c);
%>
<h1>您好,欢迎您首次访问</h1>
<%
    }
%>

</body>
</html>

2.5 JSP的指令

  • 作用:用于配置JSP页面,导入资源文件

  • 格式:<%@ 指令名称 属性名1=属性值1 属性名2=属性值2%>

  • 分类:

    • page:配置JSP页面

      • contentType:等同于response.setContentType()

        • 设置响应体的mime类型以及字符集
        • 设置当前JSP页面的编码(只能是高级的IDE才能生效,如果是低级工具,需要设置pageEncoding属性设置当前页面的字符集编码)
      • pageEcoding:设置当前JSP页面的编码

      • import:导包

      • errorPage:当前页面发生异常后,会自动跳转到指定的错误页面

        <%@ page errorPage="error.jsp" %>

      • isErrorPage:表示当前页面是否为错误页面。true/false

        • 默认为false。当设置为true时就可以使用内置对象exception。可以将错误消息输出到日志文件中
    • include:在当前页面中导入项目中其他的页面

      <%@ include file="top.jsp" %>

    • taglib:导入资源。一般用于导入标签库

      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

      prefix:前缀(自定义)

2.6 JSP的注释

  • html注释:

    <!-- -->:只能注释html代码片段

  • JSP注释:推荐使用

    <%-- --%>:可注释所有

2.7 所有的内置对象

在JSP页面中不需要创建,直接使用的对象

变量名 真实类型 作用
pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象
request HttpServletRequest 一次请求访问的对个资源(转发)
session HttpSession 一次会话的多个请求间
application ServletContext 所有用户间共享数据
response HttpServletResponse 响应对象
page Object 当前页面(Servlet)的对象,可理解为this
out JspWriter 输出对象,数据输出到页面上
config ServletConfig Servlet的配置对象
exception Throwable 异常对象

前四个:域对象。用于共享数据

3. MVC开发模式

3.1 jsp演变历史

  1. 早期只有Servlet,只能使用response输出标签数据,非常麻烦
  2. 后来有了JSP,简化可Servlet的开发。但如果过度使用JSP,在JSP中既写大量Java代码,又写HTML标签,会造成难以维护,难于分工协作,难于阅读
  3. 再后来,Java的Web开发,借鉴MVC开发模式,使得程序的设计更加合理性

3.2 MVC开发模式详解

MVC:将一个程序分为M、V、C三个部分。

  • M:Model,模型。JavaBean
    • 完成具体的业务操作,如查询数据库,封装对象
  • V:View,视图。JSP
    • 展示数据
  • C:Controller,控制器。Servlet
    • 获取用户的输入
    • 调用模型
    • 将数据交给视图进行展示

MVC

3.3 MVC的优缺点

  • 优点:
    • 耦合性低,方便维护,利于分工协作
    • 重用性高
  • 缺点:
    • 使得项目架构变得复杂,对开发人员要求很高

4. EL表达式

4.1 概述

  • 概念:Expression Language 表达式语言
  • 作用:替换和简化jsp页面中java代码的编写
  • 语法:${表达式} eg:${3 > 4} 输出false
  • 注意:
    • JSP默认支持EL表达式
    • 当在page指令中设置isELIgnored为true时将不会解析此页面的EL表达式
    • 在$前加反斜线将不会解析此EL表达式:/${3 > 4}

4.2 使用

  • 运算

    • 运算符:

      • 算术运算符:+ – * /(div) %(mod)
      • 比较运算符: > < >= <= == !=
      • 逻辑运算符:&&(and) ||(or) !(not)
      • 空运算符:empty
        • 用于判断字符串、集合、数组对象是否为null并且长度是否为0
        • ${empty list}
      <%--
        Created by IntelliJ IDEA.
        User: Mark
        Date: 2022/8/7
        Time: 17:22
        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>
      ${3 > 4}
      /${3 > 4}
      <hr>
      <h3>算数运算符</h3>
      ${3 + 4}<br>
      ${3 / 4}<br>
      ${3 div 4}<br>
      ${3 % 4}<br>
      ${3 mod 4}<br>
      
      <h3>比较运算符</h3>
      ${3 == 4}<br>
      ${3 != 4}<br>
      
      <h3>逻辑运算符</h3>
      ${3 > 4 && 3 < 4}<br>
      ${3 > 4 and 3 < 4}<br>
      
      <h3>空运算符</h3>
      ${3 > 4 && 3 < 4}<br>
      ${3 > 4 and 3 < 4}<br>
      
      </body>
      </html>
      
      
  • 获取值

    • EL表达式只能从域对象中获取值

    • 语法:

      • ${域名称.键名}:从指定域中获取指定键的值
        • 域名称:
          • pageScope —>pageContext
          • requestScope —>request
          • sessionScope —>session
          • applicationScope —>application(ServletContext)
      • ${键名}:表示依次从最小的域中查找是否又该键对应的值,直到找到为止。
      
      <%--
        Created by IntelliJ IDEA.
        User: Mark
        Date: 2022/8/7
        Time: 22:32
        To change this template use File | Settings | File Templates.
      --%>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>获取域中的数据</title>
      </head>
      <body>
      
      <%
          //在域中存储数据
          request.setAttribute("name", "zhangsan");
          session.setAttribute("age", 21);
          session.setAttribute("name", "lisi");
      %>
      
      <h3>EL获取值</h3>
      ${requestScope.name}
      ${sessionScope.age}
      ${sessionScope.haha}<%--当为null时返回空字符串,不会影响页面布局--%>
      
      ${name}<%--zhangsan--%>
      ${sessionScope.name}<%--lisi--%>
      </body>
      </html>
      
      
    • 获取对象、List集合、Map集合的值

      • 对象${域名称.键名.属性名}

        • 本质上会去调用对象的getter方法
        <%@ page import="com.mark.domain.User" %>
        <%@ page import="java.util.Date" %><%--
          Created by IntelliJ IDEA.
          User: Mark
          Date: 2022/8/7
          Time: 22:57
          To change this template use File | Settings | File Templates.
        --%>
        <%@ page contentType="text/html;charset=UTF-8" language="java" %>
        <html>
        <head>
            <title>获取数据</title>
        </head>
        <body>
        <%
            User user = new User();
            user.setName("zhangsan");
            user.setAge(21);
            user.setBirthday(new Date());
        
            request.setAttribute("u", user);
        %>
        
        <h3>获取对象的值</h3>
        ${requestScope.u}<br>
        <%--
            通过对象的属性获取
                setter或getter方法,去掉set或get,再将剩余部分首字母变为小写,得到的内容称之为属性
                setName --->  Name --->name
        --%>
        ${requestScope.u.name}
        ${requestScope.u.age}
        ${requestScope.u.birthday}<br>
        ${requestScope.u.birthday.month}<%--7--%><br>
        ${requestScope.u.birStr}
        <%--    2022-08-07 23:14:37--%>
        </body>
        </html>
        
          	/**
             * 逻辑视图
             * @return
             */
            public String getBirStr() {
                //1.格式化日期
                if (birthday != null) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    //2.返回字符串
                    return sdf.format(birthday);
                } else {
                    return "";
                }
            }
        
      • Map集合${域名称.键名.key名称}

         <%@ page import="com.mark.domain.User" %>
          <%@ page import="java.util.*" %><%--
            Created by IntelliJ IDEA.
            User: Mark
            Date: 2022/8/7
            Time: 23:20
            To change this template use File | Settings | File Templates.
          --%>
          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <html>
          <head>
              <title>获取集合数据</title>
          </head>
          <body>
          <%
              Map map = new HashMap<>();
              map.put("name", "zhangsan");
              map.put("gender", "male");
        
              request.setAttribute("map", map);
          %>
        
          <h3>获取map值</h3>
          ${map.name}
          ${map.gender}<%--male--%>
        
          ${map["gender"]}<%--male--%>
        
          </body>
          </html>
        
        
  • 空运算符的使用:

    • 用于判断字符串、集合、数组对象是否为null并且长度是否为0
    • ${empty str}
    • ${not empty str}:判断字符串、集合、数组对象是否不为null并且长度不为0
    <h4>empty运算符</h4>
    <%
    //    String str= "abc";
        String str= null;
        request.setAttribute("str",str);
    %>
    
    ${empty str}
    <%--false--%>
    <%--true--%>
    
    ${not empty str}
    <%--false--%>
    
    
  • 隐式对象:

    • el表达式中有11个隐式对象
    • pageContext:
      • 获取其他8个内置对象
      • ${pageContext.request.contextPath}

5. JSTL标签

5.1 概述

  • 概念:JavaServer Page Tag Library JSP标准标签库

    ​ 是由Apache组织提供的开源的JSP标签

  • 作用:用于简化和替换jsp页面的java代码

  • 使用步骤

    • 导入JSTL相关jar包
    • 引入标签库:taglib指令 <%@ taglib%>
    • 使用标签

5.2 常用的JSTL标签

  • if:相当于Java的if语句

    • 属性
      • test是必须属性 接收boolean表达式
        • 如果表达式为ture,则显示if标签体内容,如果为false,则不显示标签体内容
        • 如果有else情况,则可以再定义一个c:if标签
  • choose:相当于Java的switch语句

    • 完成数字编号对应星期几案例
      1. 在域中存储数字
      2. 使用choose标签取出数字(相当于switch)
      3. 使用when标签做数字判断(相当于case)
      4. otherwise标签做其他情况声明(相当于default)
    <%
        request.setAttribute("number",3);
    %>
    
    <c:choose>
        <c:when test="${number == 1}">星期一</c:when>
        <c:when test="${number == 2}">星期二</c:when>
        <c:when test="${number == 3}">星期三</c:when>
        <c:when test="${number == 4}">星期四</c:when>
        <c:when test="${number == 5}">星期五</c:when>
        <c:when test="${number == 6}">星期六</c:when>
        <c:when test="${number == 7}">星期日</c:when>
        <c:otherwise>你输入的数字有误</c:otherwise>
    </c:choose>
    
  • foreach:相当于Java的for循环语句

    • 完成重复的操作

      for(int i = 0;i < 10;i++){
      	...
      }
      
      • 属性:
        • begin:开始值(包含)
        • end:结束值(包含)
        • var:临时变量
        • stee:步长(临时遍历每次加几)
        • varStatus:循环状态对象
          • index:容器中元素的索引,从0开始
          • count:循环次数,从1开始
    • 遍历容器

      List<User> list = new ArrayList<>();
      for(User user : list){
      	...
      }
      
      • 属性:
        • items:容器对象
        • var:容器中元素的临时变量
    <c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
        ${i}     ${s.index}     ${s.count}<br>
    </c:forEach>
    <%--
        1 1 1
        3 3 2
        5 5 3
        7 7 4
        9 9 5
    --%>
    
    <%--遍历容器--%>
    
        <hr>
        <%
            List list=new ArrayList();
            list.add("aaa");
            list.add("bbb");
            list.add("ccc");
    
            request.setAttribute("list",list);
        %>
    <c:forEach items="${list}" var="str" varStatus="s" >
        ${s.index} ${s.count} ${str} <br>
    </c:forEach>
    
    <%--0 1 aaa--%>
    <%--1 2 bbb--%>
    <%--2 3 ccc--%>
    

5.3 小练习

  • 需求:
    • 在request域中有一个存有User对象的List集合
    • 需要使用JSTL+EL将list集合数据展示到jsp页面的表格table中
<body>
<%
    //        User user =new User();
//        List<User> list =new ArrayList<User>();
    List<User> list = new ArrayList<>();
    list.add(new User("zhangsan", 23, new Date()));
    list.add(new User("lisi", 24, new Date()));
    list.add(new User("wangwu", 25, new Date()));
    request.setAttribute("list", list);
%>

<table border="1" width="500" align="center">
    <tr>
        <th>编号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>生日</th>
    </tr>
    <c:forEach items="${list}" var="user" varStatus="s">
        <c:if test="${s.count % 2 == 0}">
            <tr bgcolor="red">
                <td>${s.count}</td>
                <td>${user.name}</td>
                <td>${user.age}</td>
                <td>${user.birStr}</td>
            </tr>
        </c:if>

        <c:if test="${s.count % 2 != 0}">
            <tr bgcolor="green">
                <td>${s.count}</td>
                <td>${user.name}</td>
                <td>${user.age}</td>
                <td>${user.birStr}</td>
            </tr>
        </c:if>

    </c:forEach>

</table>

</body>

6. 三层架构

三层架构:软件设计架构

  • 界面层(表示层):用户看得到的界面,用户可以通过界面上的组件和服务器进行交互
  • 业务逻辑层:处理业务逻辑的
  • 数据访问层:操作数据存储文件

三层架构6.1 用户信息列表展示案例

  • 需求:用户信息的增删改查操作

  • 设计:

    • 技术选型:Servlet+JSP+MySql+JDBCTemplate+Durid+BeanUtils+Tomcat

    • 数据库设计:

      create Database db4;
      use db4;
      create table user(
      	id int primary key auto_increment,
        	name varchar(20) not null,
        	gender varchar(6),
        	age int,
        	address varchar(32),
        	qq varchar(20),
        	email varchar(50)
      );
      
  • 开发:

    • 环境搭建

      • 创建数据库环境
      • 创建项目,导入需要的jar包
    • 编码

      • 分析:

      列表查询分析

      • 实现⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐:

        • 编写domain下的JavaBean

          package com.mark.domain;
          
          /**
           * @ClassName User
           * @Description TODO
           * @Author Mark
           * @Date 2022/8/14 18:12
           * @Version 1.0
           */
          public class User {
              private int id;
              private String name;
              private String gender;
              private int age;
              private String address;
              private String qq;
              private String email;
          
              public int getId() {
                  return id;
              }
          
              public void setId(int id) {
                  this.id = id;
              }
          
              public String getName() {
                  return name;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public String getGender() {
                  return gender;
              }
          
              public void setGender(String gender) {
                  this.gender = gender;
              }
          
              public int getAge() {
                  return age;
              }
          
              public void setAge(int age) {
                  this.age = age;
              }
          
              public String getAddress() {
                  return address;
              }
          
              public void setAddress(String address) {
                  this.address = address;
              }
          
              public String getQq() {
                  return qq;
              }
          
              public void setQq(String qq) {
                  this.qq = qq;
              }
          
              public String getEmail() {
                  return email;
              }
          
              public void setEmail(String email) {
                  this.email = email;
              }
          
              @Override
              public String toString() {
                  return "User{" +
                          "id=" + id +
                          ", name='" + name + '/'' +
                          ", gender='" + gender + '/'' +
                          ", age=" + age +
                          ", address='" + address + '/'' +
                          ", qq='" + qq + '/'' +
                          ", email='" + email + '/'' +
                          '}';
              }
          }
          
          
        • 将index.html资源文件转化为index.jsp页面,修改超链接为${pageContext.request.contextPath}/userListServlet

          <%--
            Created by IntelliJ IDEA.
            User: Mark
            Date: 2022/8/14
            Time: 17:58
            To change this template use File | Settings | File Templates.
          --%>
          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <!DOCTYPE html>
          <html lang="zh-CN">
          <head>
            <meta charset="utf-8"/>
            <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
            <meta name="viewport" content="width=device-width, initial-scale=1"/>
            <title>首页</title>
          
            <!-- 1. 导入CSS的全局样式 -->
            <link href="css/bootstrap.min.css" rel="stylesheet">
            <!-- 2. jQuery导入,建议使用1.9以上的版本 -->
            <script src="js/jquery-2.1.0.min.js"></script>
            <!-- 3. 导入bootstrap的js文件 -->
            <script src="js/bootstrap.min.js"></script>
            <script type="text/javascript">
            </script>
          </head>
          <body>
          <div align="center">
            <a
                    href="${pageContext.request.contextPath}/userListServlet" style="text-decoration:none;font-size:33px">查询所有用户信息
            </a>
          </div>
          </body>
          </html>
          
          
        • 在web目录下servlet包中创建UserListServlet,修改路径为/userListServlet

          package com.mark.web.servlet;
          
          import com.mark.domain.User;
          import com.mark.service.UserService;
          import com.mark.service.impl.UserServiceImpl;
          
          import javax.servlet.*;
          import javax.servlet.http.*;
          import javax.servlet.annotation.*;
          import java.io.IOException;
          import java.util.List;
          
          @WebServlet("/userListServlet")
          public class UserListServlet extends HttpServlet {
              @Override
              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                
              }
          
              @Override
              protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  this.doGet(request, response);
              }
          }
          
          
        • 在UserListServlet首先调用UserService完成查询

        • 在service下创建接口UserService:用户管理的业务接口

          package com.mark.service;
          
          import com.mark.domain.User;
          
          import java.util.List;
          
          //用户管理的业务接口
          public interface UserService {
              /**
               * 查询所有用户信息
               * @return
               */
              public List<User> findAll();
          }
          
          
        • 在service下的impl包下创建UserService的实现类UserServiceImpl,调用Dao完成查询

          package com.mark.service.impl;
          
          import com.mark.dao.UserDao;
          import com.mark.dao.impl.UserDaoImpl;
          import com.mark.domain.User;
          import com.mark.service.UserService;
          
          import java.util.List;
          
          /**
           * @ClassName UserServiceImpl
           * @Description TODO
           * @Author Mark
           * @Date 2022/8/14 18:20
           * @Version 1.0
           */
          public class UserServiceImpl implements UserService {
              @Override
              public List<User> findAll() {
                  //调用Dao完成查询
                  return dao.findAll();
              }
          }
          
          
        • 在dao下创建接口UserDao:用户操作的Dao

          package com.mark.dao;
          
          import com.mark.domain.User;
          
          import java.util.List;
          
          //用户操作的Dao
          public interface UserDao {
              public List<User> findAll();
          }
          
          
        • 在dao下的impl包下创建UserDao的实现类UserDaoImpl,使用JDBC操作数据库

          package com.mark.dao.impl;
          
          import com.mark.dao.UserDao;
          import com.mark.domain.User;
          import com.mark.util.JDBCUtils;
          import org.springframework.jdbc.core.BeanPropertyRowMapper;
          import org.springframework.jdbc.core.JdbcTemplate;
          
          import java.util.List;
          
          /**
           * @ClassName UserDaoImpl
           * @Description TODO
           * @Author Mark
           * @Date 2022/8/14 18:22
           * @Version 1.0
           */
          public class UserDaoImpl implements UserDao {
              private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
          
              @Override
              public List<User> findAll() {
                  //使用JDBC操作数据库
              }
          }
          
          
        • 在UserServiceImpl中创建UserDao对象,使用dao.findAll()查询所有数据

          private UserDao dao = new UserDaoImpl();
          
              @Override
              public List<User> findAll() {
                  //调用Dao完成查询
                  return dao.findAll();
              }
          
        • 在Servlet中完成业务逻辑

           //1.调用UserService完成查询
                  UserService service = new UserServiceImpl();
                  List<User> users = service.findAll();
                  //将List存入request域
                  request.setAttribute("users", users);
                  //转发到list.jsp页面
                  request.getRequestDispatcher("/list.jsp").forward(request,response);
          
        • 完成UserDaoImpl中使用JDBC操作数据库

          private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
          
          @Override
          public List<User> findAll() {
              //使用JDBC操作数据库
              //1.定义sql
              String sql = "select * from user";
              List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
              return users;
          }
          
        • 将list.html资源文件转化为list.jsp页面,将死数据修改为活数据

          <%@ page contentType="text/html;charset=UTF-8" language="java" %>
          <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
          <!DOCTYPE html>
          <!-- 网页使用的语言 -->
          <html lang="zh-CN">
          <head>
              <!-- 指定字符集 -->
              <meta charset="utf-8">
              <!-- 使用Edge最新的浏览器的渲染方式 -->
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
              width: 默认宽度与设备的宽度相同
              initial-scale: 初始的缩放比,为1:1 -->
              <meta name="viewport" content="width=device-width, initial-scale=1">
              <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
              <title>用户信息管理系统</title>
          
              <!-- 1. 导入CSS的全局样式 -->
              <link href="css/bootstrap.min.css" rel="stylesheet">
              <!-- 2. jQuery导入,建议使用1.9以上的版本 -->
              <script src="js/jquery-2.1.0.min.js"></script>
              <!-- 3. 导入bootstrap的js文件 -->
              <script src="js/bootstrap.min.js"></script>
              <style type="text/css">
                  td, th {
                      text-align: center;
                  }
              </style>
          </head>
          <body>
          <div class="container">
              <h3 style="text-align: center">用户信息列表</h3>
              <table border="1" class="table table-bordered table-hover">
                  <tr class="success">
                      <th>编号</th>
                      <th>姓名</th>
                      <th>性别</th>
                      <th>年龄</th>
                      <th>籍贯</th>
                      <th>QQ</th>
                      <th>邮箱</th>
                      <th>操作</th>
                  </tr>
                  <c:forEach items="${requestScope.users}" var="user" varStatus="s">
                      <tr>
                          <td>${s.count}</td>
                          <td>${user.name}</td>
                          <td>${user.gender}</td>
                          <td>${user.age}</td>
                          <td>${user.address}</td>
                          <td>${user.qq}</td>
                          <td>${user.email}</td>
                          <td><a class="btn btn-default btn-sm" href="update.html">修改</a>&nbsp;<a class="btn btn-default btn-sm"
                                                                                                  href="">删除</a></td>
                      </tr>
                  </c:forEach>
                  <tr>
                      <td colspan="8" align="center"><a class="btn btn-primary" href="add.html">添加联系人</a></td>
                  </tr>
              </table>
          </div>
          </body>
          </html>
          
          
  • 测试

  • 部署运维

7. 综合练习

基于6.1案例完成

  • 简单功能:
    • 列表查询
    • 登录
    • 添加
    • 删除
    • 修改
  • 复杂功能
    • 删除选中
    • 分页查询
    • 复杂条件查询

7.1 登录功能

  • 调整页面,加入验证码功能
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>管理员登录</title>

    <!-- 1. 导入CSS的全局样式 -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- 2. jQuery导入,建议使用1.9以上的版本 -->
    <script src="js/jquery-2.1.0.min.js"></script>
    <!-- 3. 导入bootstrap的js文件 -->
    <script src="js/bootstrap.min.js"></script>
    <script type="text/javascript">
		//切换验证码
		function refreshCode() {
			//获取验证码的图片对象
			var vcode = document.getElementById("vcode");
			//设置其src属性,获取时间戳
			vcode.src = "${pageContext.request.contextPath}/checkCodeServlet?time="+new Date().getTime();
		}
    </script>
</head>
<body>
<div class="container" style="width: 400px;">
    <h3 style="text-align: center;">管理员登录</h3>
    <form action="${pageContext.request.contextPath}/loginServlet" method="post">
        <div class="form-group">
            <label for="user">用户名:</label>
            <input type="text" name="username" class="form-control" id="user" placeholder="请输入用户名"/>
        </div>

        <div class="form-group">
            <label for="password">密码:</label>
            <input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
        </div>

        <div class="form-inline">
            <label for="vcode">验证码:</label>
            <input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码"
                   style="width: 120px;"/>
            <a href="javascript:refreshCode()"><img src="${pageContext.request.contextPath}/checkCodeServlet"
                                                    title="看不清点击刷新" id="vcode"/></a>
        </div>
        <hr/>
        <div class="form-group" style="text-align: center;">
            <input class="btn btn btn-primary" type="submit" value="登录">
        </div>
    </form>

    <!-- 出错显示的信息框 -->
    <div class="alert alert-warning alert-dismissible" role="alert">
        <button type="button" class="close" data-dismiss="alert">
            <span>&times;</span></button>
        <strong>${requestScope.login_msg}</strong>
    </div>
</div>
</body>
</html>
  • 验证码Servlet
package com.mark.web.servlet;

import javax.imageio.ImageIO;
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.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
 * 验证码
 */
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

        //服务器通知浏览器不要缓存
        response.setHeader("pragma","no-cache");
        response.setHeader("cache-control","no-cache");
        response.setHeader("expires","0");

        //在内存中创建一个长80,宽30的图片,默认黑色背景
        //参数一:长
        //参数二:宽
        //参数三:颜色
        int width = 80;
        int height = 30;
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        //获取画笔
        Graphics g = image.getGraphics();
        //设置画笔颜色为灰色
        g.setColor(Color.GRAY);
        //填充图片
        g.fillRect(0,0, width,height);

        //产生4个随机验证码,12Ey
        String checkCode = getCheckCode();
        //将验证码放入HttpSession中
        request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);

        //设置画笔颜色为黄色
        g.setColor(Color.YELLOW);
        //设置字体的小大
        g.setFont(new Font("黑体",Font.BOLD,24));
        //向图片上写入验证码
        g.drawString(checkCode,15,25);

        //将内存中的图片输出到浏览器
        //参数一:图片对象
        //参数二:图片的格式,如PNG,JPG,GIF
        //参数三:图片输出到哪里去
        ImageIO.write(image,"PNG",response.getOutputStream());
    }
    /**
     * 产生4位随机字符串
     */
    private String getCheckCode() {
        String base = "0123456789ABCDEFGabcdefg";
        int size = base.length();
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for(int i=1;i<=4;i++){
            //产生0到size-1的随机值
            int index = r.nextInt(size);
            //在base字符串中获取下标为index的字符
            char c = base.charAt(index);
            //将c放入到StringBuffer中去
            sb.append(c);
        }
        return sb.toString();
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }
}

  • 登录Servlet
package com.mark.web.servlet;

import com.mark.domain.User;
import com.mark.service.UserService;
import com.mark.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置编码
        request.setCharacterEncoding("utf-8");
        //2.获取数据
        //获取用户填写的验证码
        String verifycode = request.getParameter("verifycode");
        //获取所有数据
        Map<String, String[]> map = request.getParameterMap();
        //3.校验验证码
        HttpSession session = request.getSession();
        String checkcode_server = (String) session.getAttribute("CHECKCODE_SERVER");
        //确保验证码一致性
        session.removeAttribute("CHECKCODE_SERVER");
        if (!checkcode_server.equalsIgnoreCase(verifycode)) {
            //验证码不正确
            //提示信息
            request.setAttribute("login_msg", "验证码错误!");
            //跳转登录页面
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }
        //4.封装User对象
        User user = new User();
        try {
            BeanUtils.populate(user, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //5.调用Service对象查询
        UserService service = new UserServiceImpl();
        User loginUser = service.login(user);
        //6.判断是否登录成功
        if (loginUser != null) {
            //登录成功
            //将用户存到session
            session.setAttribute("user", loginUser);
            //跳转页面
            response.sendRedirect(request.getContextPath() + "/index.jsp");
        } else {
            //登录失败
            //提示信息
            request.setAttribute("login_msg", "用户名或密码错误!");
            //跳转登录页面
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return;
        }
    }

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

7.2 添加功能

  • 功能分析

3.添加功能

  • 功能实现
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- HTML5文档-->
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
    <!-- 指定字符集 -->
    <meta charset="utf-8">
    <!-- 使用Edge最新的浏览器的渲染方式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
    width: 默认宽度与设备的宽度相同
    initial-scale: 初始的缩放比,为1:1 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>添加用户</title>

    <!-- 1. 导入CSS的全局样式 -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- 2. jQuery导入,建议使用1.9以上的版本 -->
    <script src="js/jquery-2.1.0.min.js"></script>
    <!-- 3. 导入bootstrap的js文件 -->
    <script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <center><h3>添加联系人页面</h3></center>
    <form action="${pageContext.request.contextPath}/addUserServlet" method="post">
        <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
        </div>

        <div class="form-group">
            <label>性别:</label>
            <input type="radio" name="gender" value="男" checked="checked"/>男
            <input type="radio" name="gender" value="女"/>女
        </div>

        <div class="form-group">
            <label for="age">年龄:</label>
            <input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
        </div>

        <div class="form-group">
            <label for="address">籍贯:</label>
            <select name="address" class="form-control" id="address">
                <option value="广东">广东</option>
                <option value="广西">广西</option>
                <option value="湖南">湖南</option>
            </select>
        </div>

        <div class="form-group">
            <label for="qq">QQ:</label>
            <input type="text" class="form-control" id="qq" name="qq" placeholder="请输入QQ号码"/>
        </div>

        <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱地址"/>
        </div>

        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交"/>
            <input class="btn btn-default" type="reset" value="重置"/>
            <input class="btn btn-default" type="button" value="返回"/>
        </div>
    </form>
</div>
</body>
</html>
package com.mark.web.servlet;

import com.mark.domain.User;
import com.mark.service.UserService;
import com.mark.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.beans.JavaBean;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/addUserServlet")
public class AddUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.设置编码
        request.setCharacterEncoding("utf-8");
        //2.获取所有数据
        Map<String, String[]> map = request.getParameterMap();
        //3.封装对象
        User user = new User();
        try {
            BeanUtils.populate(user, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //4.调用service完成保存
        UserService service = new UserServiceImpl();
        service.addUser(user);

        //跳转到userListServlet
        response.sendRedirect(request.getContextPath() + "/userListServlet");
    }

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

在UserService中添加addUser方法

@Override
public void addUser(User user) {
    dao.addUser(user);
}

在UserDao中添加addUser方法

@Override
public void addUser(User user) {
    String sql= "insert into user values(null,?,?,?,?,?,?,null,null)";
    template.update(sql,user.getName(),user.getGender(),user.getAge(),user.getAddress(),user.getQq(),user.getEmail());
}

7.3 删除功能

  • 功能分析

4.删除功能

  • 功能实现

修改删除按钮链接

<script>
        function deleteUser(id) {
            //用户安全提示
            if(confirm("您确定要删除吗?")){
                //访问路径
                location.href="${pageContext.request.contextPath}/deleteUserServlet?id="+id;
            }
        }
</script>

<c:forEach items="${requestScope.users}" var="user" varStatus="s">
    <tr>
        <th><input type="checkbox"></th>
        <td>${s.count}</td>
        <td>${user.name}</td>
        <td>${user.gender}</td>
        <td>${user.age}</td>
        <td>${user.address}</td>
        <td>${user.qq}</td>
        <td>${user.email}</td>
        <td>
            <a class="btn btn-default btn-sm" href="update.html">修改</a>&nbsp;
            <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a>
                <%--这里的user.id中的user就是forEach循环中var的user--%>
        </td>
    </tr>
</c:forEach>

添加DeleteUserServlet

package com.mark.web.servlet;

import com.mark.service.UserService;
import com.mark.service.impl.UserServiceImpl;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet("/deleteUserServlet")
public class DeleteUserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取id
        String id = request.getParameter("id");
        //2.调用service删除
        UserService userService = new UserServiceImpl();
        userService.deleteUser(id);
        //跳转到查询所有Servlet
        response.sendRedirect(request.getContextPath() + "/userListServlet");
    }

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

在UserService添加方法deleteUser

@Override
public void deleteUser(String id) {
    dao.deleteUser(Integer.parseInt(id));
}

在UserDao中添加方法deleteUser

@Override
public void deleteUser(int id) {
    String sql = "delete from user where id = ?";
    template.update(sql,id);
}

7.4 修改功能

  • 功能分析

5.修改功能

  • 功能实现

    • 回显操作

      修改list.jsp页面的修改按钮超链接

    <a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>&nbsp;
    

    ​ 添加FindUserServlet

    package com.mark.web.servlet;
    
    import com.mark.domain.User;
    import com.mark.service.UserService;
    import com.mark.service.impl.UserServiceImpl;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/findUserServlet")
    public class FindUserServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1.获取id
            String id = request.getParameter("id");
            //2.调用Service查询
            UserService service=new UserServiceImpl();
            User user = service.findUserById(id);
            //3.将user存入request
            request.setAttribute("user",user);
            //4.将request转发到update.jsp
            request.getRequestDispatcher("/update.jsp").forward(request,response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    

    ​ 在UserService中添加findUserById方法

    @Override
    public User findUserById(String id) {
        return dao.findUserById(Integer.parseInt(id));
    }
    

    ​ 在UserDao中添加findUserById方法

    @Override
    public User findUserById(int id) {
        String sql = "select * from user where id = ?";
        return template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), id);
    }
    

    ​ 修改update.jsp进行回显

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!DOCTYPE html>
    <!-- 网页使用的语言 -->
    <html lang="zh-CN">
    <head>
        <!-- 指定字符集 -->
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>修改用户</title>
    
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <script src="js/jquery-2.1.0.min.js"></script>
        <script src="js/bootstrap.min.js"></script>
    
    </head>
    <body>
    <div class="container" style="width: 400px;">
        <h3 style="text-align: center;">修改联系人</h3>
        <form action="" method="post">
            <div class="form-group">
                <label for="name">姓名:</label>
                <input type="text" class="form-control" id="name" name="name" value="${user.name}" readonly="readonly"
                       placeholder="请输入姓名"/>
            </div>
    
            <div class="form-group">
                <label>性别:</label>
                <c:if test="${user.gender == '男'}">
                    <input type="radio" name="sex" value="男" checked />男
                    <input type="radio" name="sex" value="女"/>女
                </c:if>
                <c:if test="${user.gender == '女'}">
                    <input type="radio" name="sex" value="男" />男
                    <input type="radio" name="sex" value="女" checked />女
                </c:if>
            </div>
    
            <div class="form-group">
                <label for="age">年龄:</label>
                <input type="text" class="form-control" id="age" value="${user.age}" name="age" placeholder="请输入年龄"/>
            </div>
    
            <div class="form-group">
                <label for="address">籍贯:</label>
                <select name="address" class="form-control" id="address">
                    <c:if test="${user.address == '广东'}">
                        <option value="广东" selected>广东</option>
                        <option value="北京">北京</option>
                        <option value="广西">广西</option>
                        <option value="湖南">湖南</option>
                    </c:if>
    
                    <c:if test="${user.address == '北京'}">
                        <option value="广东">广东</option>
                        <option value="北京" selected>北京</option>
                        <option value="广西">广西</option>
                        <option value="湖南">湖南</option>
                    </c:if>
    
                    <c:if test="${user.address == '广西'}">
                        <option value="广东">广东</option>
                        <option value="北京">北京</option>
                        <option value="广西" selected>广西</option>
                        <option value="湖南">湖南</option>
                    </c:if>
    
                    <c:if test="${user.address == '湖南'}">
                        <option value="广东">广东</option>
                        <option value="北京">北京</option>
                        <option value="广西">广西</option>
                        <option value="湖南" selected>湖南</option>
                    </c:if>
    
                </select>
            </div>
    
            <div class="form-group">
                <label for="qq">QQ:</label>
                <input type="text" class="form-control" name="qq" id="qq" value="${user.qq}" placeholder="请输入QQ号码"/>
            </div>
    
            <div class="form-group">
                <label for="email">Email:</label>
                <input type="text" class="form-control" name="email" id="email" value="${user.email}"
                       placeholder="请输入邮箱地址"/>
            </div>
    
            <div class="form-group" style="text-align: center">
                <input class="btn btn-primary" type="submit" value="提交"/>
                <input class="btn btn-default" type="reset" value="重置"/>
                <input class="btn btn-default" type="button" value="返回"/>
            </div>
        </form>
    </div>
    </body>
    </html>
    
    • 修改操作

      设置提交表单路径,设置隐藏域

    <form action="${pageContext.request.contextPath}/updateUserServlet" method="post">
        <div class="form-group">
            <!--隐藏域 提交id-->
            <input type="hidden" name="id" value="${user.id}">
    

    ​ 添加UpdateUserServlet

    package com.mark.web.servlet;
    
    import com.mark.domain.User;
    import com.mark.service.UserService;
    import com.mark.service.impl.UserServiceImpl;
    import org.apache.commons.beanutils.BeanUtils;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.util.Map;
    import java.util.Set;
    
    @WebServlet("/updateUserServlet")
    public class UpdateUserServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1.设置编码
            request.setCharacterEncoding("utf-8");
            //2.获取map
            Map<String, String[]> map = request.getParameterMap();
            /*Set<String> keyset =map.keySet();
            for (String name : keyset) {
                //根据key键获取值
                String[] values = map.get(name);
                System.out.println(name);
                for (String value : values) {
                    System.out.println(value);
                }
                System.out.println("---------");
            }
            */
            //3.创建对象
            User user = new User();
            try {
                BeanUtils.populate(user, map);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
    //        System.out.println(user);
            //html的name,要和封装属性值set的参数名称一致,如果不这样做,那么使用BeanUtils.populate()封装时,里面的键值就会为null
            //4.调用UserService
            UserService service = new UserServiceImpl();
            service.updateUser(user);
            //5.查询所有Servlet
            response.sendRedirect(request.getContextPath() + "/userListServlet");
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    

    ​ 在UserService中添加updateUser方法

    @Override
    public void updateUser(User user) {
        dao.updateUser(user);
    }
    

    ​ 在UserDao中添加updateUser方法

    @Override
    public void updateUser(User user) {
        String sql = "update user set name = ? , gender = ? ,age = ? , address = ? , qq = ? , email = ? where id = ?";
        template.update(sql, user.getName(), user.getGender(), user.getAge(), user.getAddress(), user.getQq(), user.getEmail(), user.getId());
    }
    

7.5 删除选中功能

  • 功能分析

6.删除选中功能

  • 代码实现

    ​ 选中id通过表单提交checkbox获取

    <script>
            window.onload = function () {
                //给删除选中按钮添加单机事件
                document.getElementById("delSelect").onclick = function () {
                    //完成表单提交
                    document.getElementById("delForm").submit();
                }
            }
    </script>
    
    <form id="delForm" action="${pageContext.request.contextPath}/delSelectedServlet" method="post">
        <table border="1" class="table table-bordered table-hover">
            <tr class="success">
                <th><input type="checkbox"></th>
                <th>编号</th>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
                <th>籍贯</th>
                <th>QQ</th>
                <th>邮箱</th>
                <th>操作</th>
            </tr>
            <c:forEach items="${requestScope.users}" var="user" varStatus="s">
                <tr>
                    <th><input type="checkbox" name="uid" value="${user.id}"></th>
                    <td>${s.count}</td>
                    <td>${user.name}</td>
                    <td>${user.gender}</td>
                    <td>${user.age}</td>
                    <td>${user.address}</td>
                    <td>${user.qq}</td>
                    <td>${user.email}</td>
                    <td>
                        <a class="btn btn-default btn-sm"
                           href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>&nbsp;
                        <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a>
                            <%--这里的user.id中的user就是forEach循环中var的user--%>
                    </td>
                </tr>
            </c:forEach>
        </table>
    </form>
    

    ​ 编写delSelectedServlet

    package com.mark.web.servlet;
    
    import com.mark.service.UserService;
    import com.mark.service.impl.UserServiceImpl;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    
    @WebServlet("/delSelectedServlet")
    public class DelSelectedServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取所有id
            String[] ids = request.getParameterValues("uid");
            //调用Service
            UserService service = new UserServiceImpl();
            service.delSelectedUser(ids);
    
            //跳转到查询所有Servlet
            response.sendRedirect(request.getContextPath() + "/userListServlet");
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    }
    
    

    ​ 在UserService下添加delSelectedUser方法

    @Override
    public void delSelectedUser(String[] ids) {
        //遍历数字
        for (String id : ids) {
            //调用dao删除
            dao.deleteUser(Integer.parseInt(id));
        }
    }
    

    ​ 全选全不选功能实现

    //全选全不选功能
    //获取第一个checkbox
    document.getElementById("firstCheckBox").onclick = function () {
        //获取下边列表中所有的CheckBox
        var cbs = document.getElementsByName("uid")
        for (var i = 0; i < cbs.length; i++) {
            //设置这些cbs[i]的checked状态 = firstCheckBox.checked
            cbs[i].checked = this.checked;
        }
    }
    

    ​ 在Sevice应该判断一下ids是否为空(或者在前端遍历cbs,有选中则提交),为空则不提交

    @Override
        public void delSelectedUser(String[] ids) {
            if (ids != null && ids.length > 0) {
                //遍历数字
                for (String id : ids) {
                    //调用dao删除
                    dao.deleteUser(Integer.parseInt(id));
                }
            }
        }
    

7.6 分页查询功能

7.7 复杂条件查询功能

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/280800.html

(0)
上一篇 2022年8月16日
下一篇 2022年8月16日

相关推荐

发表回复

登录后才能评论