Java Web

Java Web

一、使用Tomcat部署Java web应用

Tomact:

Web应用服务器:Tomcat、JBoos、Weblogic、Jetty

  • 安装Tomcat

    1. 下载压缩文件

    2. 解压缩

      bin:存放各个平台下启动和停止的Tomcat服务的脚本

      bonf:存放各种Tomcat服务器的配置文件

      lib:存放Tomcat服务器所需要的jar

      logs:存放Tomcat服务运行的日记

      temp:Tomcat运行时的临时文件

      webapps:存放允许客户端访问的资源(Java程序)

      work:存放Tomcat将JSP转换之后的Servlet文件

IDEA集成Tomcat

  1. 创建Java Web文件

  2. 配置Tomcat文件

Servlet

  • 什么是Servlet?

    Servlet是JavaWeb开发的基石,与开发平台无关,他是运行在Servlet容器/web应用服务器/Tomcat服务器,负责与客户端进行通信。

    Servlet的功能:

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

    2. 与数据库进行通信

    • 如何使用Servlet?

      Servlet本身是一组接口,(javax.serlvet、jiava.lang、java.util、java.sql),自定义一个类,并且实现servlet接口,这类就具备了接收客户端的请求以及做出响应的功能。

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

      1. 基于XML文件配置方式

            <servlet>
                <servlet-name>MyServlet</servlet-name>
                <servlet-class>com.gopan.servlettest.MyServlet</servlet-class>
            </servlet>
            <servlet-mapping>
                <servlet-name>MyServlet</servlet-name>
                <url-pattern>/myservlet</url-pattern>
            </servlet-mapping>
        
      2. 基于注解的方式 代替XML文件很简单

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

        两种配置一样,将demo1与Myservlet进行映射,就是在浏览器地址中直接访问Demo1就可以映射到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的基本信息的。

    servletConfig.getServletName();//返回Servlet的名称,
    getInitParameter(String key); //获取init参数的值(web.xml)
    getInitParameterNames(); //返回所有的Paramter所有的值,一般用循环
    getServletContext();//返回ServletContext对象,他是Servlet的上下文,整个服务的信息
    

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

    一个是局部对象,一个是全局对象

Servlet的层次结构

  • Servlet --> GenericServlet --> HttpServlet

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

    • GET 读取
    • POST 保存
    • PUT 修改
    • DELETE 删除

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

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

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

    package com.gopan.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("/demo02")
    public class TestServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("GET...");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("POST...");
        }
    }
    

JSP

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

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

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

    具体嵌入方式有3种:

    1. JSP脚本

      <% //Java代码    %>
      
    2. JSP声明:定义Java方法

      <%!
      	声明方法
      %>
      
    3. JSP表达式:把Java对象直接到输出到HTML页面中

      <%=Java变量%>
      
      <%!
        	public String test(){
         		return "world...";
      	}
          %>
      
          <%
            String str = test();
            //
          %>
      
          <%=str%>
      

JSP内置对象 9个

  • resqust:表示一次请求,HttpServletRequst
  • response:表示一次响应,HttpServlerResponse
  • pageContext:页面上下文,获取页面信息,PageContext
  • session:表示一次会话,保存用户信息,HttpSession
  • application:表示当前的Web应用,全局对象,保存所有用户共享信息,ServlerContext
  • config:当前JSP对应的Servlet的ServletConfig对象,获取当前的Servlet的信息
  • out:向浏览器输出数据,JSPWriter
  • page:当前JSP对象的Servlet对象,Servlet
  • excerption:表示JSP页面发生的异常,Exception

