Servlet

Servlet是Java Web开发的基石,与平台无关的服务器组件,它是运行在Servlet容器/Web应用服务器/Tomcat,负责与客户端进行通信

Servlet的功能:

  1. 创建并返回基于客户请求的动态HTML页面

  2. 与数据库进行通信

如何使用Servlet?

package cn.soutwind.servlet;

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

public class MyServlet implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        String id = servletRequest.getParameter("id");
        System.out.println("我是Servlet,我已接收到客户端传来的数据,参数为:" + id);
        servletResponse.setContentType("text/html;charset=UTF-8");
        servletResponse.getWriter().write("软件测试测试测试");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

浏览器不能直接访问Servlet文件,只能通过映射的方式来间接的访问Servlet,映射需要开发者手动配置,有两种配置方式。

基于XML文件的配置方式

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>cn.soutwind.servlet.MyServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/myservlet</url-pattern>
</servlet-mapping>

基于注解的方式:

@WebServlet("/demo01")
public class MyServlet implements Servlet {

}

上述两种配置方式结果完全一致,将demo01与MyServlet进行映射,即在浏览器地址栏直接访问demo01就可以映射到MyServlet

Servlet生命周期

  1. 当浏览器访问Servlet的时候,Tomcat会查询当前Servlet的实例化对象是否存在,如果不存在,则通过反射机制动态创建对象,如果存在,直接执行第三步

  2. 调用init方法完成初始化

  3. 调用Service方法完成业务逻辑操作

  4. 关闭Tomcat时,会调用destory方法,释放当前对象所占用的资源

Servlet的生命周期方法:无参构造方法、init、service、destory

  1. 无参构造方法值调用一次,创建对象。

  2. init只调用一次,初始化对象

  3. service调用N次,执行业务方法

  4. destory只调用一次,卸载对象

ServletConfig

该接口是用来描述Servlet的基本信息的。

getServletName() 返回Servlet的名称,全类名(带着包名的类名)

getInitParameter(String key) 获取init参数的值(web.xml)

getInitParmeterNames() 返回所有的InitParameter 的 name 值,一般用作遍历初始化参数

getServletContext() 返回ServletContext对象,它是Servlet 的上下文,整个Servlet的管理者

ServletConfig 和 ServletContext的区别:

ServletConfig作用于某个Servlet实例,每个Servlet都有对应的ServletConfig,ServletContext作用于整个Web应用,一个Web应用对应一个ServletContext,多个Servlet实例对应一个ServletContext

Servlet的层次结构

Servlet--》 GenericServlet --》HttpServlet

HTTP请求有很多种类型,常用的有四种:

GET 读

POST 保存

PUT 修改

DELETE 删除

GenericServlet实现Servlet接口,同时为它的子类屏蔽了不常用的方法,子类只需要重写Servlet方法即可

HTTPServlet继承GenericServlet,根据请求类型进行分发处理,GET进入doGET方法,POST进入doPOST方法

开发者自定义的Servlet类只需要继承HTTPServlet即可,重新doGET和doPOST

package cn.soutwind.servlet;

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

@WebServlet("/demo03")
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("GET请求");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("POST请求");
    }
}

JSP

JSP本质上就是一个Servlet,JSP主要负责与用户交互,将最终的界面显示给用户,HTML+CSS+JS+Java 的混合文件

当服务器接收到一个后缀是jsp的请求时,将该请求交给JSP引擎处理,每一个JSP页面第一次被访问的时候,JSP引擎会将它翻译成一个Servlet文件,再由Web容器调用Servlet完成响应

单纯从开发的角度看,JSP就是在HTML中嵌入Java程序。

具体的嵌入方式有三种:

JSP脚本,执行Java逻辑代码

<% Java代码 %>

JSP声明:定义Java方法

<%! 声明 Java 方法 %>

JSP表达式:把Java对象直接输出到HTML页面中

<%= java变量 %>
<%!
  public String test(){
    return "Hello Word";
  }
%>
<%
  String str = test();
%>

<%=str%>

