zoukankan      html  css  js  c++  java
  • JavaWeb学习笔记

    内容

     

    01.web基本概念

    技术栈:Servlet/Jsp,Asp,PHPN

    动态web

     

    02.web服务器

    2.1 web 语言

    ASP:

    • C# IIS

    • 微软:国内最早流行的就是ASP

    • 在HTML中嵌入VB脚本,ASP+COM

    • 在ASP开发中,基本一个页面都有几千行的业务代码,极其混乱。

    • 维护成本高。

    <% system.out.pringln("hello")%>

    PHP:

    • PHP开发速度很快,功能很强大,跨平台,代码很简单(中国70%网站都是中小型都用PHP)。

    • 无法承载流量大的情况。

    JSP/servlet:

    • sun公司主推的B/S架构

    • 基于JAVA语言(所有大公司,或者一些开源组件,都是java写的)

    • 可以承载三高的问题

    2.2 web服务器

    IIS :

    • ASP,windows自带

    Tomcat:

    • Apache基金会核心项目之一。

    • 完美支持JSP/servlet标准。

    • 支持技术先进,性能稳定,免费。

    • 开源,轻量级,适合中小企业和并发不高的场合。

    • 处理静态html不如Apache。

     

    03 HTTP

    http1.0:客户端和服务器连接后,只能获取一个web资源,断开连接。

    http1.1:客户端和服务器连接后,可以获得多个web资源。

     

    04 Maven

    javaweb开发中,需要使用大量的jar包,我们手动去导入。

    Maven的核心思想:约定大于配置!

    4.1. IDEA中配置Maven

    • 配置一个包含基本包的项目(不勾选就是最干净的Maven项目)

    • 自动下载源码

     

    • 配置Tomcat

       

       

       

       

    4.2 pom文件

    Tomcat服务器的web目录

    pom.xml是Maven的核心配置文件

    maven仓库

    https://mvnrepository.com/

    maven会导入这个JAR包所依赖的其他JAR包;

    maven由于约定大于配置,之后例如mybatis里可能会遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:

    //在build中配置resources
         <!--在build中配置resources,来防止我们资源导出失败的问题-->
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                </resource>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>

    日志排错

    启动项目后不能打开Tomcat原来的examples/ROOT等项目。解决

    05 Servlet

    5.1 导HttpServlet包思路

    • 快捷键Alt+Ent Maven导入本地没有

    • Maven仓库也没有

    • 最后联想到Tomcat对servlet有很强的支持。所以去Tomcat的lib目录下找,找到。(Servlet-api,返回Maven仓库去找,使用人数最多的那个。)

    5.2 未走数据库

    需要两个东西,Class类+类的web.xml配置映射

    public class HelloServlet extends HttpServlet {
    ​
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/html");
            PrintWriter writer = resp.getWriter();
            writer.println("<html>");
            writer.println("hello,servlet!");
            writer.println("</html>");
        }
    ​
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    }
    <!--web.xml中是配置web的核心应用-->
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      
      <!--注册servlet-->
      <servlet>
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
      </servlet>
      <!--一个servlet有一个mapping-->
      <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <!--请求路径-->
        <url-pattern>/UrltohelloServlet</url-pattern>
      </servlet-mapping></web-app>

    访问localhost/项目名/Urltohelloservlet

    servlet出现405错误

    5.3 servlet原理

    建立子项目,删掉项目里的src目录,再在这个项目里建立Module。

    5.4 mapping问题

    1. 一个servlet可以指定一个映射路径

    2. 一个servlet可以指定多个映射路径

    3. 一个servlet可以指定通用映射路径(*通配符)

    4. 指定一些前缀或者后缀等...

      <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>/secendurl</url-pattern>
      </servlet-mapping>
      <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>*must</url-pattern>
         /*/xxx/*must不行*/
      </servlet-mapping>
    • 优先级

    指定了固定的映射路径 > 通配

    5.5 getServletContext()

    • servlet里的一些方法

    public class HelloServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        this.getInitParameter()  初始化参数  对应web.xml里<init-param>
    //        this.getServletConfig()  Servlet配置  对应web.xml全部配置
    //        this.getServletContext()  Servlet上下文  重点
            ServletContext servletContext = this.getServletContext();
        }
    }

    web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象。它代表了当前的web应用。

    应用

    1.共享数据

    在一个Servlet中保存数据(任何数据都可以保存),可以在另一个Servlet中拿到。

    #HelloServlet.class中保存

    public class HelloServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        this.getInitParameter()  初始化参数  对应web.xml里<init-param>
    //        this.getServletConfig()  Servlet配置  对应web.xml全部配置
    //        this.getServletContext()  Servlet上下文  重点
            ServletContext servletContext = this.getServletContext();
    ​
            servletContext.setAttribute("username", "xiaoyang");
        }
    }
    ​

    #GetServlet.class中拿到,并在网页打印

    public class GetServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext servletContext = this.getServletContext();
            Object username = servletContext.getAttribute("username");
    ​
            resp.setContentType("text/html;utf-8");
            resp.getWriter().print(username.toString());
        }
    }

    #别忘了web.xml文件

    <web-app>
      <display-name>Archetype Created Web Application</display-name>
    
      <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
      </servlet-mapping>
    
      <servlet>
        <servlet-name>getc</servlet-name>
        <servlet-class>GetServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
      </servlet-mapping>
    </web-app>

    访问一次localhost/hello数据存储,访问一次localhost/getc拿到数据

    2.获得初始化参数

    #testgetServletContext.class

    public class TestgetServletContext extends HttpServlet  {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext servletContext = this.getServletContext();
            String jdbcUrl = servletContext.getInitParameter("jdbcUrl");
    
            resp.getWriter().print(jdbcUrl);
        }
    }

    #web.xm

      <context-param>
        <param-name>jdbcUrl</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
      </context-param>
    
      <servlet>
        <servlet-name>gp</servlet-name>
        <servlet-class>TestgetServletContext</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>gp</servlet-name>
        <url-pattern>/gp</url-pattern>
      </servlet-mapping>

    访问localhost/gp

    3.请求转发

    #testDispatch.class

    public class TestDispatch extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext servletContext = this.getServletContext();
            resp.getWriter().print("hello<br>");
            servletContext.getRequestDispatcher("/gp").forward(req, resp);
        }
    }

    #web.xml

      <servlet>
        <servlet-name>td</servlet-name>
        <servlet-class>TestDispatch</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>td</servlet-name>
        <url-pattern>/td</url-pattern>
      </servlet-mapping>

    访问/td,得到gp的资源。并且打开F12,状态码200说明,转发 ≠ 重定向。

    4.读取资源文件(项目中大量运用) -> 失败

    Properties

    • 在java目录下新建properties

    • 在resources目录下新建properties。发现都被打包到了同一个路径下。

    #db.properties

    username = xiaoyang
    password = 1234

    新建后RUN一下,在target/项目/WEB_INFF/classes下生成properties文件【如果没有生成,则考虑04Maven里"约定大于配置",在pom文件里配置一下<build>

    #TestgetResource.class

    public class TestgetResource extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //得到一个文件流
            InputStream is = this.getServletContext().getResourceAsStream("/WEB_INF/classes/db.properties");
    
            Properties prop = new Properties();
            //加载这个流
            prop.load(is);
    
            resp.getWriter().print(prop.getProperty("username").toString());
            resp.getWriter().print(prop.getProperty("password").toString());
    
        }
    }

    #web.xml

      <servlet>
        <servlet-name>tr</servlet-name>
        <servlet-class>TestgetResource</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>tr</servlet-name>
        <url-pattern>/tr</url-pattern>
      </servlet-mapping>

    5.6 HttpServletResponse

    web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpservletRequest对象,代表响应的一个HttpservletResponse;

    • 如果要获取客户端请求过来的参数:找HttpservletRequest

    • 如果要给客户端响应一些信息:找HttpServletResponse

    1. 方法简单分类

    负责向浏览器发送数据的方法

        ServletOutputStream getOutputStream() throws IOException;
        PrintWriter getWriter() throws IOException;

    负责向浏览器发送响应头

        void setCharacterEncoding(String var1);
        void setContentLength(int var1);
        void setContentLengthLong(long var1);
        void setContentType(String var1);
        void setDateHeader(String var1, long var2);
        void addDateHeader(String var1, long var2);
        void setHeader(String var1, String var2);
        void addHeader(String var1, String var2);
        void setIntHeader(String var1, int var2);
        void addIntHeader(String var1, int var2);

    2.常见应用

    1. 向浏览器输出消息

      上面演示很多

    2. 下载文件

    过程:要获取下载文件的路径;文件名;想办法让浏览器能够支持下载;获取下载文件的输入流;创建缓冲区;获取 OutputStream对象;将FileOUtputStream流写入到buffer缓冲区;使用OutputStream将缓冲区中的数据输出到客户 端。

    #FileServlet.class 太老了,现在一般不用

      public class FileServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //要获取下载文件的路径;
              String realPath = this.getServletContext().getRealPath("E:\Java项目\javaweb-servlet\servlet-03-response\target\classes\2.png");
              System.out.println("real-path"+realPath);
              // 文件名;
              String filename = realPath.substring(realPath.lastIndexOf("\") + 1);
              // 想办法让浏览器能够支持下载;
              resp.setHeader("Content-Disposition", "attachment;filename="+filename);
              // 获取下载文件的输入流;
              FileInputStream in = new FileInputStream(realPath);
              // 创建缓冲区;
              int len = 0;
              byte[] buffer = new byte[1024];
              // 获取OutputStream对象;
              ServletOutputStream out = resp.getOutputStream();
              // 将FileOUtputStream流写入到buffer缓冲区;使用OutputStream将缓冲区中的数据输出到客户端。
              while ((len=in.read(buffer)) != -1) {
                  out.write(buffer, 0, len);
              }
              in.close();
              out.flush();
              out.close();
          }
      }
    1. 验证码功能

      前端实现

      后端实现,需要i用到Java的图片类,生产一个图片。

      #ImageServlet

      public class ImageServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //自动3秒刷新
              resp.setHeader("refresh", "3");
      
              //在内存中创建一个图片
              BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
              //得到图片
              Graphics2D g = (Graphics2D) image.getGraphics();////设置图片的背景颜色
              g.setColor(Color.WHITE);
              g.fillRect(0, 0, 80, 20);
              //给图片写数据
              g.setColor(Color.BLUE);
              g.setFont(new Font(null, Font.BOLD, 20));
              g.drawString(makeNum(), 0, 20);
      
              //告诉浏览器,这个请求用图片的方式打开
              resp.setContentType("image/png");
              resp.setDateHeader("expires", -1);
              resp.setHeader("Cache-Control", "no-cache");
              resp.setHeader("Pragma", "no-chche");
      
              //把图片写给浏览器
              ImageIO.write( image, "jpg", resp.getOutputStream());
          }
      
          //生成随机数
          private String makeNum(){
              Random random = new Random();
              String num = random.nextInt(9999999) + "";
              StringBuffer stringBuffer = new StringBuffer();
              for (int i = 0; i < 7 - num.length(); i++) {
                  stringBuffer.append("0");
              }
              num = stringBuffer.toString() + num;
              return num;
          }
      }
        <servlet>
          <servlet-name>imageservlet</servlet-name>
          <servlet-class>ImageServlet</servlet-class>
        </servlet>
        <servlet-mapping>
          <servlet-name>imageservlet</servlet-name>
          <url-pattern>/image</url-pattern>
        </servlet-mapping>

      4 实现重定向

      B一个web资源收到客户端A请求后,B通知A去访问另一个web资源C,这个过程叫重定向。

      方式1
      response.setStatus(302);
      response.setHeader("location", "/s3/image");
      方式2
      response.sendRedirect("/s3/image");

    5.7 HttpServletRequest

    HTTP请求中的所有信息会被封装到HTtpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息。

    用到jsp,则需要在父项目pom文件导入jsp包。

    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.2.1</version>
        <scope>provided</scope>
    </dependency>

    1.获取前端传递的参数+请求转发

    主要用的方法

    #index.jsp

    <form action="/s4/login" method="post">
    用户名:<input type="text" name="username" required> <br>
    密码:<input type="password" name="passwd" required> <br>
    爱好:
    <input type="checkbox" name="hobbys" value="女孩">女孩
    <input type="checkbox" name="hobbys" value="代码">代码
    <input type="checkbox" name="hobbys" value="唱歌">唱歌
    <input type="checkbox" name="hobbys" value="电影">电影
    <br>
    <input type="submit">
    </form>

    #success.jsp 验证请求转发所用

    登录成功!

    #LoginServlet.java

    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
    
            String username = req.getParameter("username");
            String passwd = req.getParameter("passwd");
            String[] hobbys = req.getParameterValues("hobbys");
    
            System.out.println(username);
            System.out.println(passwd);
            System.out.println(hobbys.toString());
    
            System.out.println(req.getContextPath());
    
            //通过请求转发
            req.getRequestDispatcher("/success.jsp").forward(req, resp);
        }
    }

    #web.xml

      <servlet>
        <servlet-name>loginservlet</servlet-name>
        <servlet-class>LoginServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>loginservlet</servlet-name>
        <url-pattern>/login</url-pattern>
      </servlet-mapping>

    登录index.jsp提交表单

    5.8 Cookie

    cookie:

    • 一般会保存在本地的用户目录下appData下。

    • 由浏览器保存,不同的浏览器具有不兼容性。

    • 由浏览器主动向服务器提供,服务端只需getCookies就行。

    细节:

    • 一个cookie只能保存一个信息

    • 一个web站点最多存放20个cookie

    • cookie大小限制4kb

    • 300个cookie浏览器上限

    • 不设置有效期,关闭浏览器自动失效。

    • 控制台输入javascript:alert (document. cookie)可查看本网站下cookie

    服务器相应给客户端cookie:

    Cookie[] cookies = req.getCookies();//获得cookie
    cookie.getName();//获得cookie中的name
    cookie.getValue();//获得cookie中的value
    new Cookie("lastLoginTime", System.currentTimeMillis()+"");//新建一个cookie
    cookie.setMaxAge(0);//设置cookie有效期。为0即删掉
    resp.addCookie(cookie);//响应给客户端一个cookie

    #CookieDemo01.java

    //保存用户上一次访问的时间
    public class CookieDemo01 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
    
            PrintWriter writer = resp.getWriter();
    
            //cookie是从客户端获取
            Cookie[] cookies = req.getCookies();
            if (cookies != null){
                writer.write("您上一次访问的时间:");
                for (int i = 0; i < cookies.length; i++) {
                    //获取cookie名字
                    Cookie cookie = cookies[i];
                    if(cookie.getName().equals("lastLoginTime")){
                        //获取cookie的值
                        long ltime = Long.parseLong(cookie.getValue());
                        Date ddate = new Date(ltime);
                        writer.write(ddate.toLocaleString());
                    }
                }
            }else{
                writer.write("这是您第一次访问本站!");
            }
            //服务给客户端响应一个cookie
            Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
            //cookie有效期
            cookie.setMaxAge(24*60*60);
            resp.addCookie(cookie);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
    }

    #web.xml

      <servlet>
        <servlet-name>cookieDemo01</servlet-name>
        <servlet-class>CookieDemo01</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>cookieDemo01</servlet-name>
        <url-pattern>/lastlogintime</url-pattern>
      </servlet-mapping>

    5.9 Session(重点)

    • 服务器会给每一个用户(浏览器)创建一个Session对象;

    • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在;

    • 用户登录之后,整个网站都可以访问。

      场景:

      1. 保存一个登录用户的信息

      2. 购物车信息

      3. 整个网站中经常会使用的数据

    1. 设置一个session

    • set后session机制自动返回给用户一个cookie:sessionID

    • session还可保存对象等数据

    #SessionDemo01.java

    public class SessionDemo01 extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
    
            //得到Session
            HttpSession session = req.getSession();
            //给Session存东西
            session.setAttribute("name", "xiaoyang");
            //获取Session的ID
            String id = session.getId();
            //判断Session是不是新创建
            if(session.isNew()){
                resp.getWriter().write("session第一次创建成功 " + id);
            }else{
                resp.getWriter().write("session已经在服务器中存在 "+id);
            }
    
            //Session创建的时候做了什么事情
            /*
            Cookie jsessionid = new Cookie("JSESSIONID", id);
            resp.addCookie(jsessionid);
            */
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
    }
    <servlet-mapping>/setsession</servlet-mapping>

    2. 同一站点共享session

    #GetSession.java

    public class GetSession 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;chareset=utf-8");
    
            HttpSession session = req.getSession();
            String name = (String) session.getAttribute("name");
            System.out.println(name);
        }
    }
    <servlet-mapping>/getsession</servlet-mapping>

    #Servlet里getServletContext对象也可存储共享的数据。但一般用session。参见5.5

    3. 注销session

    1.关闭浏览器

    2.手动注销

    HttpSession session = req.getSession();
    session.removeAttribute("name");
    session.invalidate();

    3.设置注销时间(web.xml里)

    <session-config>
        <session-timeout>1</session-timeout>//一分钟后注销
      </session-config>

    4.补充两个会话机制

    场景:客户端A和客户端B想公用一个servlet资源(之前说的是一个客户端共享多个servlet资源),就需要引进不同作用域的会话机制。ServletContext/applicationContext。

     

    06 JSP

    JSP页面可以嵌入java代码,为用户提供动态数据;

    6.1 原理:

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

    JSP转变成servlet。路径:

    C:Userskenshin.IntelliJIdea2018.2system omcatUnnamed_javaweb-servletworkCatalinalocalhosts5orgapachejsp

    分析原理

    【RUN】后生成工作空间,访问index.jsp和hello.jsp

    打开hello_jsp.java

    HttpJspBase继承HttpServlet HttpServlet继承Servlet,所以最后JSP.java实现的是Servlet。

    初始化/注销

    熟悉不?Servlet里写入html元素。

    以下这些对象都可以在JSP页面中直接使用。

    大致原理图

    6.2 JSP基础语法

    九大内置对象

    out       out对象的API

    request     HttpServletRequest(作用域对象1

    response     HttpServletResponse

    config       Servletconfig

    session     HttpSession(作用域对象2

    //在page指令中配置如下信息,session将不可用
    <%@page session="false" %>

    application   ServletContext (作用域对象3

    page     HttpJasPage相当于普通java类的this(作用域对象4

    exception     Java.lang.Exception类的对象

    //设置错误页面
    index.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" %>
    error.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="index.jsp" isErrorPage="true" %>

    pageContext   代表JSP编译后的内容(也就是JSP页面的运行环境)。理所应当可以获得其他八个内置对象.(作用域对象5,算是吧

     

    四(五)个作用域对象都有方法:

    setAttribute(string name,Object o)

    getAttribute(string name)

    removeAttribute(string name)

    着重讲下pageContext

    1 范围参数

    pageContext多了一个指定范围的参数,不指定则默认page范围;范围参数有.APPLICATION_SCOPE,SESSION_SCOPE,REQUEST_SCOPE,PAGE_SCOPE。

    #page1

    #page2

    2 findAttribute

    pageContext多了一个方法:findAttribute(string name)。该方法会从小到大访问各个域page->application,拿到name的值。

    引入和跳转

    pageContext.forward(String url) 替代RequestDispatch.forward

    pageContext.include(String url) 替代include

     

    四种属性范围

    上面已经提到

    范围

    场景

    1. request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的

    2. session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐

    3. servletContext:如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在servletContext域中,像聊天数据

     

    6.3 JavaBean

    1. 什么是JavaBean

    JavaBean说白了就是一个普通的Java类,也称之为简单java对象——POJO(Plain ordinary Java Object),是Java设计中的一种设计模式,是一种基于Java平台的软件组件思想。

    类名+setter/getter/tostring

     

    2. 为什么要使用JavaBean

    封装,重用,可读。

    一般用来和数据库的字段做映射 ORM(对象关系映射 表->类 字段->属性 行记录->对象)。

     

    3. JSP行为--JavaBean

    JSP技术提供了三个关于JavaBean组件的动作元素,即JSP行为(标签),它们分别为:

    jsp:useBean【在JSP页面中查找javaBean对象或者实例化javaBean对象】

    jsp:setProperty【设置javaBean的属性】

    jsp:getProperty【获取javaBean的属性】

    <jsp:useBean id="person" class="pojo.Person" scope="page"/>
    
    <jsp:setProperty name="person" property="name" value="xiaoyang" />
    <jsp:setProperty name="person" property="id" value="1"/>
    <jsp:setProperty name="person" property="age" value="18"/>
    
    姓名:<jsp:getProperty name="person" property="name"/>
    id:  <jsp:getProperty name="person" property="id"/>
    年龄:<jsp:getProperty name="person" property="age"/>
    <%--获取从另一个表单传递过来的值--%>
    <jsp:useBean id="person" class="pojo.Person" scope="page"/>
    
    <jsp:setProperty name="person" property="age">//根据JavaBean属性名(or表单属性名)获取值
    <%--(注意JavaBean属性名要和表单属性名一致)--%> 
    <jsp:setProperty name="person" property="*">//按照类型自动匹配

    6.4 EL表达式

    1. 什么是EL表达式

    EL(Expression Language,表达式语言),EL表达式是用${}括起来的脚本,用来更方便读取对象中的属性,提交的参数,JavaBean,甚至集合!

    EL表达式如果找不到相应的对象属性,返回空白字符串“”而不是null,这是EL表达式最大的特点。

    EL依赖

    <!-- https://mvnrepository.com/artifact/javax.el/javax.el-api -->
    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.0</version>
    </dependency>

    2. EL表达式的作用

    获取各类数据

    1.获取域对象的数据

    //1.jsp
    <%
        application.setAttribute("name", "xiaoyang");//其他域也一样。
    %>
    //2.jsp
    ${name}

    之前讲到ServletContext时讲到findAttribute(String name),EL表达式在执行时会调用该方法。这也解释了为什么EL表达式仅仅通过标识符就可以获取到域对象的数据。

    查找顺序:从小到大:page > request > session > application。

    2.获取JavaBean的属性

    ${person.age}//等同于person.getAge()

    内部通过反射机制完成!

    3.获取集合的数据

    集合在开发中广泛被使用,EL很好支持了集合操作。可以非常方便地读取Collection和Map集合地内容

    如果有一个List,元素是Person
    
    //不使用EL
    <%
    List<Person> list = (list) session.getAttribute("list");
    out.write(list.get(0).getUsername()+"<br>");
    ...
    out.write(list.get(n).getUsername());
    %>
    
    //使用EL
    %{list[0].username}
    ...
    %{list[n].username}
    如果有一个Map,关键字是数字{1,2,..},元素是Person
    
    //使用EL
    ${map["1"].username}
    ...
    ${map["n"].username}
    
    *如果关键字是字符串{"aa","bb",...}
    则应使用这种方式:${map.aa.username}

    EL表达式配合JSTL标签可以很方便的迭代集合!

    3. EL运算符

    EL支持简单的运算:加减乘除取模,关系运算符,逻辑运算符,empty运算符,三母运算符。

    关系运算符           逻辑运算符
    ==   或  eq        &&  或  and
    !=       ne        ||      or
    <        lt        !       not
    >        gt
    <=       le
    >=       ge

    三元运算符

    ${list==null ? "list为空" : "list不为空"}

    4. EL表达式11个内置对象

    EL可以输出的东西都在11个内置对象中,11个内置对象,其中10个是Map,只有pageContext不是Map,它就是PageContext类型,EL所有内置对象如下:

      1. pageScope   page域中的属性,相当于pageContext.getAttribute("name")

      2. requestScope  request域中的属性

      3. sessionScope   session域中的属性

      4. applicationScope   application域中的属性

      5. param   所有请求参数 ,适用于单值的参数,相当于request.getParameter("name")

      6. paramValues   所有请求参数 ,适用于多值的参数。

      7. header   所有http请求头字段,相当于request.getHeader("xxx")

      8. headerValues   同上,返回String[]

      9. cookie   cookie,例如${cookie.JSESSIONID.value}就是获取sessionId

      10. initParam   获取web.xml中<context-param>内的参数

      11. pageContext   可以获取JSP九大内置对象。例如pageContext.getRequest()可以写为${pageContext.request}

    注意事项:

    • headerValues,如果头里有"-",例如Accept-Encoding,则要headerValues["Accept-Encoding"];

    • cookie,${cookie.key}取的是cookie对象,访问cookie名称和值${cookie.key.name}和${cookie.key.value}

    5.回显数据

    概念:

    在数据提交出现错误的时候,已填写的信息仍在文本框中,比如用户登录,当用户输入错误的密码后,用户名仍在文本框,只是密码框清空。

    意义:

    对于一些要填写很多信息的表单,如果因为一些错误导致已经填写的整个表单信息重新填写,这对用户非常不友好。

    EL表达式最大的特点就是:如果获取到的数据为null,输出空字符串"",利用这个特点我们可以实现数据回显:

    //注册失败后,返回注册页面,之前填写的内容回显的功能!
    <%
        Person person = new Person();
        person.setName("xiaoyang");
    
        request.setAttribute("name", person);
    %>
    
    <input type="radio" name="name" value="xiaoyang" ${person.name=='xiaoyang'?'checked':''}>xiaoyang
    <input type="radio" name="name" value="xiaosun" ${person.name=='xiaosun'?'checked':''}>xiaosun

    6.EL自定义方法

    用于拓展EL表达式的功能,可以让EL表达式完成普通Java程序代码能完成的功能。

    比如:开发HTML转义的EL方法—》有时候想在JSP页面中输出JSP代码,但JSP引擎会自动把HTML代码解析输出给浏览器。

    步骤1:创建自定义EL方法的实现类

    (方法必须是静态的,因为EL表达式只能调用静态方法

    package impl;
    
    public class ShowJSP {
        public static String filter(String message){
    
            if(message == null) return null;
    
            //转储message
            char content[] = new char[message.length()];
            message.getChars(0, message.length(), content, 0);
            StringBuilder result = new StringBuilder(content.length + 50);
            for (int i = 0; i < content.length; i++) {
                switch (content[i]){
                    case '<':
                        result.append("&lt;");
                        break;
                    case '>':
                        result.append("&gt;");
                        break;
                    case '&':
                        result.append("&amp;");
                        break;
                    case '"':
                        result.append("&quot;");
                        break;
                    default:
                        result.append(content[i]);
                }
            }
            return result.toString();
        }
    }

    步骤2:注册自定义EL函数

    1.在WEB-INF目录下创建自定义tld文件:例如myelfuns.tld

    2.绑定约束文件

    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <taglib xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
            version="2.1">
    
        <!--标签库的版本号-->
        <tlib-version>1.0</tlib-version>
        <!--taglib指令中prefix需要指定的部分,任意,建议和文件名一致,方便管理。-->
        <short-name>myshortname</short-name>
        <!--taglib指令中URI需要指定的部分,任意。即便和JSP里要求的uri不一致也不影响-->
        <uri>http://mycompany.com</uri>
    
        
    <!--↓    ↓    ↓    ↓    ↓   ↓    ↓    ↓    主要配置    ↓    ↓   ↓    ↓   ↓    ↓   ↓    ↓-->
        <function>
            <!--函数名字-->
            <name>filter</name>
            <!--函数位置-->
            <function-class>impl.ShowJSP</function-class>
            <!--函数的方法声明-->
            <function-signature>java.lang.String filter(java.lang.String)</function-signature>
        </function>
        
    </taglib>

    步骤3:JSP里导入和使用

    EL自定义函数前缀一般为“fn”,uri是“/WEB-INF/tld文件名称” —》myelfuns.tld

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="fn" uri="/WEB-INF/myelfuns.tld" %>
    <html>
    <head>
        <title></title>
    </head>
    <body>
    
    <%--完成了HTML转义功能--%>
    ${fn:filter("<a href='#'>点我,大概没用</a>")}
    </body>
    </html>

    7. EL函数库(fn方法库)

    在JSP页面中显示数据时,经常需要对字符串进行处理,于是SUN公司定义了一套EL函数库。可以认为fn方法库就是String的方法。

    EL函数库(fn方法库),是JSTL标签库中的一个库,但是该库长得不像标签,所以称之fn方法库

    导入jstl和standard包。

    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
    <dependency>
        <groupId>javax.servlet.jsp.jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>

    在JSP页面中指明使用标签库

    <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    fn:contains(string, substring) 如果参数string中包含参数substring,返回true
    fn:containsIgnoreCase(string, substring) 如果参数string中包含参数substring(忽略大小写),返回true
    fn:endsWith(string, suffix) 如果参数 string 以参数suffix结尾,返回true
    fn:escapeXml(string) 将有特殊意义的XML (和HTML)转换为对应的XML character entity code,并返回
    fn:indexOf(string, substring) 返回参数substring在参数string中第一次出现的位置
    fn:join(array, separator) 将一个给定的数组array用给定的间隔符separator串在一起,组成一个新的字符串并返回。
    fn:length(item) 返回参数item中包含元素的数量。参数Item类型是数组、collection或者String。如果是String类型,返回值是String中的字符数。
    fn:replace(string, before, after) 返回一个String对象。用参数after字符串替换参数string中所有出现参数before字符串的地方,并返回替换后的结果
    fn:split(string, separator) 返回一个数组,以参数separator 为分割符分割参数string,分割后的每一部分就是数组的一个元素
    fn:startsWith(string, prefix) 如果参数string以参数prefix开头,返回true
    fn:substring(string, begin, end) 返回参数string部分字符串, 从参数begin开始到参数end位置,包括end位置的字符
    fn:substringAfter(string, substring) 返回参数substring在参数string中后面的那一部分字符串
    fn:substringBefore(string, substring) 返回参数substring在参数string中前面的那一部分字符串
    fn:toLowerCase(string) 将参数string所有的字符变为小写,并将其返回
    fn:toUpperCase(string) 将参数string所有的字符变为大写,并将其返回
    fn:trim(string) 去除参数string 首尾的空格,并将其返回              

    8. 注意:

    要使用EL则必须在JSP里添加<%@page isELIgnored="false" %>

    因为默认为true。

     

    6.5 JSTL

    1.什么是JSTL

    JSTL(JSP Standard Tag Library,JSP标准标签库)

    实现了基本的功能:集合的遍历,数据的输出,字符串的处理,数据的格式化,逻辑控制等等。

    2.core标签库

    core标签库是JSTL的核心标签库,实现了最基本的功能:流程控制,迭代输出等操作!

    core标签库的前缀一般是c

    在JSP中指明使用core标签库

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

    1 c:cout

    <c:out value="<string>" default="<string>" escapeXml="<true|false>"/>
    value是必要的。escapeXml默认为true
    <%@ page language="java" contentType="text/html; charset=UTF-8"
             pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    <html>
    <head>
        <title>c:out 标签实例</title>
    </head>
    <body>
    <h1>&lt;c:out&gt; 实例</h1>
    <%
        session.setAttribute("name", "&lt;c:out&gt; 实例");
    %>
    <c:out value="${name}" escapeXml="true" default="默认值"></c:out><br/>
    <c:out value="${name}" escapeXml="false" default="默认值"></c:out><br/>
    <c:out value="${name}" escapeXml="false">使用的表达式结果为true,则输出该值</c:out><br/>
    <c:out value="${null}" escapeXml="false">使用的表达式结果为null,则输出默认值</c:out><br/>

    2 c:set

    一般用于设置 JavaBean 对象或 java.util.Map 对象的值。

    <c:set var="<string>" value="<string>" target="<string>" property="<string>" scope="<string>"/>
    都不是必要,scope默认值为page。
    <c:set var="salary" scope="session" value="${2000*2}"/>
    <c:out value="${salary}"/>

    3 c:remove

    移除一个变量,可以指定这个变量的作用域,若未指定,则默认为变量第一次出现的作用域。

    <c:remove var="<string>" scope="<string>"/>
    var必要,scope默认所有作用域。
    <c:set var="salary" scope="session" value="${2000*2}"/>
    <p>salary 变量值: <c:out value="${salary}"/></p>
    <c:remove var="salary"/>
    <p>删除 salary 变量后的值: <c:out value="${salary}"/></p>

     4 c:catch

    处理产生的异常情况,并且将错误信息储存起来。

    <c:catch var="<string>">
    ...
    </c:catch>
    都不必要,默认值None。
    <c:catch var ="catchException">
        <% int x = 5/0;%>
    </c:catch>
    
    <c:if test = "${catchException != null}">
        <p>异常为 : ${catchException} <br />
            发生了异常: ${catchException.message}</p>
    </c:if>

    报错500

    添加包依赖

    jstl-api
    jstl-impl

    5 c:ifx

    <c:if test="<boolean>" var="<string>" scope="<string>">
       ...
    </c:if>
    test必要,scope默认值为page。
    <c:set var="salary" scope="session" value="${2000*2}"/>
    <c:if test="${salary > 2000}">
    <p>我的工资为: <c:out value="${salary}"/><p>
    </c:if>

    6 c:choose/c:when/c:otherwise

    switch语句中有case,而c:choose标签中对应有c:when,switch语句中有default,而c:choose标签中有c:otherwise

    <c:choose>
        <c:when test="<boolean>">
            ...
        </c:when>
        <c:when test="<boolean>">
            ...
        </c:when>
        ...
        ...
        <c:otherwise>
            ...
        </c:otherwise>
    </c:choose>
    c:choose和c:otherwise没有属性。
    c:when:test必要。
    <c:set var="salary" scope="session" value="${2000*2}"/>
    <p>你的工资为 : <c:out value="${salary}"/></p>
    <c:choose>
        <c:when test="${salary <= 0}">
           太惨了。
        </c:when>
        <c:when test="${salary > 1000}">
           不错的薪水,还能生活。
        </c:when>
        <c:otherwise>
            什么都没有。
        </c:otherwise>
    </c:choose>

    7 c:import

    提供了所有jsp:include行为标签所具有的功能,同时也允许包含绝对URL。

    举例来说,使用c:import标签可以包含一个FTP服务器中不同的网页内容。

    <c:import url="<string>" var="<string>" scope="<string>" varReader="<string>" context="<string>" charEncoding="<string>"/>
    url必要,context默认值为当前应用程序,charEncoding默认值为ISO--8869-1,scope默认值为page。
    url::                    待导入资源的URL,可以是相对路径和绝对路径,并且可以导入其他主机资源
    context:                 当使用相对路径访问外部context资源时,context指定了这个资源的名字。
    charEncoding:            所引入的数据的字符编码集
    var:                     用于存储所引入的文本的变量
    scope:                   var属性的作用域
    varReader:               可选的用于提供java.io.Reader对象的变量
    <c:import var="data" url="http://www.runoob.com"/>
    <c:out value="${data}"/>

    以上程序将会打印http://www.runoob.com"页面的源代码。

    8 c:forEach

    迭代一个集合中的对象。

    <c:forEach
        items="<object>"
        begin="<int>"
        end="<int>"
        step="<int>"
        var="<string>"
        varStatus="<string>">
        ...
    都没必要,begin默认值0,end默认值最后一个元素,step默认1。
    <c:forEach var="i" begin="1" end="5">
       Item <c:out value="${i}"/>
    </c:forEach>

    9 c:forTokens

    指定分隔符,将字符串分隔成一个数组然后迭代。

    <c:forTokens
        items="<string>"
        delims="<string>"
        begin="<int>"
        end="<int>"
        step="<int>"
        var="<string>"
        varStatus="<string>">
    delims必要。begin默认值0,end默认值最后一个元素,step默认值1。
    <c:forTokens items="google,runoob,taobao" delims="," var="name">
       <c:out value="${name}"/><br/>
    </c:forTokens>

    10 c:param

    用于在c:url标签中指定参数,而且与URL编码相关。

    <c:param name="<string>" value="<string>"/>
    name必要。value默认值Body。
    <c:url var="myURL" value="index.jsp">
        <c:param name="name" value="xiaoyang"/>
        <c:param name="password" value="123"/>
    </c:url>
    <c:out value="${myURL}"/>

    11 c:redirect

    重定向至一个新的URL,它提供内容相关的URL,并且支持c:param标签。

    <c:redirect url="<string>" context="<string>"/>
    url必要,context默认值当前应用程序。
    <c:redirect url="http://www.runoob.com"/>

    6.6 传统自定义标签

    6.7 简单自定义标签

    6.8 JSP面试题

     

     

    07 MVC三层架构

    7.1 早些年

    servlet--CRUD-->数据库
    弊端:程序十分臃肿,不利于维护
    servlet的代码中:处理请求,响应,视图跳转,处理JDBC,处理业务代码,处理逻辑代码
    
    架构:没有什么是加一层解决不了的!
    程序员调用
     |
     JDBC
     |
    Mysql Oracle sqlServer

    7.2 MVC三层架构

    Model

    • 业务处理:业务逻辑(Service)

    • 数据持久层:CRUD(Dao)

    View

    • 展示数据

    • 提供链接发起Servlet请求(a,form,img...)

    Controller

    • 接收用户的请求:(req:请求参数,Session信息...)

    • 交给业务层处理对应的代码

    • 控制视图的跳转

    • 登录-->请求用户的登录请求-->处理用户的请求(获取用户登录的参数)-->交给业务层处理登录业务(判断用户名密码是否正确:事务)-->Dao层查询用户名和密码是否正确 -->数据库
      再一层层返回

     

    08 过滤器Filter(重)

    8.1 什么是Filter

    在web开发过程中,为了实现某些特殊功能,经常需要对请求和响应消息进行处理。例如,记录用户访问信息,统计页面访问次数,验证用户身份等。Filter作为Servlet2.3中新增的技术,可以实现用户在访问某个目标资源之前,对访问的请求和响应进行相关处理;Filter被称作为过滤器或者拦截器,其基本功能就是对Servlet容器调用Servlet的过程进行拦截,从而在Servlet进行响应处理前后实现一些特殊功能。这就好比现实中的污水净化设备,它可以看作一个过滤器,专门用于过滤污水杂志。

    导入mysql包

    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.39</version>
    </dependency>

    8.1 Filter开发步骤

    1.编写Filter的实现类

    *注意存在很多Filter,导包正确->servlet-api

    #CharacterEncodingFilter.java 过滤乱码

    public class CharacterEncodingFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            //web服务器启动就已经初始化了,随时等待过滤对象出现!
        }
    
        @Override
        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执行后...");
        }
    
        @Override
        public void destroy() {
        }
    }

    2.编写测试类

    public class ShowServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //如果没有Filter,一定会出现乱码
            resp.getWriter().write("您好呀,world!");
        }
    }

    3.在web.xml中配置Filter

      <servlet>
        <servlet-name>showservlet</servlet-name>
        <servlet-class>ShowServlet</servlet-class>
      </servlet>
      <!--这样就没过滤器的支持-->
      <servlet-mapping>
        <servlet-name>showservlet</servlet-name>
        <url-pattern>/showservlet</url-pattern>
      </servlet-mapping>
      <!--这样就有过滤器的支持-->
      <servlet-mapping>
        <servlet-name>showservlet</servlet-name>
        <url-pattern>/show/showservlet</url-pattern>
      </servlet-mapping>
    
      <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        只要是/show/路径下的任何请求,都会经过这个过滤器
        <url-pattern>/show/*</url-pattern>
      </filter-mapping>

    没走过滤器(/showservlet

    走过滤器(/show/showservlet)

     

    09 监听器listener

    9.1 什么是监听器

    GUI图形化编程里经常用。

    9.2 步骤

    以统计网站在线人数为例,通过监听统计session可做到。

    1.编写Listenner监听类

    #OnlineCountListener.java

    //统计网站在线人数:统计session
    public class OnlineCountListener implements HttpSessionListener {
        //创建session监听
        //一旦创建session就会触发一次这个事件
        @Override
        public void sessionCreated(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);
            System.out.println("sessionCreated233333333");
        }
    
        //销毁session监听
        //一旦销毁session就会触发一次这个事件
        //销毁session的方式:参见5 -》 5.9 -》 3 主动退出浏览器并不会注销session。考虑其他两种方式,手动注销。或者设置session过期时间。
        @Override
        public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
            ServletContext ctx = httpSessionEvent.getSession().getServletContext();
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    
            if(onlineCount == null){
                onlineCount = new Integer(0);
            }else{
                int count = onlineCount.intValue();
                onlineCount = new Integer(count - 1);
            }
    
            ctx.setAttribute("OnlineCount", onlineCount);
            System.out.println("sessionDestroyed2333333333");
        }
    }

    2.在web.xml中配置listner

    <listener>
        <listener-class>OnlineCountListener</listener-class>
    </listener>

    3.编写测试页面

    # index.jsp 统计页面
    <%@page isELIgnored="false" %>
    当前 ${applicationScope.OnlineCount} 人在线
    
    # destroy.jsp 主动销毁session
    <%
        session.invalidate();
    %>

    4.测试

    [redeploy] 登录0次

    [restart] 登录2次

    [另一个浏览器页面打开+1次]

    补充:

    10 JDBC及事务

    JDBC(Java Database Connection,Java 连接数据库)

    • 注意Mysql版本8必须导入响应的版本驱动

    1. 简单增删改查

    #数据库

    create database jdbc;
    
    use jdbc;
    
    create table users(
      id int primary key ,
      `name` varchar(40),
      `password` varchar(40),
      email varchar(60),
      birthday date
    );
    
    insert  into users(users.id,users.`name`,users.`password`,users.email,users.birthday)
    values (1,'张三','123456','zs@qq.com','2000-01-01');
    insert  into users(users.id,users.`name`,users.`password`,users.email,users.birthday)
    values (2,'李四','123456','ls@qq.com','2000-01-01');
    insert  into users(users.id,users.`name`,users.`password`,users.email,users.birthday)
    values (3,'王五','123456','ww@qq.com','2000-01-01');

    驱动:com.mysql.cj.jdbc.Driver

    URL:jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8

    import java.sql.*;
    
    public class TestJDBC {
            public static void main(String[] args) throws ClassNotFoundException, SQLException {
                String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8";
                String username = "root";
                String password = "root";
    
            //1.加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.连接数据库
            Connection connection = DriverManager.getConnection(url, username, password);
            //3.向数据库发送SQL的对象statement:CRUD
            Statement statement = connection.createStatement();
            //4.编写Sql
            String sql = "select * from users";
            //5.执行sql。返回一个结果集
            ResultSet resultSet = statement.executeQuery(sql);
            while(resultSet.next()){
                System.out.println(resultSet.getObject("id"));
                System.out.println(resultSet.getObject("name"));
                System.out.println(resultSet.getObject("password"));
                System.out.println(resultSet.getObject("email"));
                System.out.println(resultSet.getObject("birthday"));
            }
            //6.关闭连接,先开的后关
            resultSet.close();
            statement.close();
            connection.close();
    
        } 
    }

    增(采用预编译的方式)

    public class TestJDBC {
            public static void main(String[] args) throws ClassNotFoundException, SQLException {
                String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8";
                String username = "root";
                String password = "root";
    
            //1.加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.连接数据库
            Connection connection = DriverManager.getConnection(url, username, password);
            //3.编写Sql
            String sql = "insert into users(id,name,password,email,birthday) value(?,?,?,?,?);";
            //4.预编译
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, 4);
            preparedStatement.setString(2, "xiaoyang");
            preparedStatement.setString(3, "123456");
            preparedStatement.setString(4, "xy@qq.com");
            preparedStatement.setDate(5, new Date(new java.util.Date().getTime()));
            //5.执行sql
            int i = preparedStatement.executeUpdate();
            if(i > 0){
                System.out.println("插入成功【" + i + "】条数据");
            }
            //6.关闭连接
            preparedStatement.close();
            connection.close();
            
        }
    }

    2.事务

    要么都成功,要么都失败。

    ACID原则:保证数据安全。

    题外话:junit.jar:@Test注解保证不需要main方法,在哪都可以测试方法

    开启事务
    事务提交 commit()
    事务回滚 rollback()
    关闭事务
    
    转账:
    A:1000
    B:1000
    A(900)    --100-->    B(1100)

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    二维数组的使用及其内存结构
    一维数组的练习
    数组的默认初始化
    数组
    完数
    break与continue
    乘法表及质数的输出法
    嵌套循环的使用
    Elasticsearch索引和查询性能调优
    elasticsearch数据冷热分离、数据冷备
  • 原文地址:https://www.cnblogs.com/p0pl4r/p/13157406.html
Copyright © 2011-2022 走看看