常用的是:requst、response、session、appliction、pageContext

  1. requst的常用方法:

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

    2. void setAttribute(String key.Object value)通过键值对的形式保存数据。 服务器内部资源传递

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

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

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

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

      HTTP请求状态码:200 正常 404资源找不到 400请求类型不匹配 500java程序抛出异常

  2. response

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

      转发getRequestDispatcher和重定向sendRedirect区别:

      ​ 转发就是将同一个请求下传给下一个页面,重定向是创建一个新的请求传给下一个页面。

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

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

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

      • 用户登录,如果用户名和密码正确,则跳转到首页(首页),并展示用户名,否则重新回到登陆页面(重定向)
  3. Session

    • 用户会话

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

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

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

      实现会话两种方式

      • session
      • cookie

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

      session常用的方法:

      1. String getID()获取到当前的sessionID
      2. void setMaxINactiveInterval(int interval)设置session的失效时间单位为秒
      3. int getMaxIncativeInterval() 获取session的失效时间
      4. void invalidate() 设置session立即失效
      5. void serAttribute(String key,Object value) 通过键值对的形式来存储数据
      6. Object getAtrribute(String key) 通过键值获取对应的数据
      7. void removeAtrribute(String key) 通过键值删除对应的数据
  • Cookie是服务端在HTTP响应中附带传给浏览器的一个小文本文件,一旦浏览器保存了某个Cookie,在之后的请求和响应过程中会将Cookie来回传递,这样就可以通过Cookie这个载体完成客户端和服务器的数据交互。

    Cookie

    • 创建Cookie
    Cookie cookie = new Cookie("name", "lisi");
    response.addCookie(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的有效时间

    String 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) {
                //out.write(cookie.getName() + ":" + cookie.getValue());
                if(cookie.getName().equals("name")){
                    out.write("欢迎回来!" + cookie.getValue());
                }
            }
    

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

    退出登录:setMaxAge(0)

JSP内置对象作用域

​ 4个

​ page、request、session、application

​ setAttribute、getAttribute

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

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

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

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

  • page<request<session<appllication

    page只在当前的页面上有效

    request在一次请求内有效

    session在一次会话有效

    application对应整个web应用的

    • 网站的访问量统计

      Integer count = (Integer) application.getAttribute("count");
              if(count == null){
                  count = 1;
                  application.setAttribute("count", count);
              }else{
                  count++;
                  application.setAttribute("count", count);
              }
      您是当前网页的第<%=count%>位访客
      

EL表达式

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

​ ${变量名} 变量名就是setAttrribute对应的key值.

​ 1. EL对于4种域对象的默认查找顺序:

​ pageContext->request->session->application

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

  1. 指定作用域进行查找

    ${内置对象Scope.name}

    例如:${sessionScope.name}

    数据级联:

    <%
    //        pageContext.setAttribute("name", "page");//优先级最高,最先查找
    //        request.setAttribute("name", "request");
    //        session.setAttribute("name","session");
    //        application.setAttribute("name","application");
    //        //request.getRequestDispatcher("el2.jsp").forward(request,response);
    
            User user = new User(1,"张三",98.5,new Address(1,"欻大"));
            pageContext.setAttribute("user",user);
    
        %>
        <table>
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>成绩</th>
                <th>地址</th>
            </tr>
            <tr>
                <td>${user.id}</td>
                <%
                    //((User)pageContext.getAttribute("user")).getId();
                %>
                <td>${user.name}</td>
                <td>${user.score}</td>
                <td>${user.address.value}</td>
            </tr>
        </table>
    

    $(user["id"])

​ EL执行表达式

​ &&||! < > <= >=

&&and ||or ! not == eq !=ne  <lt >gt  <=le   >=ge  
empty变量为null,长度为0的string,size为0的集合

JSTL

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

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

JSTL的使用

  1. 需要导入jar包(两个jstl,jar standard.jar)

    存放的位置是web/WEB-INF/lib

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

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

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

JSTL优点

1. 通过了统一的标签
	2. 可以用于编写各种动态功能
  • 常用核心的标签:

set、out、remove、catch

set:向域对象添加数据

<%
	reuqest.setAttribute(Key,value)
%>

<c:set var="name" value="tom" scope="request"></c:set>

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