JSP内置对象9个

  1. request:表示一次请求,HttpServletRequest。

  2. response:表示一次响应,HttpServletResponse

  3. pageContext:页面上下文,获取页面信息,PageContext

  4. session:表示一次会话,保存用户信息,HttpSession

  5. application:表示当前Web应用,全局对象,保存所有用户共享信息,ServletContext

  6. config:当前JSP对应的Servlet的ServletConfig对象,获取当前Servlet信息

  7. out:向浏览器输出数据,JSPWrite

  8. page:当前JSP对应的Servlet对象,Servlet。

  9. exception:表示JSP页面的发生的异常,Exception

常用的是request、response、session、application、pageContext

request常用方法:

  1. String getParameter(String key)获取客户端传来的参数

  2. void setAttribute(String key,Object value) 通过键值对的形式保存数据

  3. Object getAttribute(String key) 通过key取出value

  4. RequestDispatcher getRequestDispatcher(String path) 返回一个RequestDispatcher对象,该对象的forward方法用于请求转发

  5. String[] getParameterValues() 获取客户端传来的多个同名参数

  6. void setCharacterEncoding(String charset) 指定每个请求的编码

response常用方法:

  1. sendRedirect(String path) 重定向,页面之间的跳转。

转发getRequestDispatcher 和 重定向sendRedirect的区别:

转发是将同一个请求传给下一个页面,重定向是创建一个新的请求传给下一个页面,之前的请求结束生命周期

转发:同一个请求在服务器之间传递,地址栏不变,也叫服务器跳转

重定向:由客户端发送一次新的请求来访问跳转后的目标资源,地址栏改变,也叫客户端跳转

如果两个页面之间需要通过request来传值,则必须使用转发,而不能使用重定向

例:用户登录,如果用户名和密码正确,则跳转到首页(转发),并且展示用户名,否则重新回到登录页面(重定向)

Session

用户会话

服务器无法识别每一次HTTP请求的出处(不知道来自于哪个终端)它只会接收到一个请求信号,所以就存在一个问题:将用户的响应发送给其他人,必须有一种技术来让服务器知道请求来自哪里,这就是会话技术

会话:就是客户端和服务器之间发生的一系列连续的请求和响应的过程,打开浏览器进行操作到关闭浏览器的过程

会话状态:指服务器和浏览器在会话过程中产生的状态信息,借助于会话状态,服务器能够把属于同一次会话的一系列请求和响应关联起来。

实现会话有两种方式:

  • session

  • cookie

属于同一次会话的请求都有一个相同的标识符,sessionID

session常用的方法:

String getId() 获取sessionID

void setMaxInactiveInterval 设置session的失效时间,单位为秒

int getMaxInactiveInterval 获取当前session的失效时间

void invalidate() 设置session立即失效

void setAttribute(String key,Object value) 通过键值对的形式来存储数据

Object getAttribute(String key) 通过键获取对应的数据

void removeAttribute(String key) 通过键删除对应的数据

Cookie是服务端在HTTP响应中附带传给浏览器的一个小文本文件,一旦浏览器保存了某个Cookie,在之后的请求和响应过程中,会将此Cookie来回传递,这样就可以通过Cookie这个载体完成客户端和服务端之间的数据交互

创建Cookie

//创建Cookie
Cookie cookie = new Cookie("name","joker");
response.addCookie(cookie);

读取Cookie

// 读取Cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie: cookies){
    out.write(cookie.getName() + ":" + cookie.getValue() + "</br>");
}

Cookie常用的方法

void setMaxAge(int age) 设置Cookie的有效时间,单位为秒

int getMaxAge() 获取Cookie的有效时间

Stirng getName() 获取Cookie的name

String getValue() 获取Cookie的value

Session和Cookie的区别

session: 保存在服务器

保存的数据是Object

会随着会话的结束而销毁

保存重要信息

cookie: 保存在浏览器

保存的数据是String

可以长期保存在浏览器,无会话无关

保存不重要的信息、

存储用户信息:

session: setAttribute("name","admin") 存

getAttribute("name") 取

生命周期:服务端:只要WEB应用重启就销毁,客户端:只要浏览器关闭就销毁

退出登录:session.invalidate()

cookie:response.addCookie(new Cookie("name","admin")) 存

