JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC

JavaWeb-2

学习视频:B站 狂神说Java – https://www.bilibili.com/video/BV12J411M7Sj

学习资料笔记:CSDN – https://blog.csdn.net/DDDDeng_/article/details/106826674

JavaWeb:网页编程 B/S

  • B/S即浏览器/服务器(browser/server),不需要安装客户端,采用浏览器浏览就可以了,指的是软件系统的结构.

网络编程:TCP/IP C/S

  • C/S 指的就是 客户端/服务器 Client/server

web开发:

  • web,网页的意思。例如 www.baidu.com
  • 静态web
    • html, css
    • 提供给所有人看的, 这个数据始终不会发生变化
  • 动态Web
    • 几乎是所有的网站。比如淘宝
    • 提供给所有人看到数据始终会发生变化。 每个人在不同的事件,不同的地点看到的信息各不相同。从服务端获取数据Web界面因人而变
    • 技术栈:Servlet / JSP, ASP, PHP

在Java中,动态web资源开发的技术统称为 JavaWeb。

1、Cookie、Session

Cookie: 曲奇饼干

session:会话

1.1、会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器这个过程可以称之为会话。

有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过

那么对于一个网站而言,如何证明你来过呢 ?下面是两种方式:

客户端、服务端:

  1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了;cookie
  2. 服务器登记你来过了下次你来的时候我来匹配你session

意思就相当于:

  1. 服务端给客户端开了一个证明,下次你拿着证明来,就可以报道,即cookie
  2. 服务端自己进行登记了,下次你来,服务端自己在登记表里面找你的信息,找到了就让你进去。session。

1.2、保存会话的两种技术

cookie

  • 客户端技术(通过响应,请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息。我们可以把信息或者数据放在Session中

常见问题:

网站登录之后,下次不用再登录了,第二次就直接上去了。 这就是客户端和服务端成功的进行了匹配, 把曾经两个人之间的交易记录(存放在 cookie / session)拿出来能够成功比对。

查看一下Cookie类:都是一些 get 和 set 的方法用来存放和获取数据的

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第1张图片

1.3、Cookie 客户端技术

Cookie: 服务端给访问的客户端开了一个证明/信件, 下一次 客户端拿着信件/证明来, 就能直接进去服务端。

客户端技术的例子

cookie

  1. 创建一个Servlet程序,CookieDemo01:服务器先请求客户端,得到其cookie信息。然后服务器响应客户端,生成一个cookie。

    • 在这里,我们试图去保存一个 cookie信息是用户上次访问的时间信息
    • 注意:这个Cookie 是 客户端的,在客户端的手里,客户端拿着证明去 将访问进入服务端。 所以,应该是 服务端从客户端 获取 cookie
    • 我们可以去设置cookie的存活时间 有效时间。
    package com.AL.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.URLEncoder;
    import java.util.Date;
    
    // 保存用户上一次访问的时间
    public class CookieDemo01 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //服务器告诉你, 你来的时间.把这个时间封装成一个发票,你下次带着发票来,我就知道是你来了
            // 解决中文乱码
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/html; charset=utf-8");
    
            PrintWriter out = resp.getWriter();
    
            // Cookie,服务器从客户端获取,查看你的发票. 查看你啥时来的,是不是这个班的人
            Cookie[] cookies = req.getCookies();  //返回的是数组,表明cookie可能存在多个
            // 判断cookie是否存在
            if (cookies!=null){
                // 当存在时的输出
                out.write("你上次访问的时间为:");
    
                for (int i = 0; i < cookies.length; i++) {
                    Cookie cookie = cookies[i];
                    //获取cookie的名字
                    if (cookie.getName().equals("lastLoginTime")){
                        // 获取cookie的值
                        long lastLoginTime = Long.parseLong(cookie.getValue());
                        Date date = new Date(lastLoginTime);
                        out.write(date.toLocaleString());
                    }
                }
            }else {
                out.write("This is you first time");
            }
            // 服务器给客户端响应一个cookie
            Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
    
            // cookie有效期设置为1天.  以秒为单位
            cookie.setMaxAge(24*60*60);
            resp.setCharacterEncoding("utf-8");
            resp.addCookie(cookie);
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    
  2. web.xml配置文件。进行注册Servlet 和 Servlet的路径映射

    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
      <servlet>
        <servlet-name>CookieDemo01servlet-name>
        <servlet-class>com.AL.servlet.CookieDemo01servlet-class>
      servlet>
      <servlet-mapping>
        <servlet-name>CookieDemo01servlet-name>
        <url-pattern>/c1url-pattern>
      servlet-mapping>
    
    web-app>
    
  3. 启动Tomcat,进行测试。输入 localhost:8080/c1,结果为:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第2张图片

删除cookie:

1.创建一个cookie,且名字必须和要删除的名字一样:

package com.AL.servlet;

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

public class CookieDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建一个cookie. 名字必须要和删除的目标cookie一样
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");

        // 将cookie有效期设置为0, 立马失效
        cookie.setMaxAge(0);
        resp.addCookie(cookie);
    }

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

2.配置文件web.xml:

  <servlet>
    <servlet-name>CookieDemo02servlet-name>
    <servlet-class>com.AL.servlet.CookieDemo02servlet-class>
  servlet>
  <servlet-mapping>
    <servlet-name>CookieDemo02servlet-name>
    <url-pattern>/c2url-pattern>
  servlet-mapping>

3.启动Tomcat,进行测试。 localhost:8080/c2, 结果显示 cookie立马失效。

小结:

cookie

  1. 服务器先向客户端请求,去获取cookie信息。请求中拿到cookie信息。想要得到你的发票,如果你有发票,则将发票展示出来;没有,则给你一个新的发票。
  2. 服务器请求完之后,开始响应给客户端cookie。将得到的信息去生成一个cookie,进行展示,表明你是新来的还是 已经来过。

在这个实现cookie中使用的函数有:

Cookie[] cookies=req.getCookiles();//获得cookie
cookie.getName();//获得cookie中的key
cookie.getValue();//获得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie

cookie:一般会保存在本地的 用户目录下 appdata

一个网站cookie是否存在上限?

  • 一个cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • cookie大小有限制4kb
  • 300个cookie浏览器上限

删除cookie

  • 不设置有效期,关闭浏览器,自动失效
  • 设置有效期时间为0

一关闭浏览器,cookie就自动失效了