out:输出域对象中的数据

    <c:set var="name" value="tom"></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:捕获异常

    <c:catch var="error">
        <%
            int a = 1/0;
        %>
    </c:catch>
    ${error}
  • 条件标签

    • 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="1" step="2" end="5" varStatus="sta">
              <%--{sta.index} - ${str}<br/>--%>
              ${sta.count} - ${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="32145.23434" maxFractionDigits="3" maxIntegerDigits="2"></fmt:formatNumber>
      

      函数标签库

          <%
              request.setAttribute("ignfo", "Java,C");
          %>
          ${fn:contains(ignfo, "Python") }<br/>
          ${fn:startsWith(ignfo, "Java")}<br/>
          ${fn:endsWith(ignfo, "C")}<br/>
          ${fn:indexOf(ignfo, "va")}<br/>
          ${fn:replace(ignfo,"C", "Python")}<br/>
          ${fn:substring(ignfo, 2,3 )}<br/>
          ${fn:split(ignfo, "," )[0]}-${fn:split(ignfo, ",")[1]}<br/>
      

过滤器

  • Filter

    功能:

    1. 用来拦截传入的请求和传出的响应
    2. 修改或以某种方式处理正在客户端和服务端之间交换的数据流

    如何使用?

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

public class CharacterFilter 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>com.gopan.filter.CharacterFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>character</filter-name>
        <url-pattern>/login</url-pattern>
        <url-pattern>/text</url-pattern>
    </filter-mapping>

注意:Filter处理完业务逻辑之后,一定要添加filterChain.doFilter(servletRequest,servletResponse);

Filter生命周期

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

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

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

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

destory:只调用一次mTomcat关闭时调用

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

    <filter>
        <filter-name>character</filter-name>
        <filter-class>com.gopan.filter.CharacterFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>character</filter-name>
        <url-pattern>/login</url-pattern>
        <url-pattern>/text</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>myfilter</filter-name>
        <filter-class>com.gopan.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myfilter</filter-name>
        <url-pattern>/login</url-pattern>
        <url-pattern>/text</url-pattern>
    </filter-mapping>

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

@WebFilter("/login")
public class Myfilter implements Filter{
    
}

实际开发中的Filter的使用场景

  1. 统一处理中文乱码

  2. 屏蔽,敏感词

    @WebFilter("/test")
    public class WordFilter  implements Filter {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletRequest.setCharacterEncoding("UTF-8");
            //将敏感词替换成****
            String name = servletRequest.getParameter("name");
            System.out.println(name);
            name = name.replaceAll("敏感词","***");
            System.out.println(name);
            servletRequest.setAttribute("name", name);
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
    @WebServlet("/test")
    public class TestServlet extends HttpServlet {
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String name = (String) req.getAttribute("name");
            System.out.println(name);
        }
    }
    
  3. 控制资源的访问权限

文件上传下载

  • JSP

    1. input的type设置为file
    2. form表单的method设置为post,get请求会将文件名传给服务端,而不是文件本身
    3. form表单的enctype值设置为multipart/form-data,以二进制的形式传输数据
  • Servlet

    fileupload组件可以将所有的请求信息都解析成FileIteam对象,可以通过FileItem对象的操作完成上传,面向对象的思想。

        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    /*        //输入流
            req.setCharacterEncoding("UTF-8");
            ServletInputStream inputStream = req.getInputStream();//字节流
            Reader reader = new InputStreamReader(inputStream);//字符流
            BufferedReader bufferedReader = new BufferedReader(reader);//缓冲字符流
    
            //输出流将数据流输出到本地
            //获取文件绝对路径
            String path = req.getServletContext().getRealPath("file/copy.txt");
            OutputStream outputStream = new FileOutputStream(path);
            Writer writer =new OutputStreamWriter(outputStream);
            BufferedWriter bufferedWriter = new BufferedWriter(writer);
            String str="";
            while((str = bufferedReader.readLine())!=null){
                System.out.println(str);
                bufferedWriter.write(str);
            }
            bufferedWriter.close();
            writer.close();
            outputStream.close();
            bufferedReader.close();
            reader.close();
            inputStream.close();*/
    
    
            /*int temp = 0;
            while ((temp = inputStream.read())!=-1){
                System.out.println(temp);
            }*/
    
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            try {
                List<FileItem> list = servletFileUpload.parseRequest(req);
                for (FileItem fileItem : list) {
                    if(fileItem.isFormField()){
                        String name = fileItem.getFieldName();
                        String value = fileItem.getString("UTF-8");
                        System.out.println(name + ":" + value);
                    }else {
                        String fileNmae = fileItem.getName();
                        long size = fileItem.getSize();
                        System.out.println(fileNmae+ ":"+size+"Byte");
                        InputStream inputStream = fileItem.getInputStream();
    
                        String path = req.getServletContext().getRealPath("file/"+fileNmae);
                        OutputStream outputStream =new FileOutputStream(path);
    
                        int temp = 0;
                        while((temp = inputStream.read())!=-1){
                            outputStream.write(temp);
                        }
                        outputStream.close();
                        inputStream.close();
    
                        System.out.println("上传成功...");
                    }
                }
    
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
    
    
        }
    
        <form enctype="multipart/form-data" action="/upload" method="post">
            <input type="text" name="desc"><br/>
            <input type="file" name="file"><br/>
            <input type="submit" value="上传">
    
        </form>
    

文件下载

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String type= req.getParameter("type");
        String fileName = "";
        switch (type){
            case "png":
                fileName = "123.png";
                break;
            case "txt":
                fileName = "test.txt";
                break;
        }
        //设置响应方式
        resp.setContentType("application/x-msdownload");


        //设置下载之后的文件名
        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){
            outputStream.write(temp);
        }
        inputStream.close();
        outputStream.close();
    }