Cookie[] cookies = request.getCookies();
for(Cookie cookie:cookies){
  if (cookie.getName().equals("name")){
    out.write("欢迎回来" + cookie.getValue());
  }
}

生命周期:不随着服务端的重启而销毁,客户端:默认只要关闭浏览器就销毁,我们通过setMaxAge()方法设置有效期,一旦设置了有效期,则不随浏览器的关闭而销毁,而是由设置的时间来决定

退出登录:setMaxAge(0)

JSP内置对象作用域

page、request、session、application

setAttribute,getAttribute

page作用域:对应的内置对象是pageContext

request作用域:对应的内置对象是request

session作用域:对应的内置对象是session

application作用域:对应的内置对象是application

page

page只在当前页有效

request在一次请求内有效

session在一次会话内有效

application对应整个WEB应用

EL表达式

Expression Language 表达式语言,替代JSP页面中数据访问时的复杂编码,可以非常便携的取出域对象(pageContext、request、session、application)中保存的数据,前提是一定要先setAttribute,EL相当于在简化getAttribute

$(变量名) 变量名就是setAttribute对应的key值

  1. EL对应四种域对象的默认查找顺序:

pageContext-》request-》session-》application

按照上述的顺序进行查找,找到立即返回,在application中无法找到,则返回null

  1. 指定作用域进行查找

pageContext:${pageScope.name}

request:${requestScope.name}

session:${sessionScope.name}

application:${applicationScope.name}

<%
    User user = new User(1,"张三");
    pageContext.setAttribute("user",user);
%>
<table>
    <tr>
        <th>编号</th>
        <th>姓名</th>
    </tr>
    <tr>
        <td>${user.id}</td>
        <td>${user.name}</td>
    </tr>

JSTL

JSP Standard Tag Library JSP标准标签库,JSP为开发者体用的一系列的标签,使用这些标签可以完成一些逻辑处理,比如循环遍历集合,让代码更加简洁,不在出现JSP脚本穿插的情况。

实际开发中 EL 和 JSTL 结合起来使用,JSTL侧重于逻辑处理,EL负责展示数据。

JSTL的使用

  1. 需要导入jar包(两个jstl.jar standard.jar)存放的位置 web-WEB-INF

  2. 在JSP页面开始的地方导入JSTL标签库

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  1. 在需要的地方使用

<c:forEach items="${requestScope.list}" var="user">
  <tr>
    <td>${user.id}</td>
    <td>${user.name}</td>
  </tr>
</c:forEach>

JSTL优点:

  1. 提供了统一的标签

  2. 可以用于编写各种动态功能

核心标签库常用的标签:

  • set、out、remove、catch

set:向域对象添加数据

<c:set var="name" value="张三"></c:set>
${name}

<%
    User user = new User(1,"张三");
    request.setAttribute("user",user);
%>
${user.name}
<br>
<c:set target="${user}" property="name" value="李四"></c:set>
${user.name}

out:输出域对象中的数据

<c:set var="name" value="张三"></c:set>
<c:out value="${name}" default="没哟"></c:out>

remove:删除域对象中的数据

<c:remove var="name" scope="page"></c:remove>
<c:out value="${name}" default="没定义"></c:out>

catch:捕获异常

v
  • 条件标签:if choose

<c:set var="num1" value="1"></c:set>
<c:set var="num2" value="2"></c:set>

<c:if test="${num1 > num2}">ok</c:if>
<c:if test="${num1 < num2}">fail</c:if>
<hr>
<c:choose>
    <c:when test="${num1 > num2}">ok</c:when>
    <c:otherwise>fail</c:otherwise>
</c:choose>
  • 迭代标签:forEach

<c:forEach items="${list}" var="str" begin="2" end="5" step="2" varStatus="sta">
   ${sta} - ${str}<br>
</c:forEach>

格式化标签库常用的标签:

<%
    request.setAttribute("data",new Date());
%>
<fmt:formatDate value="${data}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate>
<fmt:formatNumber value="1234.665" maxIntegerDigits="3" maxFractionDigits="1"></fmt:formatNumber>

过滤器(Filter)

功能:

  1. 用来拦截传入的请求和传出的响应

  2. 修改或以某种方式处理正在客户端和服务端之间交换的数据流