中文数据传递

  1. 创建一个cookie:

    package com.AL.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.util.Date;
    
    public class CookieDemo03 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            resp.setContentType("text/html; charset=utf-8");
    
            //服务器告诉你, 你来的时间.把这个时间封装成一个发票,你下次带着发票来,我就知道是你来了
            // Cookie,服务器从客户端获取,查看你的发票. 查看你啥时来的,是不是这个班的人
            Cookie[] cookies = req.getCookies();  //返回的是数组,表明cookie可能存在多个
            PrintWriter out = resp.getWriter();
    
    
            // 判断cookie是否存在
            if (cookies!=null){
                // 当存在时的输出
                out.write("你上一次访问的时间是:");
                //out.write("you last time is:");
    
                for (int i = 0; i < cookies.length; i++) {
                    Cookie cookie = cookies[i];
                    //获取cookie的名字
                    if (cookie.getName().equals("name")){
                        // 获取cookie的值
                        //out.write(cookie.getValue());
                        out.write(URLDecoder.decode(cookie.getValue(),"UTF-8")); // 解码
                    }
                }
            }else {
                out.write("这是你第一次访问本站");
            }
            // 服务器给客户端响应一个cookie.   编码: URLEncoder.encode()
            Cookie cookie = new Cookie("name", URLEncoder.encode("坤坤","utf-8"));
    
            // cookie有效期设置为1天.  以秒为单位
            cookie.setMaxAge(24*60*60);
            resp.addCookie(cookie);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    
  2. web.xml配置文件。发布Servlet程序。

      <servlet>
        <servlet-name>CookieDemo03servlet-name>
        <servlet-class>com.AL.servlet.CookieDemo03servlet-class>
      servlet>
      <servlet-mapping>
        <servlet-name>CookieDemo03servlet-name>
        <url-pattern>/c3url-pattern>
      servlet-mapping>
    
  3. 处理请求参数传递编码问题: 使用编码和解码的方式,使中文不产生乱码。

    • java中编码:URLEncoder.encode(strUri, “UTF-8”);
    • java中解码:URLDecoder.decode(strUri, “UTF-8”);

1.4、Session(重点)

什么是Session

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登陆之后,整个网站它都可以访问!–>保存用户的信息;保存购物车的信息

Session和cookie的区别

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  • session由服务器创建,且保存在服务器中。

Session使用场景

  • 保存一个登陆用户的信息;

  • 购物车信息;

  • 在整个网站中经常会使用的数据,我们将它保存在session中

创建一个Session程序

  • 创建一个session程序。session对象中去存储一个字符串 name
    • 每个客户端的sessionID是唯一的
package com.AL.servlet;

import com.AL.pojo.Person;

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

// session。 存放一个字符串
public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8"); // 使文档可以访问,还有编码

        //得到一个session
        HttpSession session = req.getSession();
        // 给session中存放东西。 服务器对客户进行登记
        //session.setAttribute("name", new Person("鑫仔",1));
        session.setAttribute("name", "鑫仔");
        // 获取session的ID。  且每个客户端的sessionID是唯一的
        String sessionId = session.getId();

        //判断Session是否是新建的
        if (session.isNew()){
            resp.getWriter().write("Session创建成功,ID为"+sessionId);
        }else {
            resp.getWriter().write("session已经在服务器中创建了,ID为"+sessionId);
        }
        //Session创建的时候做了什么事情
//        Cookie cookie = new Cookie("JSESSIONID", sessionId);
//        resp.addCookie(cookie);

    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
  • 配置 web.xml文件。 注册servlet和servlet的映射路径。
  <servlet>
    <servlet-name>SessionDemo01servlet-name>
    <servlet-class>com.AL.servlet.SessionDemo01servlet-class>
  servlet>
  <servlet-mapping>
    <servlet-name>SessionDemo01servlet-name>
    <url-pattern>/s1url-pattern>
  servlet-mapping>
  • 启动Tomcat,进行测试。localhost:8080/s1, 结果为:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第3张图片

获取Session的程序

1.创建一个获取Session的session程序:

package com.AL.servlet;

import com.AL.pojo.Person;

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

public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8"); // 使文档可以访问,还有编码

        //得到一个session
        HttpSession session = req.getSession();

//        Person person = (Person) session.getAttribute("name");
//        System.out.println(person.toString());
        String name = (String) session.getAttribute("name");
    }

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

2.配置 web.xml文件。 这个相当于web容器,发布 Servlet程序。

  <servlet>
    <servlet-name>SessionDemo02servlet-name>
    <servlet-class>com.AL.servlet.SessionDemo02servlet-class>
  servlet>
  <servlet-mapping>
    <servlet-name>SessionDemo02servlet-name>
    <url-pattern>/s2url-pattern>
  servlet-mapping>

3.启动Tomcat,进行测试: localhost:8080/s2。在java控制台可以得到输出。

Session存储一个类

创建一个Person类,建立 name,age 这个属性。session不仅可以存储字符串,也能去存储一个类

1.创建一个Person类: 此时的属性为私有属性,所以利用快捷键 ALT+ INSERT创建公共属性。

package com.AL.pojo;

public class Person {
    private String name;
    private int age;

    public Person(){
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.在创建的Session类中,去存储一个 person 类:

package com.AL.servlet;

import com.AL.pojo.Person;

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

// session。 存放一个字符串
public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8"); // 使文档可以访问,还有编码

        
        //得到一个session
        HttpSession session = req.getSession();
        // 给session中存放东西。 服务器对客户进行登记
        session.setAttribute("name", new Person("鑫仔",1));//存储一个 person类
        // 获取session的ID。  且每个客户端的sessionID是唯一的
        String sessionId = session.getId();

        //判断Session是否是新建的
        if (session.isNew()){
            resp.getWriter().write("Session创建成功,ID为"+sessionId);
        }else {
            resp.getWriter().write("session已经在服务器中创建了,ID为"+sessionId);
        }
        //Session创建的时候做了什么事情
//        Cookie cookie = new Cookie("JSESSIONID", sessionId);
//        resp.addCookie(cookie);
    }


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

3.启动Tomcat测试。

Session注销

Session注销

  • 移除session信息,手动注销。
  • 注销session信息。自动注销。
  1. 创建一个Session。

    package com.AL.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    public class SessionDemo03 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            HttpSession session = req.getSession();
            session.removeAttribute("name");
            // 手动注销session
            session.invalidate();
            System.out.println("over!!!");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    
  2. 配置web.xml文件:

      <servlet>
        <servlet-name>SessionDemo03servlet-name>
        <servlet-class>com.AL.servlet.SessionDemo03servlet-class>
      servlet>
      <servlet-mapping>
        <servlet-name>SessionDemo03servlet-name>
        <url-pattern>/s3url-pattern>
      servlet-mapping>
    
  3. 如果想要自动注销session,那么在web.xml配置文件中进行:

    
      <session-config>
    
        <session-timeout>1session-timeout>
      session-config>
    

那么, 一个网站,究竟如何证明你来过 ?

  • Cookie方法: 初次访问的时候,服务器给客户端一个cookie。以后客户端去请求服务端时,带着cookie去

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第4张图片

  • Session方法:客户端访问服务器的时候,服务器会登记一个Session,编号为SessionID,且这个ID是唯一的,每个浏览器是一个用户其实。用户其实是拿着SessionID去进行访问。 而在服务器中的Session是可以存放数据的

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第5张图片

假如两个用户去想要得到对方的数据,就需要==ServletContext,即 applicatiContext:==就好比前面的多个servlet程序中共享数据一样。
JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第6张图片

2、JSP

2.1、JSP简介

javaweb 动态web的技术栈有 JSP/Servlet

前面我们已经创建一个Servlet程序完成了简单的动态web。