Ajax

asnchronous javascript and XML 异步的JavaScript和XML

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

优点:

  1. 局部刷新,效率更高
  2. 用户体验更好

基于jQuery的AJAX

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-1.7.2.js"></script>
    <script type="text/javascript">
        $(function () {
            var btn = $("#btn");
            btn.click(function () {
                $.ajax({
                    url:'/test',
                    type:'post',
                    data:'id=1',
                    dataType:'text',
                    success:function (data) {
                        $("#id").val(data.id);
                        $("#name").val(data.name);
                        $("#score").val(data.score);
                    },
                    error:function () {
                        alert("服务器正在维护中...")
                    },
                    complete:function () {
                        alert("请求完成!")
                    }
                });
            });
        })


    </script>
</head>
<body>
    编号:<input type="text" id="id"/><br/>
    姓名:<input type="text" id="name"/><br/>
    成绩:<input type="text" id="score"/><br/>
    <input type="button" value="提交" id="btn">
</body>
</html>

不能用表单的提交方式,改用JjQuery方式动态绑定事件来提交。

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

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {     
        String id =req.getParameter("id");
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String str = "HRllo";
        resp.getWriter().write(str);
    }

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

  • 客户端请求方式不同

    • 传统:浏览器发送同步请求(Form,a)
    • AJAX:异步引擎对象发送异步请求
  • 服务器响应方式不同

    • 传统:响应一个完整的JSP页面
    • JAJAX:响应需要的数据
  • 客户端处理方式不同

    • 传统:需要等待服务器完成响应并且重新加载整个页面之后,用户才能进行后续的操作
    • AJAX:动态更新页面中的局部内容,不影响用户的其他操作

AJAX原理

1591902727930

基于jQuery的AJAX语法

$.ajax({属性})

  • 常用的属性参数:
    • url 请求的后端服务地址
    • type请求的范式,默认get
    • data请求的参数
    • dataType服务器返回的数据类型text/json
    • success请求成功的回调函数
    • error请求失败的回调函数
    • complete请求完成的回调函数(无论成功还是失败,都会调用)

JSON

JavaScript Object Notion 一种轻量级数据交互格式,完成js与Java等后端开发语言对象数据之间的转换

客户端和服务器之间传递对象数据,需要用到JSON格式

public class User {
    private Integer id;
    private String name;
    private Double score;

    public User(Integer id, String name, Double score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }
}
        User user = new User(1, "张三", 56.2);
var user = {
	id:1,
	name:"张三",
	score:45.5
}
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = new User(1, "张三", 56.2);
        resp.setCharacterEncoding("UTF-8");
//        resp.getWriter().write(user.toString());
        //需要将Java对象转换成JSON格式
        JSONObject jsonObject = JSONObject.fromObject(user);
        resp.getWriter().write(jsonObject.toString());
    }

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-1.7.2.js"></script>
    <script type="text/javascript">
        $(function () {
            var btn = $("#btn");
            btn.click(function () {
                $.ajax({
                    url:'/test',
                    type:'post',
                    data:'id=1',
                    dataType:'json',
                    success:function (data) {
                        $("#id").val(data.id);
                        $("#name").val(data.name);
                        $("#score").val(data.score);
                    },
                    error:function () {
                        alert("服务器正在维护中...")
                    },
                    complete:function () {
                        alert("请求完成!")
                    }
                });
            });
        })


    </script>
</head>
<body>
    编号:<input type="text" id="id"/><br/>
    姓名:<input type="text" id="name"/><br/>
    成绩:<input type="text" id="score"/><br/>
    <input type="button" value="提交" id="btn">