如何使用?

与使用Servlet类似,Filter是Java WEB提供的一个街口,开发者只需要定义一个类并且实现该接口即可。

package cn.soutwind.Filter;

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

public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("UTF-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

web.xml 中配置Filter

<filter>
    <filter-name>Character</filter-name>
    <filter-class>cn.soutwind.Filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Character</filter-name>
    <url-pattern>/login</url-pattern>
</filter-mapping>

注意:doFilter方法中处理完业务逻辑之后,必须添加filterChain.doFilter(servletRequest,servletResponse);否则请求/响应无法向后传递,一直停留在过滤器中

Filter的生命周期

当Tomcat启动时,通过反射机制调用Filter的无参构造函数创建实例化对象,同时调用init方法实现初始化,doFilter方法调用多次,当Tomcat服务关闭的时候,调用destory来销毁Filter对象。

无参构造函数:只调用一次,当Tomcat启动时调用(Filter一定要进行配置)

init方法:只调用一次,但Filter的实例化对象创建完成之后调用

doFilter:调用多次,访问Filter的业务逻辑都写在Filter中

destory:只调用一次,Tomcat关闭时调用

同时配置多个Filter,Filter的调用顺序是由web.xml中的配置顺序来决定的,写在上面的配置先调用,因为web.xml是从上往下顺序读取的

<filter>
    <filter-name>Character</filter-name>
    <filter-class>cn.soutwind.Filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Character</filter-name>
    <url-pattern>/login</url-pattern>
</filter-mapping>

<filter>
    <filter-name>my</filter-name>
    <filter-class>cn.soutwind.Filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>my</filter-name>
    <url-pattern>/login</url-pattern>
</filter-mapping>

也可以通过注解的方式来简化web.xml中的配置

@WebFilter("/login")

实际开发中Filter的使用场景

  1. 统一处理中文乱码

  2. 屏蔽敏感词

package cn.soutwind.Filter;

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

public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("UTF-8");
        String name = servletRequest.getParameter("name");
        name = name.replaceAll("敏感词","***");
        servletRequest.setAttribute("name",name);
        filterChain.doFilter(servletRequest,servletResponse);
    }
}
package cn.soutwind.Servlet;

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

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        req.setCharacterEncoding("UTF-8");
        String name = (String) req.getAttribute("name");
        System.out.println(name);
    }
}
  1. 控制资源的访问权限

package cn.soutwind.Filter;

import com.sun.deploy.net.HttpResponse;

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

@WebFilter("/download.jsp")
public class DownloadFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpSession session = request.getSession();
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String name = (String) session.getAttribute("name");
        if (name != null){
            filterChain.doFilter(servletRequest,servletResponse);
        }else{
            response.sendRedirect("index.jsp");
        }
    }
}
package cn.soutwind.Servlet;

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

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String password= req.getParameter("password");
        if(name.equals("admin") && password.equals("123456")){
            HttpSession session = req.getSession();
            session.setAttribute("name",name);
            resp.sendRedirect("download.jsp");
        }else{
            resp.sendRedirect("index.jsp");
        }
    }
}

文件上传下载

JSP

  1. input的type设置为file

  2. form表单的method设置post,get请求会将文件名传给服务端,而不是文件本身

  3. form表单的enctype设置multipart/form-data,以二进制的形式传输数据

Servlet

上传

