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:\Users\kenshin.IntelliJIdea2018.2\system\tomcat\Unnamed_javaweb-servlet\work\Catalina\localhost\s5\org\apache\jsp

分析原理

【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)

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-06-18 14:37  p0pl4r  阅读(489)  评论(0编辑  收藏  举报