AJAX

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-1.7.2.js"></script>
    <script>
        $(function () {

            //修改城市
            $("#province").change(function () {
                var id = $(this).val()
                $.ajax({
                    url:"location",
                    type:"POST",
                    data:"id="+id+"&type=province",
                    dataType:"JSON",
                    success:function (data) {
                        console.log(data)
                        var content = "";
                        var cities = data.cities;
                        for (var  i=0; i<cities.length;i++){
                            content += "<option>"+ cities[i] + "</option>";
                        }
                        $("#city").html(content);

                        var content = "";
                        var areas = data.areas;
                        for (var  i=0; i< areas.length;i++){
                            content += "<option>"+ areas[i] + "</option>";
                        }
                        $("#area").html(content);

                    }
                });

            });


            //修改城市
            $("#city").change(function () {
                var id = $(this).val()
                $.ajax({
                    url:"location",
                    type:"POST",
                    data:"id="+id+"&type=city",
                    dataType:"JSON",
                    success:function (data) {
                        var content = "";
                        for(var i=0;i<data.length;i++){
                            content += "<option>"+ data[i] + "</option>";
                        }
                        $("#area").html(content);
                    }
                });
            });
        });

    </script>
</head>
<body>
    省:<select id="province">
        <option value="陕西省">陕西省</option>
        <option value="河南省">河南省</option>
        <option value="江苏省">江苏省</option>
    </select>
    市<select id="city">
        <option value="西安市">西安市</option>
        <option value="宝鸡市">宝鸡市</option>
        <option value="渭南市">渭南市</option>
    </select>
    区<select id="area">
        <option>雁塔区</option>
        <option>莲湖区</option>
        <option>新城区</option>
    </select>

</body>
</html>
@WebServlet("/location")
public class LocationServlet extends HttpServlet {
    private static Map<String, List<String>> cityMap;
    private static Map<String, List<String>> procinceMap;

    static {
        cityMap = new HashMap<>();
        List<String> areas = new ArrayList<>();
        areas.add("雁塔区");
        areas.add("莲湖区");
        areas.add("新城区");
        cityMap.put("西安市",areas);
        areas = new ArrayList<>();
        areas.add("陈仓区");
        areas.add("渭滨区");
        areas.add("新城区");
        cityMap.put("宝鸡市", areas);
        areas = new ArrayList<>();
        areas.add("高新区");
        areas.add("临渭区");
        areas.add("新城区");
        cityMap.put("渭南市", areas);
        areas = new ArrayList<>();
        areas.add("高新A区");
        areas.add("临渭B区");
        areas.add("新城C区");
        cityMap.put("惠州市", areas);
        areas = new ArrayList<>();
        areas.add("陈仓A区");
        areas.add("渭滨B区");
        areas.add("新城C区");
        cityMap.put("潮州市", areas);
/*        areas = new ArrayList<>();
        areas.add("雁塔A区");
        areas.add("莲湖B区");
        areas.add("新城C区");
        cityMap.put("宝鸡市",areas);*/

        procinceMap = new HashMap<>();
        List<String> cites = new ArrayList<>();
        cites.add("西安市");
        cites.add("宝鸡市");
        cites.add("深圳市");
        procinceMap.put("陕西省",cites);
        cites = new ArrayList<>();
        cites.add("南宁市");
        cites.add("广州市");
        cites.add("珠海市");
        procinceMap.put("河南省",cites);
        cites = new ArrayList<>();
        cites.add("惠州市");
        cites.add("潮州市");
        cites.add("香港市");
        procinceMap.put("江苏省",cites);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        String type = req.getParameter("type");
        String id = req.getParameter("id");
        switch (type){
            case "city":
                List<String>  areas = cityMap.get(id);
                JSONArray jsonArray = JSONArray.fromObject(areas);
                resp.getWriter().write(jsonArray.toString());
                break;
            case "province":
                List<String>  citis = procinceMap.get(id);
                String  city = citis.get(0);
                List<String> cityAreas = cityMap.get(city);
                Location location =new Location();
                location.setAreas(cityAreas);
                location.setCities(citis);
                JSONObject jsonObject = JSONObject.fromObject(location);
                resp.getWriter().write(jsonObject.toString());
                int i = 0;
                break;
        }
    }
}