package cn.soutwind.Servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        InputStream inputStream = req.getInputStream();
//        int temp = 0;
//        while((temp = inputStream.read()) != -1){
//            System.out.println(temp);
//        }

        try {
            // 创建一个文件工厂
            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
            // 把请求的内容转为FileItem的集合
            List<FileItem> list = servletFileUpload.parseRequest(req);
            for (FileItem fileItem : list){
                //有两种数据,一个是表单数据一个是文件数据
                if(fileItem.isFormField()){
                    //表单数据
                    String name = fileItem.getName();
                    String value = fileItem.getString("UTF-8");
                    System.out.println(name + ":" + value);
                }else{
                    //文件数据
                    String name = fileItem.getName();
                    String path = req.getServletContext().getRealPath("file/" + name);
                    InputStream inputStream = fileItem.getInputStream();
                    OutputStream outputStream = new FileOutputStream(path);
                    int temp = 0;
                    while((temp = inputStream.read()) != -1){
                        outputStream.write(temp);
                        System.out.println(temp);
                    }
                    inputStream.close();
                    outputStream.close();
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
}

下载

package cn.soutwind.Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置响应方式
        resp.setContentType("application/x-msdownload");
        String filename= "1.jpg";
        //设置下载后的文件名
        resp.setHeader("Content-Disposition","attachment;filename=" + filename);
        OutputStream outputStream = resp.getOutputStream();
        String path = req.getServletContext().getRealPath("file/" + filename);
        InputStream inputStream = new FileInputStream(path);
        int temp = 0;
        while((temp = inputStream.read()) != -1){
            System.out.println(temp);
            outputStream.write(temp);
        }
        inputStream.close();
        outputStream.close();
    }
}

Ajax

Asynchronous JavaScript And XML:异步的JavaScript和XML

Ajax不是新的编程,指的是一种交互方式,异步加载 ,客户端和服务端的数据交互更新在局部页面的技术,不需要刷新整个页面(拒不刷新)

优点:

  1. 局部刷新,效率更高

  2. 用户体验更好

<%--
  Created by IntelliJ IDEA.
  User: DELL
  Date: 2023/8/24
  Time: 19:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.5.1.min.js"></script>
    <script type="text/javascript">
        $(function (){
            var btn = $("#btn");
            btn.click(function (){
               $.ajax({
                   url:'/test',
                   type:'post',
                   dataType:'text',
                   success:function (data){
                       var text = $("#txt");
                       text.before("<h1>" + data + "</h1>" + "<br>")
                   }
               });
            });
        })
    </script>
</head>
<body>
    <input type="text" id="txt"><br>
    <input type="button" id="btn" value="提交">
</body>
</html>

不能用表单提交请求,改用Jquery方式动态绑定事件来提交。

Servlet不能跳转到JSP,只能将数据返回

package cn.soutwind.Servlet;

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

@WebServlet("/test")
public class TestServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String str = "Hello Word";
//        req.setAttribute("str",str);
//        req.getRequestDispatcher("test.jsp").forward(req,resp);
        resp.getWriter().write(str);
    }
}

传统的WEB数据交互 VS AJAX数据交互

客户端请求的方式不同:

传统,浏览器发送同步请求(form、a)

AJAX,异步引擎对象发送异步请求

服务器响应的方式不同:

传统,响应的一个完整的JSP页面(视图)

AJAX,响应需要的数据

客户端处理方式不同:

传统:需要等待服务器完成响应并且重新加载整个页面后,用户才能进行后续的操作

AJAX:动态更新页面中的局部内容,不影响用户的其他操作

基于JQuery的AJAX语法

$.ajax({属性})

常用的属性参数:

url:请求的后端服务地址

type:请求方式,默认get

data:请求参数

dataType:服务器返回的数据类型,text/json

success:请求传给的回调函数

error:请求失败的回调函数

complete:请求完成的回调函数(无论成功或者失败,都会调用)

JDBC

Java DataBase Connectivity是一个独立于特定数据库的管理系统,通用的SQL数据存取操作的公共接口。

定义了一组标准,为访问不同数据库提供了统一的途径。

JDBC体系结构

JDBC接口包括两个层面:

  • 面向应用的API,供程序员使用

  • 面向数据库的API,供厂商开发数据库的驱动程序

JDBC API

提供者:Java官方

内容:供开发者调用的接口

java.sql 和 javax.sql

  • DriverManager类

  • Connection接口

  • Statement接口

  • ResultSet接口

Drivermanager

提供者:Java 官方

作用:管理不同的JDBC驱动

JDBC驱动

提供者:数据库厂商

作用:负责连接不同的数据库

JDBC的使用

  1. 加载数据库驱动,Java程序和数据库之间的桥梁

  2. 获取Connection,Java程序与数据库的一次连接

  3. 创建Statement对象,由Connection产生,执行SQL语句

  4. 如果需要接受返回值,创建ResultSet对象,保存Statement执行之后所查询到的结果。

数据库连接池