  1. 编写一个Servlet类。 我们选择了直接继承HttpServlet接口,就实现了继承Servlet接口。
  2. 将编写的Servlet发布到web服务器中。 即在web.xml里面进行注册 Servlet和Servlet的路径映射。

这里讲解使用 JSP 技术栈的动态 web。

  • jsp也能完成页面跳转,提供动态数据。

什么是JSP?

Java Server PagesJava服务器端页面,也和Servlet一样,用于动态web技术

最大的特点:

  • 写jsp就像在写HTML

  • 区别:

    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入java代码,为用户提供动态数据

2.2、JSP原理

2.2.1、JSP原理解析

思路:JSP究竟是如何执行的?

  • 代码层面没有任何问题

  • 服务器内部工作

    • tomcat中有一个work目录

    • 在IDEA中使用Tomcat的,会在IDEA中的tomcat中产生一个work目录

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第7张图片

我的电脑上的地址为:C:\Users\ASUS.IntelliJIdea2019.3\system\tomcat\Unnamed_javaweb-02_servlet\work\Catalina\localhost\r1\org\apache\jsp

在此页面下转换成了 java程序

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第8张图片

所以 jsp到底怎么执行?

上面的图片中可以发现, jsp 最终也会被转换成一个 java类

我们去查看里面的代码:

//初始化
public void _JspInit(){
}
//销毁
public void _jspDestroy(){
}
//JSPService
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response){}

在这个 jspService 中的代码的内容有:

  1. 判断请求:

  2. 内置一些对象:

    final javax.servlet.jsp.PageContext pageContext;//页面上下文
    javax.servlet.http.HttpSession session=null; //session
    final javax.servlet.ServletContext application;//applicationContext
    final javax.servlet.ServletConfig config;//config
    javax.servlet.jsp.JspWriter out = null;//out
    final java.lang.Object page = this;//page:当前页
    javax.servlet.jsp.JspWriter _jspx_out = null; //请求
    javax.servlet.jsp.PageContext _jspx_page_context = null;//响应
    
  3. 输出页面前增加的代码:

    response.setContentType("text/html; charset=UTF-8");  //设置响应的页面类型
    pageContext = _jspxFactory.getPageContext(this, request, response,
             null, false, 8192, true);
    _jspx_page_context = pageContext;
    application = pageContext.getServletContext();
    config = pageContext.getServletConfig();
    out = pageContext.getOut();
    _jspx_out = out;
    
  4. 以上这些对象我们可以在jsp中直接使用。

    • 我们在 index.jsp中输入的代码为:

      <%
      String name = "鑫仔";
      %>
      name:<%=name%>
      
    • 在jsp页面中,只要是java代码就会原封不动的输出

       String name = "鑫仔"; /
      
    • 如果是html代码,就会转换为 下面的格式进行输出到前端。

      out.write("  name:");
      out.print(name);
      out.write("\n");
      

所以 JSP的本质就是一个 Servlet浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

2.2.2、Tmocat创建Servlet类实例原理

Tomcat 容器是如何创建 Servlet 类实例?用到了什么原理?

  1. 当容器启动时,会读取在 webapps 目录下所有的 web 应用中的 web.xml 文件,然后对 xml 文件进行解析,并读取 Servlet 注册信息。然后,将每个应用中注册的 servlet 类都进行加载,并通过反射的方式实例化。(有时候也是在第一次请求时实例化)
  2. 在 Servlet 注册时加上 1 如果为正数,则在一开始就实例化,如果不写或为负数,则第一次请求实例化。

2.2.3、JSP和java、Servlet之间的关系

从前面的jsp本质上就是一个 Servlet。(自己的理解)jsp前端页面的信息,会经过转换成 *.java文件,再编译变为 *jsp.class 类。 等价于 Servlet类后, 那么这时候 原先的jsp(Servlet类)和Servlet类 会在 web容器中的 web.xml 文件被解析。 读取Servlet注册信息; 然后进行类加载 通过反射的方式实例化 Servlet 类。 有的是 在客户端第一次请求实例化 Servlet类, 然后客户端处理这个经过服务器处理完毕后的 class对象,即Servlet。

视频中的 jsp、java和Servlet的关系图:
JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第9张图片

2.2.4、Jsp 和 servlet 有什么区别

1、Jsp 经编译后就变成了 Servlet(Jsp 的本质就是 Servlet,JVM 只能识别 Java 的类,不能识别 Jsp 的代码,Web 容器将 Jsp 的代码编译成 JV M能够识别的 Java 类);

2、Jsp 更擅长表现于页面显示,servlet 更擅长于逻辑控制;

3、Servlet 中没有内置对象,Jsp 中的内置对象都是必须通过 HttpServletRequest 对象、HttpServletResponse 对象以及 HttpServlet 对象得到;

4、Jsp 是 Servlet 的一种简化,使用 Jsp 只需要完成程序员需要输出到客户端的内容,Jsp 中的 Java 脚本如何镶嵌到一个类中,由 Jsp 容器完成。而 Servlet 则是个完整的 Java类,这个类的 Service 方法用于生成对客户端的响应。

2.3、JSP基础语法和指令

  • 我们可以直接在创建Maven项目的时候, 选择 一个maven模板进行创建。

  • 另外一种添加webapp模板 maven项目的方法:在创建一个空的maven项目后,在下图位置处,选择添加,然后找到 web application点击添加。

在这里插入图片描述

添加所需要的jar包, 即导入 maven依赖:


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.ALgroupId>
    <artifactId>javaweb-jspartifactId>
    <version>1.0-SNAPSHOTversion>

<dependencies>
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>servlet-apiartifactId>
        <version>3.0-alpha-1version>
    dependency>
    
    <dependency>
        <groupId>javax.servlet.jspgroupId>
        <artifactId>javax.servlet.jsp-apiartifactId>
        <version>2.3.3version>
    dependency>
    
    <dependency>
        <groupId>javax.servlet.jsp.jstlgroupId>
        <artifactId>jstl-apiartifactId>
        <version>1.2-rev-1version>
    dependency>
    
    
    <dependency>
        <groupId>javax.servlet.jsp.jstlgroupId>
        <artifactId>jstlartifactId>
        <version>1.2version>
    dependency>

    
    <dependency>
        <groupId>taglibsgroupId>
        <artifactId>standardartifactId>
        <version>1.1.2version>
    dependency>
dependencies>

project>

基础语法

任何语言都有自己的语法,JAVA中有。JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解知道即可),java所有语法都支持!需要符合java语法,所以这个<% %>这个里面的代码注释用//,<% %> 里面是用来写 java代码的 更需要符合java语法。