JDBC

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

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

1591903568331

JDBC体系结构

JDBC接口包括两个层面:

  • 面向应用的API,提供程序员调用
  • 面向数据库API,供厂商开发数据库的驱动程序

1591903683341

JDBC API

提供者:Java官方

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

java.sql和jjavax.sql

  • DriverManager类
  • Connection接口
  • Statement接口
  • ResultSet接口

DriverManager

提供者:Java官方

作用:管理不同的JDBC驱动

JDBC驱动

提供者:数据库厂商

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

JDBC的使用

  1. 加载数据库驱动,Java程序和数据库之间的桥梁
  2. 获取Connection,Java程序与数据库的一次链接
  3. 创建Statement对象,由Connection产生,执行SQL语句
  4. 如果需要接收返回值,创建ResultSet对象,保存Statement执行之后的所查询到的结果。

PreparedStatement

Statement的子类,提供了SQL占位符的功能

使用Statement进行开发有两种问题:

  1. 需要频繁拼接String字符串,出错频率较高
  2. 存在SQL注入的风险

SQL注入:利用某些系统没有对用户输入的信息进行充分检测,在用户输入的数据中注入非法的SQL语句,从而利用系统的SQL引擎完成恶意行为的做法

数据库连接池

JDBC开发流程:

  • 加载驱动(只需要加载一次)
  • 建立数据库连接(Connection)
  • 执行sql语句(Statement)
  • ResultSet接收结果集(查询)
  • 断开连接,释放资源

数据库连接对象是通过DriverManager来获取的,每次获取都需要向数据库申请获取连接,验证用户和密码

执行完SQL语句后断开连接,这种方式会造成资源的浪费,数据库资源没有得到很好的重复利用。

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

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

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

数据库连接池

JDBC的数据库连接池使用java.sql.DataSourse接口来完成的,DataSourse是Java官方提供的接口,使用的时候开发者并不需要自己来实现该接口,可以用第三方工具,C3P0是一个第三方实现,实际开发中直接,使用C3P0ji'wan'cheng2是菊科连接池的操作。

  1. 导入jar架包。

    传统方式拿到的Connection

    com.mysql.cj.jdbc.ConnectionImp1@557caf28
    

    C3P0拿到的Connection

    com.mchange.v2.c3p0.impl.NewPeoxyConnection@4988d8b8
    
  2. public class DataSourceTest {
        public static void main(String[] args) {
    
            try {
                //创建C3P0
                ComboPooledDataSource dataSource = new ComboPooledDataSource();
                dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
                dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8");
                dataSource.setUser("root");
                dataSource.setPassword("123456");
                Connection conn = dataSource.getConnection();
                System.out.println(conn);
                //返回到数据库池中
                conn.close();
            } catch (PropertyVetoException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    

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

    1. 配置文件的名字必须是c3p0-config.xml
    2. 初始化ComboPooledDataSource,传入的参数的必须是c3p0-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">123456</property>
            <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/test</property>
    
            <!-- 初始化连接池连接数量 -->
            <property name="initialPoolSize">5</property>
            <!-- 数据库连接池最小的数据库连接数 -->
            <property name="minPoolSize">5</property>
            <!-- 数据库连接池最大的数据库连接数 -->
            <property name="maxPoolSize">10</property>
            <!-- 连接数不足,一次向数据库服务器申请多少个链接 -->
            <property name="acquireIncrement">5</property>
    
        </named-config>
    </c3p0-config>
    
    public class DataSourceTest {
    public static void main(String[] args) {
        try {
            //创建C3P0
            ComboPooledDataSource dataSource = new ComboPooledDataSource("testc3p0");
            Connection conn = dataSource.getConnection();
            System.out.println(conn);
            //返回到数据库池中
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    }
    

DBUtils

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

  1. 导入架包

    ResultHandler接口是用来处理结果集,可以将查询到的结果集转换成java对象,提供了4

    中实现类

    • BeanHander 讲结果集映射成java对象Student
    • BeanListHandler 将结果集映射成List集合List
    • MapHandler 将结果集映射成Map对象
    • MapListHandler 将结果集映射成MapLsit结合
原文地址:https://www.cnblogs.com/itgopan/p/13932607.html