JDBC开发流程

  • 加载驱动(只需要加载一次)

  • 建立数据库连接(Connection)

  • 执行SQL语句(Statement)

  • ResultSet接收结果集(查询)

  • 断开连接,释放资源

数据库连接对象是通过DriverManager来获取,每次获取都需要向数据库申请获取连接,验证用户名和密码,执行完SQL语句后断开连接,这样的方式会造成资源的浪费,数据连接资源没有得到很好的重复利用。

可以使用数据库连接池解决这一问题

数据库连接池的基本思想就是为数据库建立一个缓冲池,预先向缓冲池放入一定数量的连接对象,当需要获取数据库连接的时候,只需要从缓冲池取出一个对象,用完之后再放回缓冲池中,供下一次请求使用,做到了资源的重复利用,允许程序重复使用一个现有的数据库连接对象,而不需要重新创建。

当数据库连接池中没有空闲的连接时,新的请求就会进入等待队列,等待其他线程释放连接

数据库连接池的实现

JDBC的数据库连接池是哟韩Javax.sql.Datasourc接口来完成的,DataSource是Java官方提供的接口,使用的时候开发者并不需要自己来实现该接口,可以使用第三方的工具,C3P0是一个常用的第三方实现,实际开发中直接使用C3P0即可完成数据库连接池的操作

  1. 导入jar包

  2. 代码实现

package com.soutwind.Demo09;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

public class C3P0 {
    public static void main(String[] args) {
        try {
            //创建连接池对象
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            //加载驱动
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            //设置连接路径
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/express?characterEncoding=UTF-8");
            //设置连接用户名
            dataSource.setUser("root");
            //设置密码
            dataSource.setPassword("xxxxxx");
            // 获取连接对象
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
            //归还连接对象
            connection.close();
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        } catch (SQLException e){
            e.printStackTrace();
        }

    }
}

实际开发,将C3P0的配置信息定义在xml文件中,Java程序只需要加载配置文件即可完成数据库连接池的初始化操作。

  1. 配置文件的名字必须是c3p0-config.xml

  2. 初始化ComboPooledDataSource时,传入的参数必须是c3o0-config.xml中named-config标签的name属性值。

<?xml version="1.0" encoding="utf-8" ?>
<c3p0-config>
    <named-config name="testc3p0">
<!--            指定连接数据源的基本属性-->
        <property name="user">root</property>
        <property name="password">xxxxxx</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/express?characterEncoding=UTF-8</property>

        <!-- 若数据库中连接数不足时,一次向数据库服务器申请多少个连接 -->
        <property name="acquireIncrement">5</property>
        <!-- 初始化数据库连接池连接的对象 -->
        <property name="initialPoolSize">2</property>
        <!-- 数据库连接池中最小的数据库连接数 -->
        <property name="minPoolSize">2</property>
        <!-- 数据库连接池中最大的数据库连接数 -->
        <property name="maxPoolSize">10</property>

    </named-config>
</c3p0-config>
package com.soutwind.Demo09;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

public class C3P0_2 {
    public static void main(String[] args) {
        try {
            //创建连接池对象
            ComboPooledDataSource dataSource = new ComboPooledDataSource("testc3p0");
            // 获取连接对象
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
            //归还连接对象
            connection.close();
        } catch (SQLException e){
            e.printStackTrace();
        }

    }
}
  1. xml文件得放在src目录下

DBUtils

DBUtils可以帮助开发者完成数据的封装(结果集到Java对象的映射)

  1. 导入jar包

ResultHandler接口是用来处理结果集,可以将查询到的结果集转为Java对象,提供了四种实现类

  • BeanHandler 将结果集映射成Java对象

  • BeanListHandler 将结果集映射成List集合

  • MapHandler 将结果集映射成Map对象

  • MapListHandler 将结果集映射MapList集合

package com.soutwind.Demo09;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import java.sql.Connection;
import java.sql.SQLException;

public class Test {
    public static void main(String[] args) {
        ComboPooledDataSource dataSource = new ComboPooledDataSource("testc3p0");
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            QueryRunner queryRunner = new QueryRunner();
            String sql = "select * from userinfo ";
            System.out.println(queryRunner.query(connection,sql,new MapListHandler()));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}