在jsp,嵌入java代码即可:

  • <%%>脚本片段

  • <%= %>输出变量或者表达式

  • <%! %>声明

  • <%–注释–%>

  • jsp表达式

    <%–jsp表达式 作用:将程序的输出,输出到客户端
    <% = 变量或者表达式 %> --%>

    <%  = new java.util.Date()   %>
    

    注释写在这样的符号中:<%–注释 --%>

  • jsp脚本片段

    <%–jsp脚本片段–%>

     <%
       int sum=0;
       for (int i = 0; i <=100 ; i++) {
         sum+=i;
       }
       out.println("

    Sum="+sum+"

    "); %>

    <%–脚本再实现,在代码嵌入HTML元素–%>

    <%
       for (int i = 0; i <5 ; i++) {
     %>
     

    hello,world

    <% } %>
  • jsp声明

    <%!
       static{
         System.out.println("Loading Servlet!");
       }
       private int globalVar =0;
       public void kuang(){
         System.out.println("进入了方法狂!");
       }
     %>
    

    JSP声明会被编译到JSP生成java的类中其他的,会被生成到JSPService方法中。即在IDEA中的tomcat文件中查看root文件里面的java代码可以发现。

    我们查看启动Tomcat运行后, 在work文件中root文件中找到 jsp 下的 index_jsp.java 代码:

    public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
        implements org.apache.jasper.runtime.JspSourceDependent,
                     org.apache.jasper.runtime.JspSourceImports {
    
    // JSP 的声明写在了
        static{
          System.out.println("Loading Servlet!");
        }
        private  int globalVar =0;
        public  void xinxin(){
          System.out.println("进入了春天!");
        }
    

jsp的注释,不会在客户端显示。html会显示

  
   <%--  我是JSP的注释--%>

写变量的时候,<%=%> 也可以写成**${}** 这样的形式。

<%--  变量表达式
<%=%>
${}  EL表达式
--%>
  <%
    for (int i = 0; i < 5; i++) { %>
      

hello,girl${i}!

<% }%>

上述三种基础语法的代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%-- $END$ --%>
  <%-- JSP表达式
   <%  = 变量或者表达式 %>  --%>
  <%= new java.util.Date()%>
  <br>
  <%
    String name = "鑫仔";
  %>
  name:<%=name%>
<br>
<%--  jsp 脚本片段
<%  %>脚本片段      --%>
  <%
    int sum=0;
    for (int i = 0; i <=100 ; i++) {
      sum+=i;
    }
    out.println("

Sum="+sum+"

"
); %> <br> <%-- jsp声明 <%! %>声明--%> <%! static{ System.out.println("Loading Servlet!"); } private int globalVar =0; public void xinxin(){ System.out.println("进入了春天!"); } %> <br> <%--注释--%> <!--我是 HTML的注释 --> <%-- 我是JSP的注释--%> <%-- 变量表达式 <%=%> ${} EL表达式 --%> <% for (int i = 0; i < 5; i++) { %> <h1>hello,girl${i}!</h1> <% }%> </body> </html>

2.4、JSP指令

定制错误界面 <%@page … %>

我们在访问页面的时候,有时候会出现访问错误的界面, 如何去定制。

代码 int x =1/0; 错误代码, 因为除数不能为0. 我们定制一个错误的页面,想要在出现 500错误的时候,去跳转到一个500错误的特定信息界面。

  1. 设置一个出错的页面。

    定义跳转路径。 表示当发生错误的时候,则页面跳转到 error/500.jsp 文件这个界面。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    <%-- 定制错误页面--%>
    <%@ page errorPage="error/500.jsp" %>
    <%@ page errorPage="error/404.jsp" %>
    
    
        Title
    
    
    <%
        int x=1/0;
    %>
    
    
    
  2. 自定义的500的错误的 jsp文件,

    我们可以直接让此页面显示 500错误文字信息, 在这里,我们将500错误页面去换成一个图片。 扫描 web 路径下的图片。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
    <%--

    这个是用来设置字体大小的

    自定义500错误的界面

    --%>
  3. 在web.xml中进行配置文件的修改。

    —另一种方式:不用在 jsp 文件中定义跳转页面。出现了响应状态码,到对应的jsp页面

    我们也可以直接在 web.xml文件中进行配置修改:这样出现了错误,就直接去跳转到对应的jsp文件执行。

    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        
        <servlet-mapping>
            <servlet-name>defaultservlet-name>
            <url-pattern>*.cssurl-pattern>
        servlet-mapping>
        <servlet-mapping>
            <servlet-name>defaultservlet-name>
            <url-pattern>*.jsurl-pattern>
        servlet-mapping>
        <servlet-mapping>
            <servlet-name>defaultservlet-name>
            <url-pattern>*.jpgurl-pattern>
        servlet-mapping>
    
        
        <error-page>
            <error-code>404error-code>
            <location>/error/404.jsplocation>
        error-page>
        <error-page>
            <error-code>500error-code>
            <location>/error/500.jsplocation>
        error-page>
    
    web-app>
    
  4. 启动,进行测试。

文件夹格式

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第10张图片

页面拼接

JSP指令:
<%@page … %>
<%@>

  • <%@include file=“common/header.jsp”%>

测试指令**<%@include … %>**:拼接指令。

  • 创建两个jsp文件。 header.jsp 和footer.jsp文件:,且这两个 jsp文件建立在 web目录下的common文件中。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    

    我是header

    Title
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    

    我是footer

    Title
  • 定义一个 jsp3.jsp文件。 想要去展现拼接两个页面的结果。**<%@include … %>**指令

    <%--JSP的注释--%>
    
    
    <%--两个页面拼接在一起: 合二为一--%>
    <%@include file="common/header.jsp"%>
    

    网页主体

    <%@include file="common/footer.jsp"%>
  • 采用**jsp:include 指令**进行页面拼接。 斜杠 / 表示外部的路径

    <%--两个页面拼接在一起: 单独存在,页面进行拼接--%>
    
    

    网页主体

  • 启动tomcat,进行测试观察者这两种方式的结果。http://localhost:8080/jsp3.jsp

    JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第11张图片

    粗略的看,这两种指令 @include 和 jsp.include 完成的效果一样。 但还是存在着一些区别。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
    <%--JSP的注释--%>
    
    <%--两个页面拼接在一起: 合二为一--%>
    <%@include file="common/header.jsp"%>
    

    网页主体

    <%@include file="common/footer.jsp"%>
    <%--两个页面拼接在一起: 单独存在,页面进行拼接--%>

    网页主体

    @include 是将两个页面合二为一;jsp:include是将页面进行拼接。

2.5、JSP内置对象及作用域

2.5.1、9大内置对象

  • PageContext 存东西
  • Request 存东西,封装客户端的请求。 包括来自get和post请求的参数
  • Response 封装服务器对客户端的响应。
  • Session 存东西。 封装用户会话的对象
  • Application [ServletContext] 存东西 封装服务器运行环境的 对象
  • conifg [ServletConfig] Web应用的配置对象
  • out
  • page Jsp 页面本身(相当于 Java 程序中的 this);
  • exception

例子: pageContextDemo01.jsp

使用存放东西的这几个内置对象: pageContext、request、session、 application 去存放数据。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


<%-- 内置对象
在脚本片段的代码,会原封不动生成.jsp.java 要遵循java语法
--%>
<%
    pageContext.setAttribute("name1","鑫仔1号");//保存的数据只在一个页面中有效
    request.setAttribute("name1","鑫仔2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name1","鑫仔3号");//保存的数据只在一次会话中有效,从打开浏览器道关闭浏览器
    application.setAttribute("name1","鑫仔4号");//保存的数据只在服务器中有效,从打开服务器道关闭服务器
%>
<% //从pageContext取出,我们通过寻找的方式来
    //作用域:从底层到高层的顺序
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");
%>
<%--使用EL表达式输出  形式为:${}--%>

取出的值为:

${name1}

${name2}

${name3}

${name4}

保存的数据,作用的区域不同,从==底层到高层的作用域分别为:page、request(请求)、session(会话)、application==

pageContext.setAttribute("name1","鑫仔1号");//保存的数据只在一个页面中有效
request.setAttribute("name1","鑫仔2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name1","鑫仔3号");//保存的数据只在一次会话中有效,从打开浏览器道关闭浏览器
application.setAttribute("name1","鑫仔4号");//保存的数据只在服务器中有效,从打开服务器道关闭服务器

新建一个 pageContextDemo02.jsp.

查看哪个有效? 因为作用域不同,存活的时间也是不一样的

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


<% //从pageContext取出,我们通过寻找的方式来
    //作用域:从底层到高层的顺序
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");
%>
<%--使用EL表达式输出  形式为:${}--%>

取出的值为:

${name1}

${name2}

${name3}

${name4}

${name5}

当我们从 pageContext取出时, 我们通过寻找的方式来。即pageContext.findAttribute()方法

作用域的顺序为: page->request -> session ->application。类似于JVM中的双亲委任机制。

双亲委任机制: 先找最大,级别最高的,一开始就继承的那个类。 没有了再从高往低找。

2.5.2、JSP的4种作用域

Jsp 中的四种作用域包括 page、request、session 和 application,具体来说:

1、page 代表与一个页面相关的对象和属性

2、request 代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多

个页面,涉及多个 Web 组件,需要在页面显示的临时数据可以置于此作用域;

3、session 代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关

的数据应该放在用户自己的 session 中;

4、application 代表与整个 Web 应用程序相关的对象和属性,它实质上是跨越整个 Web

应用程序,包括多个页面、请求和会话的一个全局作用域。

对应于上面这4种作用域,

  • pageContext的范围只适用于当前页面范围,超过这个范围就不行了。 所以不能使用pageContext去进行页面之间的参数传递。
  • request:用户向服务端发送请求,服务端响应后的数据。用户看完就没用了。 即作用域的范围是 在这一JSP网页 请求到另一 JSP网页之间,然后属性就会消失。 比如:新闻,用户看完后就失效了
  • session:客户端向用户端发送请求,产生的数据。 用户进行使用,会使用一定的时间。 但是当与服务端关闭后,即关闭浏览器,则就没用了。
  • application:客户端向服务端发送请求,产生的数据。 这个用户用完,其它用户还能使用。 范围在服务器一开始执行服务,到服务器关闭为止。它的范围最大,生存周期最长。

不同的作用域它们之间的关系

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第12张图片

2.6、jsp标签、jstl标签、EL表达式

在使用这些标签的时候,需要相应的 jar包。

pom.xml文件中 导入maven依赖


<dependency>
    <groupId>javax.servlet.jsp.jstlgroupId>
    <artifactId>jstl-apiartifactId>
    <version>1.2-rev-1version>
dependency>


<dependency>
    <groupId>javax.servlet.jsp.jstlgroupId>
    <artifactId>jstlartifactId>
    <version>1.2version>
dependency>


<dependency>
    <groupId>taglibsgroupId>
    <artifactId>standardartifactId>
    <version>1.1.2version>
dependency>
dependencies>

project>

EL表达式: ${}

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象

我们使用美元符号大括号进行 获取数据和执行运算。

2.6.1、jsp标签

jsp:forward page 页面跳转标签

  1. 在jsptag.jsp中写入一个程序,并指定跳转页面。 去观察跳转的结果。

    定义一个页面,功能就是用来跳转的,并给这个页面一些数据信息

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Titletitle>
    head>
    <body>
    <h1>1h1>
    <%--jsp:include  jsp标签--%>
    <%--页面跳转标签 jsp:forward page --%>
    <jsp:forward page="jsptag2.jsp">
        <jsp:param name="name" value="ALZN"/>
        <jsp:param name="age" value="18"/>
    jsp:forward>
    body>
    html>
    
  2. 对应的跳转页面 jsptag2.jsp。 利用request.getParameter() 去获取信息。

    功能是用来得到来自跳转页面的信息。用来展示信息的:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
<h1>2h1>
<%--取出参数
<%=变量名%>    <${}>   这两种方式等价
--%>
<%--取出参数--%>

名字:<%=request.getParameter("name")%>
年龄:<%=request.getParameter("age")%>
body>
html>

获取参数的两种方式:

  • =变量名
  • ${}

3.这种 jsp 标签页面跳转。 是不需要像 Servlet程序那样进行 web发布的。 直接启动Tomcat进行测试就行了。

输入:http://localhost:8080/jsptag.jsp 结果为:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第13张图片

可以发现, 我们定义的 jsptag.jsp 页面就是会直接发生跳转,响应到 jsptag2.jsp的信息。但是url路径却没变。

2.6.2、JSTL标签

关于JSTL标签的简单使用链接:https://www.runoob.com/jsp/jsp-jstl.html

JSTL表达式:

  • JSTL标签库的使用是为了弥补HTML标签的不足
  • 自定义许多标签,供我们使用,
  • 标签的功能和 java 代码一样

JSTL标签:

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

核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:

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

标签 描述
用于在JSP中显示数据,就像<%= … >
用于保存数据
用于删除数据
用来处理产生错误的异常状况,并且将错误信息储存起来
与我们在一般程序中用的if一样
本身只当做的父标签
的子标签,用来判断条件是否成立
的子标签,接在标签后,当标签判断为false时被执行
检索一个绝对或相对 URL,然后将其内容暴露给页面
基础迭代标签,接受多种集合类型
根据指定的分隔符来分隔内容并迭代输出
用来给包含或重定向的页面传递参数
重定向至一个新的URL.
使用可选的查询参数来创造一个URL

JSTL标签库使用步骤

  1. 引入对应的 taglib
  2. 使用其中的方法
  3. 在Maven中也需要引入 jstl 的包,否则就会报错: JSTL解析错误

例子:

在coreif.jsp文件下:

  1. 导入对应的taglib: 这个和前面的 <%@ include 类似。

    • 引入JSTL核心标签库, 我们才能去使用JSTL标签 core
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
  2. 使用其中的方法: 。 这里面的代码形式和 java代码一样

    if代码测试

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%-- 引入JSTL核心标签库, 我们才能去使用JSTL标签 core--%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
    
        Title
    
    
    

    if测试


    <%--使用EL表达式获取表单中的数据 ${param.参数名} --%>
    <%--判断 如果用户提交的是管理员,则登录成功--%>

corewhen.jsp文件下测试 jstl标签库中的 , 条件判断是否成立。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    Title


<%--定义一个变量score,值为85--%>



    
        你的成绩为优秀
    
    
        你的成绩为一般
    
    
        你的成绩为良好
    
    
        你的成绩为不及格
    




coreforeach.jsp文件下测试:。 进行遍历:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.ArrayList" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    Title


<%
    ArrayList people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田七");
    request.setAttribute("list",people);
%>

<%--
var , 每一次遍历出来的变量
items, 要遍历的对象
begin,   哪里开始
end,     到哪里
step,   步长
--%>

     


3、JavaBean

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用来和数据库的字段做映射 ORM;

ORM:对象关系映射

  • 表 —> 类
  • 字段 —> 属性
  • 行记录 —> 对象

people表:

id name age address
1 鑫仔1号 1 山西
2 鑫仔2号 2 山西
3 鑫仔3号 3 山西

这个表去对应位一个类的话:

class People{
   private int id;
   private String name;
   private String adress
 }
class A{
    new People(1,"鑫仔1号",1,"山西");
    new People(2,"鑫仔2号",2,"山西");
    new People(3,"鑫仔3号",3,"山西");
}

JavaBean 例子:

  1. people类 java程序。

    属性私有化:即 private, 这种属性子类不能直接继承,需要get/set方法去将属性创建为一些公共属性去进行调用。

    package com.AL.pojo;
    
    public class people {
        private int id;
        private String name;
        private int age;
        private String address;
    
        public people() {
        }
    
        public people(int id, String name, int age, String address) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        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 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;
        }
    
        @Override
        public String toString() {
            return "people{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
  2. 创建数据库。 数据库为jdbc,表名为people:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第14张图片

  1. 创建javabean.jsp文件。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    
    
    <%--
    换行
    是html标签 表示一条直线 --%> 姓名: 年龄: id: 地址:

启动Tomcat进行测试:http://localhost:8080/javabean.jsp

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第15张图片

4、MVC三层架构

什么是MVC:Model View Controller 模型、视图、控制器

4.1、以前的架构

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第16张图片

用户直接访问控制层,控制层就可以直接操作数据库

就好比,我们前面创建的一个javaweb的 Servlet程序+jsp。 不过jsp主要是用来渲染界面的,虽然本质上也是一个Servlet。 客户端访问服务端,我们在Servlet程序中接收到请求 req, 然后回响应 resp。而当加入数据库后,直接在Servlet代码中进行 JDBC的工作,处理数据库的数据, 然后把操作得到的数据返回给客户端,并且你改了数据还要在服务端中对数据库完成同步 数据持久化。 代码臃肿,不利于维护。

servlet–CRUD–>数据库
弊端:程序十分臃肿,不利于维护 (要在Servlet里面写JDBC的代码)
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的!
程序猿调用
|
JDBC (实现该接口)
|
Mysql Oracle SqlServer …(不同厂商)

4.2、MVC三层架构

改进:MVC架构如下所示, Model、View、Controller

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第17张图片

三层架构中,各自主要负责的功能为

Model

  • 业务处理 :业务逻辑(Service)
  • 数据持久层:CRUD (Dao - 数据持久化对象)

View

  • 展示数据
  • 提供链接发起Servlet请求 (a,form,img…)

Controller (Servlet)

  • 接收用户的请求 :(req:请求参数、Session信息….)
  • 交给业务层处理对应的代码
  • 控制视图的跳转
    • 登录—>接收用户的登录请求—>处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)—>Dao层查询用户名和密码是否正确–>数据库

在MVC三层架构中, 我们不再让Servlet独自一人完成刚才的 请求、响应、视图跳转、JDBC、业务代码等工作。

  • 我们让Servlet程序 作为一个控制器 Controller,处理请求,然后去调用Model中的 service层进行业务处理,响应完成后去调用 view 视图层进行视图跳转。
  • View专心的渲染视图,展现给用户页面; 并且接收客户端的链接 去发送请求
  • Model 模型中分为 Service 业务层专门进行业务逻辑处理; Dao层进行底层的数据库处理,完成数据持久化。

5、过滤器 Filter

5.1、Filter

Filter:过滤器,用来过滤网站的数据

  • 处理中文乱码
  • 登陆验证

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第18张图片

5.2、写过滤器

  1. 创建maven项目。导入maven依赖,这里特地增加了 数据库连接的依赖。

    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
    
        <groupId>com.ALgroupId>
        <artifactId>javaweb-filterartifactId>
        <version>1.0-SNAPSHOTversion>
        <dependencies>
            
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>servlet-apiartifactId>
                <version>3.0-alpha-1version>
            dependency>
            
            <dependency>
                <groupId>javax.servlet.jspgroupId>
                <artifactId>javax.servlet.jsp-apiartifactId>
                <version>2.3.3version>
            dependency>
            
            <dependency>
                <groupId>javax.servlet.jsp.jstlgroupId>
                <artifactId>jstl-apiartifactId>
                <version>1.2-rev-1version>
            dependency>
            
            
            <dependency>
                <groupId>javax.servlet.jsp.jstlgroupId>
                <artifactId>jstlartifactId>
                <version>1.2version>
            dependency>
            
            <dependency>
                <groupId>taglibsgroupId>
                <artifactId>standardartifactId>
                <version>1.1.2version>
            dependency>
            
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.47version>
            dependency>
        dependencies>
    
    project>
    
  2. 编写过滤器 filter类。

    • 我们想要去进行过滤所有的代码,让其进行编码 UTF-8。 新建一个 CharacterEncodingFilter 类。

    • 注意:此时的过滤器导入的包为 java.servlet.*

    • package com.AL.filter;
      
      import javax.servlet.*;
      import java.io.IOException;
      
      public class CharacterEncodingFilter implements Filter {
          // 初始化: web服务器启动,就已经初始化了,随时等待过滤对象出现
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("CharacterEncodingFilter初始化");
          }
          //Chain:链
          /*
           * 1.过滤中的所有代码,在过滤特定请求的时候都会执行
           * 2.必须要让过滤器继续同行
           * chain.doFilter(request,response);
           * */
      
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              servletRequest.setCharacterEncoding("utf-8");
              servletResponse.setCharacterEncoding("utf-8");
              servletResponse.setContentType("text/html;charset=UTF-8");
      
              System.out.println("CharacterEncodingFilter执行前");
              filterChain.doFilter(servletRequest,servletResponse); //让我们的请求继续走,如果不写的话,程序到这里就被拦截停止
              System.out.println("CharacterEncodingFilter执行后");
          }
      
          // 销毁: web服务器关闭的时候,过滤器就会被销毁
          public void destroy() {
              System.out.println("CharacterEncodingFilter销毁");
          }
      }
      
  3. 编写Servlet类。

    新建一个showFilter,servlet程序。添加编码和没有编码,分别进行调试:

    注意:如果有1000个servlet程序响应, 那么我们就要输1000次编码 utf-8。 所以我们想要过滤器去做这件事情。

    package com.AL.servlet;
    
    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 ShowServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setCharacterEncoding("utf-8");
            resp.getWriter().write("你好,李焕英!");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    
  4. 编写web.xml配置文件.

    • 注册Servlet类和 Servlet的映射路径。定义两种 添加编码和没有编码,分别进行调试: 即一种

    • 过滤器 filetr的注册和映射路径。

    • 
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
               version="4.0">
      
          <servlet>
              <servlet-name>ShowServletservlet-name>
              <servlet-class>com.AL.servlet.ShowServletservlet-class>
          servlet>
          <servlet-mapping> 
              <servlet-name>ShowServletservlet-name>
              <url-pattern>/servlet/showurl-pattern>
          servlet-mapping>
          <servlet-mapping> 
              <servlet-name>ShowServletservlet-name>
              <url-pattern>/showurl-pattern>
          servlet-mapping>
      
      
          <filter>
              <filter-name>CharacterEncodingFilterfilter-name>
              <filter-class>com.AL.filter.CharacterEncodingFilterfilter-class>
          filter>
          
          
          <filter-mapping>
              <filter-name>CharacterEncodingFilterfilter-name>
              <url-pattern>/servlet/*url-pattern>
          filter-mapping>
      
      web-app>
      

启动Tomcat进行测试。

  • 没有经过过滤器 filter的servlet程序。 输入 localhost:8080/show.结果为:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第19张图片

  • 经过过滤器 filter的servlet程序。 输入 **localhost:8080/servlet/show.**结果为:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第20张图片

设计一个过滤器的步骤:

  • 编写一个过滤器 filetr类。实现Filter接口
  • web.xml配置文件中注册过滤器

在 servlet程序和服务器之间添加一些过滤器,完成请求和响应的一些功能,解决乱码和过滤不必要的请求。

6、监听器

实现一个监听器的接口;(有N种接口)

  1. 编写一个监听器。 即实现一个监听器的接口就行。
  2. web.xml文件中注册监听器

例子:

统计网站在线人数

  1. 编写一个 session的监听器程序。 在服务器中存储这种 网站在线人数的信息, 不存放在 cookie里面。

    • 创建session监听:每次创建session,就触发httpSessionEvent 事件。观察得到的ID

    • 销毁session监听

    package com.AL.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class OnlineCountListener implements HttpSessionListener {
        //创建 session监听: 查看你的一举一动
        // 一旦创建了 Session就会触发一次这个事件
        public void sessionCreated(HttpSessionEvent httpSessionEvent) {
            ServletContext ctx = httpSessionEvent.getSession().getServletContext();
    
            System.out.println(httpSessionEvent.getSession().getId());
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    
            if (onlineCount == null){
                onlineCount = new Integer(1);
            }else {
                int count = onlineCount.intValue();
                onlineCount = new Integer(count+1);
            }
            ctx.setAttribute("OnlineCount", onlineCount);
        }
    
        //销毁session监听
        //一旦销毁Session就会触发一次这个事件!
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            ServletContext ctx = httpSessionEvent.getSession().getServletContext();
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    
            if (onlineCount == null){
                onlineCount = new Integer(1);
            }else {
                int count = onlineCount.intValue();
                onlineCount = new Integer(count-1);
            }
            ctx.setAttribute("OnlineCount", onlineCount);
        }
    }
    
  2. 在index.jsp中去获得在线人数的数据,用于界面展示:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
      
        $Title$
      
      
      

    当前有 <%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>人在线

  3. 配置文件web.xml监听事件的注册:

    
        <listener>
            <listener-class>com.AL.listener.OnlineCountListenerlistener-class>
        listener>
    
  4. 添加测试:查看是有几个,具体标号

    //查看具体标号
    System.out.println(httpSessionEvent.getSession().getId());
    

多开几个浏览器进行测试。此时java控制台显示的3个人的标号 getId. 三个人在线。

E94BC8A2E7DF88FE4397B8A0D0C032E4
DD3304FD19601E9BC73FF08F3AE96B81
123623BDC7FAE4355487EEEE0F801047

session销毁有自动和手动两种方式,如下所示:

  • 手动销毁

        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            ServletContext ctx = httpSessionEvent.getSession().getServletContext();
            httpSessionEvent.getSession().invalidate();//手动销毁
    
  • 自动销毁

    
        <session-config>
            <session-timeout>1session-timeout>
        session-config>
    

7、监听器和过滤器的常见应用

7.1、监听器GUI中理解

监听事件的例子:

package com.AL.listener;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

//监听事件的例子
public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("中秋节快乐");  //新建一个窗体
        Panel panel = new Panel(null); //面板
        frame.setLayout(null); //设置窗体的布局

        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,255)); //设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,0)); //设置背景颜色

        frame.add(panel);

        frame.setVisible(true);

        //监听事件,监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
            }
        });
    }
}

7.2、Filter实现权限拦截

  • 用户登录之后才能进入主页。
  • 用户注销后不能进入主页。

1.登录界面 login.jsp

在这里定义登录界面, 使用 post方法去获取页面前端参数。 请求路径为 /servlet/login。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


登录

2.创建一个 servlet程序

获取前端的数据后,进行重定向,实现页面跳转。 方法和前端处的一样为 post。

package com.AL.servlet;

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 LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取前端请求的参数
        String username = req.getParameter("username");

        if (username.equals("admin")){ //登录成功
            req.getSession().setAttribute("USER_session", req.getSession().getId());
            resp.sendRedirect("/sys/success.jsp");
        } else { //登录失败
            resp.sendRedirect("/error.jsp");
        }
    }

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

3.定义登录成功和失败的 jsp页面

注意路径,success.jsp在 sys目录下。 error.jsp在同一级目录下。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


主页

注销

error.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


错误

没有权限,用户名错误

返回登录界面

4.web.xml配置文件。


    <servlet>
        <servlet-name>LoginServletservlet-name>
        <servlet-class>com.AL.servlet.LoginServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>LoginServletservlet-name>
        <url-pattern>/servlet/loginurl-pattern>
    servlet-mapping>
    <servlet>
        <servlet-name>LogoutServletservlet-name>
        <servlet-class>com.AL.servlet.LogoutServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>LogoutServletservlet-name>
        <url-pattern>/servlet/logouturl-pattern>
    servlet-mapping>

启动Tomcat进行测试:在浏览器中输入 localhost:8080/login.jsp, 然后在接收到请求后,即提交动作 submit会 会在web.xml文件中找到此Servlet的注册信息去进行 servlet ,对前端客户端的信息进行获取,然后去响应 进行重定向 页面跳转。

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第21张图片

成功进入登录页面:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第22张图片

在用户名错误的时候:

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第23张图片

无法登录成功.

但是在测试的时候,你直接输入http://localhost:8080/sys/success.jsp 也会直接进入 登录成功的页面。 我们要使用过滤器 去阻止这种操作。 页面拦截的作用

5.过滤器拦截。

对于登录成功的页面:/sys/success.jsp 这个界面。 我们设置了一个 USER_SESSION 去获取 session的ID, 当ID==null的时候,这说明没有进行页面登录中进行登录成功的 事件, 所以会直接拦截,让其去跳转到 错误页面。

package com.AL.filter;

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

public class SysFilter implements Filter {
    // 初始化: web服务器启动,就已经初始化了,随时等待过滤对象出现
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    //SysFilter过滤器
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        if (request.getSession().getAttribute("USER_SESSION") == null) {
            response.sendRedirect("/error.jsp");
        }
        chain.doFilter(request, response);
    }
    // 销毁: web服务器关闭的时候,过滤器就会被销毁
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}

在拦截器 Servlet接口实现类的步骤:

  • 初始化。public void init(FilterConfig filterConfig) throws ServletException{} 在web服务器启动的时候,就会初始化,然后去随时等待过滤对象出现
  • 过滤器。doFilter。 此时的过滤器 拦截器作用是 sessiID为空的时候,就让其去跳转到错误界面
  • ==销毁。destroy() 。==web服务器关闭的时候,过滤器就会被销毁

6.过滤器的web.xml配置文件信息。

    <filter>
        <filter-name>SysFilterfilter-name>
        <filter-class>com.AL.filter.SysFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>SysFilterfilter-name>
        <url-pattern>/sys/*url-pattern>
    filter-mapping>

启动Tomcat进行测试,直接输入:localhost:8080/sys/success.jsp 发现此时无法将纳入登录成功的页面:
JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第24张图片

8、JDBC

简单的来说 JDBC就是一个统一驱动, 用于 java去连接 数据库驱动。

JavaWeb(二):Cookie、Session、JSP、过滤器和监听器、JDBC_第25张图片

我们在 mysql数据库学习中, 在IDEA中去进行JDBC练习时,导入的jar包有:

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java… 连接驱动(必须要导入)

在这里,我们使用Maven,创建 maven项目后,直接导入 maven的依赖即可:

<dependencies>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.47version>
    dependency>
dependencies>

创建数据库:

CREATE TABLE `users` (
  `id` INT(11) NOT NULL,
  `name` VARCHAR(40) DEFAULT NULL,
  `password` VARCHAR(40) DEFAULT NULL,
  `email` VARCHAR(40) DEFAULT NULL,
  `birthday` DATE DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

向其中添加几组数据: 例子:

-- 注意,在进行创建数据库的时候, 关于 列表名 column 要使用 飘号进行包裹, 而不是单引号,
-- 因为在这里的意义不是字符串,而是属性段
INSERT INTO `users`(`id`,`name`,`password`,`email`,`birthday`)
VALUES('3','坤坤','123456','[email protected]','2021-1-1'),('4','略略','123456','[email protected]','2021-1-1')

INSERT INTO `users`(`id`,`name`,`password`,`email`,`birthday`)
VALUES('5','坤坤','123456','[email protected]','2021-1-1');

INSERT INTO `users`(`id`, `name`, `password`, email, birthday)
VALUES(6,'呜呜','123456','[email protected]','2021-1-1');

8.1、JDBC的步骤和执行SQL的对象 Statement、PreparedStatement

JDBC的步骤,整个流程:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement : CRUD
  4. 编写SQL (根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接(先开的后关)

普通的SQL执行对象 Statement

  • Statement statement = connection.createStatement(); 创建一个去执行SQL的对象。 简单来说,就是把 sql语句丢给这个对象 statement里面去执行。
  • 查询使用executeQuery. 增删改使用executeUpdate()
package com.AL.test;

import java.sql.*;

public class TestJdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 数据库的配置信息
        // useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";
        
        // 1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.连接数据库, 代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        // 3. 向数据库发送 SQL的对象 Statement: CRUD.  用这个对象去完成 操作CRUD
        Statement statement = connection.createStatement();
        // 4.编写 SQL语句
        String sql = "select * from users";
        // 5.使用 statement 即能够执行sql的对象   去 进行具体的sql语句。  查询语句返回的是一个结果集: ResultSet
        ResultSet rs = statement.executeQuery(sql); // 查询使用executeQuery. 增删改使用executeUpdate()

        while (rs.next()){
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }

        // 6.关闭连接,释放资源。  遵循先开后关的原则
        rs.close();
        statement.close();
        connection.close();
    }
}

采用预编译的方法

  • 即使用占位符 ?的 方式去进行编译 sql语句。
  • 使用 PreparedStatement preparedStatement = connection.prepareStatement(sql);
package com.AL.test;

import java.sql.*;

public class TestJDBC2 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 数据库的配置信息
        // useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        // 1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.连接数据库, 代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        // 3. 编写 SQL。  使用占位符 ?
        String sql = "insert into users(`id`, `name`, `password`, `email`, `birthday`) values(?,?,?,?,?);";

        // 4. 预编译.   向数据库发送 SQL的对象 PreparedStatement: CRUD.  用这个对象去完成 操作CRUD
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,7); //给第一个占位符?的赋值为 1;
        preparedStatement.setString(2, "乌日三省吾身");
        preparedStatement.setString(3,"787878");
        preparedStatement.setString(4,"[email protected]");
        preparedStatement.setString(5, String.valueOf(new Date(new java.util.Date().getTime())));

        // 5.使用 preparedStatement 即能够执行sql的对象   去 进行具体的sql语句。
        // 查询语句返回的是一个结果集: ResultSet.查询使用executeQuery.
        // 增删改使用executeUpdate(). 返回的是一个
        int i = preparedStatement.executeUpdate();
        if (i>0) System.out.println("插入成功");

        // 6.关闭连接,释放资源。  遵循先开后关的原则
        preparedStatement.close();
        connection.close();
    }
}

8.2、JDBC事务

事务的性质: ACID原则:原子性、一致性、隔离性、持久性

事务

  • 要么都成功,要么都失败!
  • ACID原则:保证数据的安全。

事务完成的步骤

  1. 开启事务
  2. 事务提交 commit()
  3. 事务回滚 rollback()
  4. 关闭事务

需要导入的jar包: Junit单元测试

    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
    dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!

@Test
public void test(){
    System.out.println("Hello");
}

搭建一个环境去设计事务: 银行转账

创建数据库:

-- 创建账单 account  数据表
CREATE TABLE `account`(
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET = utf8

INSERT INTO  `account`(`name`,`money`) 
VALUES ('A',2000.00),('B',1000); 
-- 此时输入的A是字符串的意思,并不是表名,所以用单引号,不用`。

JDBC程序:

  1. 数据库配置信息,加载驱动
  2. 连接数据库,
  3. 创建能够代表数据库去执行SQL的对象 Statement:CRUD
  4. 编写 SQL语句
  5. 执行SQL
  6. 关闭连接。

但是需要添加事务回滚 rollback, 所以采用 try catch方法去进行判断:事务失败则回滚

package com.AL.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC3 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 数据库的配置信息
        // useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

            // 1.加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.连接数据库, 代表数据库
             Connection connection = DriverManager.getConnection(url, username, password);
//            // 3. 向数据库发送 SQL的对象 Statement: CRUD.  用这个对象去完成 操作CRUD
//            Statement statement = connection.createStatement();
        try {
            // 3.通知数据库开启事务, false开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-1000 where name='A';";
            connection.prepareStatement(sql).executeUpdate();

            // 制造错误
            //int i =1/0;
            String sql2 = "update account set money = money-200 where name='B';";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit(); //以上两条SQL都执行成功了,就提交事务
            System.out.println("success");
        } catch (Exception e) {
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            }catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(过滤器,javabean,java)