JavaWeb知識梳理

平遙發表於2020-12-06

JavaWeb

靜態web資源(如html 頁面):指web頁面中供人們瀏覽的資料始終是不變。

動態web資源:指web頁面中供人們瀏覽的資料是由程式產生的,不同時間點訪問web頁面看到的內容各不相同

靜態web資源開發技術:HTML、CSS、JavaScript。

動態web資源開發技術:JSP/Servlet、ASP、PHP等。在Java中,動態web資源開發技術統稱為Java Web。

Web伺服器

技術講解

ASP:微軟,國內最早流行的是ASP,在HTML中嵌入了VB的指令碼,ASP+COM,維護成本高。

PHP:開發速度很快,功能很強大,跨平臺,程式碼簡單,但是無法承載大訪問量的情況(侷限性)。

JSP/Servlet:sun公司主推的B/S架構,基於java語言,可以承載三高問題(高併發,高可用,高效能)。

B/S:瀏覽器和伺服器;C/S:客戶端和伺服器。

Web伺服器

伺服器用來處理使用者的一些請求,響應給使用者一些資料。

IIS:微軟的,主要用於ASP,Windows中自帶的伺服器。

Tomcat:Tomcat是Apache 軟體基金會(Apache Software Foundation)的Jakarta 專案中的一個核心專案,最新的Servlet 和JSP 規範總是能在Tomcat 中得到體現,Tomcat 5支援最新的Servlet 2.4 和JSP 2.0 規範。因為Tomcat 技術先進、效能穩定,而且免費,因而深受Java 愛好者的喜愛並得到了部分軟體開發商的認可,成為目前比較流行的Web 應用伺服器。

Tomcat 伺服器是一個免費的開放原始碼的Web 應用伺服器,屬於輕量級應用伺服器,在中小型系統和併發訪問使用者不是很多的場合下被普遍使用,是開發和除錯JSP 程式的首選。對於一個JavWeb初學者來說,是最好的選擇。

Tomcat 實際上執行JSP 頁面和Servlet。

Tomcat

安裝Tomcat:官網下載(http://tomcat.apache.org/)壓縮包,解壓至指定目錄(可選:配置環境變數)。

在bin目錄下點選startup.bat啟動,在瀏覽器網址欄輸入localhost:8080測試。

網站是如何進行訪問的:

  • 輸入使用者名稱,回車
  • 檢查本機的C:\Windows\System32\drivers\etc\hosts配置檔案有沒有這個域名的對映
    • 有就直接返回對應的ip地址
    • 沒有就去DNS(全世界的域名管理)伺服器上尋找,找到就返回

Http

Http(超文字傳輸協議):http是一個簡單的請求-響應協議,它通常執行在TCP之上。(預設埠:80)

Https:443

  • Http1.0:客戶端可以與web伺服器連線後,只能獲得一個web資源,斷開連線。
  • Http1.1:客戶端可以與web伺服器連線後,可以獲得多個web資源。

Http請求

  • 客戶端----發請求----伺服器

百度為例:

Request URL: https://www.baidu.com/    請求地址
Request Method: GET    請求方法
Status Code: 200 OK    狀態碼
Remote Address: 180.101.49.11:443   遠端地址
Referrer Policy: no-referrer-when-downgrade 

Http響應

  • 伺服器----發請求----客戶端

百度響應:

Cache-Control: private    快取控制
Connection: keep-alive    保持連線
Content-Encoding: gzip    編碼
Content-Type: text/html;charset=utf-8    型別

請求方式:

get:請求能夠攜帶的引數比較少,大小有限制,會在瀏覽器位址列顯示引數的內容,不安全,但是高效。

post:請求能夠攜帶的引數沒有限制,大小沒有限制,不會再瀏覽器位址列顯示引數的內容,安全,但不高效。

響應狀態碼:

200:請求響應成功

3**:請求重定向

404:找不到資源

500:伺服器程式碼錯誤,502:閘道器錯誤

Maven

Maven:專案架構管理工具,自動匯入jar包(約定大於配置)。

下載Maven後解壓,配置環境變數,將bin目錄的路徑配置到path中,在cmd中輸入mvn-version,檢視是否配置成功

在conf目錄下setting的 下配置本地倉庫

D:\Environments\apache-maven-3.6.3\maven-repo

在conf目錄下setting的 中配置阿里雲的映象

<!-- 設定阿里雲映象-->
<mirror>
    <id>alimaven</id>
    <mirrorOf>central</mirrorOf>
    <name>aliyun maven</name>
    <url>https://maven.aliyun.com/repository/public/</url>
</mirror>

pom.xml

pom.xml:maven的核心配置檔案

由於maven的約定大於配置,我們之後寫的配置檔案可能無法匯出或者無法生效,就需要在maven配置下面配置resouce。

Servlet

servlet就是sun公司開發動態web的一門技術,sun公司在API中提供了一個介面叫Servlet,如果需要開發一個Servlet程式,需要編寫一個類去實現Servlet介面,再把開發好的java類部署到web伺服器中。

HelloServlet

sun公司有兩個Servlet介面的預設實現類:HttpServlet和GenericServlet

  1. 構建一個maven專案,刪除裡面的src專案,以後就直接新建model,這個空的工程就是Maven的主工程。

  2. 關於Maven父子工程的理解:

父專案中會有

<modules>
    <module>servlet-01</module>
</modules>

​ 子專案中有

 <parent>
        <artifactId>javaweb-02-servlet</artifactId>
        <groupId>com.zr</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
  1. Maven環境優化:修改web.xml為最新的,將Maven的結構搭建完整。

  2. 編寫一個普通類,實現Servlet介面,繼承HttpServlet。

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter();  //響應流
        writer.println("Hello Servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
  1. 編寫Servlet的對映:我們寫的是java程式,但是要通過瀏覽器訪問,而瀏覽器要連線web伺服器,所以我們要在web伺服器註冊我們寫的Servlet,還需要給它一個瀏覽器能夠訪問的路徑。
<!--註冊Servlet-->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.zr.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet請求路徑-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. 配置Tomcat
  2. 啟動測試

Servlet原理

Servlet是由Web伺服器呼叫,web伺服器收到請求後,會:

Mapping

  1. 一個Servlet可以指定一個對映路徑

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  2. 一個Servlet可以指定多個對映路徑

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    
  3. 一個Servlet可以指定通用對映路徑

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
    
  4. 預設請求

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  5. 一個Servlet可以指定一些字尾或者字首對映路徑

    <!--*前面不能加任何對映的路徑-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.zzr</url-pattern>
    </servlet-mapping>
    

優先順序問題:

指定了固有的對映路徑,優先順序最高,找不到就會走預設的處理請求。

處理404頁面

<!--404-->
<servlet>
    <servlet-name>error</servlet-name>
    <servlet-class>com.zr.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>error</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

ServletContext

web容器在啟動的時候,它會為每一個web程式都建立一個ServletContext物件,它代表了當前的 web應用。

  • 共享資料

    我在這個Servle中儲存的資料可以在另外一個Servle中拿到

    public class HelloServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("hello");
            //this.getInitParameter();   初始化引數
            //this.getServletConfig();   Servlet的配置
            //this.getServletContext();   Servlet上下文
    
            ServletContext context = this.getServletContext();
            String username = "週週";
            context.setAttribute("username",username);//將一個資料儲存在ServletContext中
    
        }
    }
    
    public class GetServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext context = this.getServletContext();
            String username = (String) context.getAttribute("username");
    
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/html");
            resp.getWriter().println("名字:"+username);
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
    }
    
    <servlet>
            <servlet-name>hello</servlet-name>
            <servlet-class>com.zr.servlet.HelloServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
    <servlet>
        <servlet-name>get</servlet-name>
        <servlet-class>com.zr.servlet.GetServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>get</servlet-name>
        <url-pattern>/get</url-pattern>
    </servlet-mapping>
    

    測試訪問結果

  • 獲取初始化引數

    <!--配置一個web應用的初始化引數-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybaits</param-value>
    </context-param>
    
    <servlet>
            <servlet-name>gp</servlet-name>
            <servlet-class>com.zr.servlet.ServletDemo03</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>gp</servlet-name>
            <url-pattern>/gp</url-pattern>
        </servlet-mapping>
    
    public class ServletDemo03 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext context = this.getServletContext();
            String url = context.getInitParameter("url");
            resp.getWriter().println(url);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    
  • 請求轉發

    public class ServletDemo04 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext context = this.getServletContext();
            RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//轉發的請求路徑
            requestDispatcher.forward(req,resp);//轉發
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    
    <servlet>
        <servlet-name>sd4</servlet-name>
        <servlet-class>com.zr.servlet.ServletDemo04</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sd4</servlet-name>
        <url-pattern>/sd4</url-pattern>
    </servlet-mapping>
    
  • 讀取資原始檔

    properties

    • 在Java目錄下新建propreties(需要在pom.xml下配置resources)
    • 在resources目錄下新建properties

    發現都被打包到了target下的class目錄下,我們稱這個路徑為類路徑classpath。

    public class ServletDemo05 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
            Properties properties = new Properties();
            properties.load(is);
            String username = properties.getProperty("username");
            String password = properties.getProperty("password");
            resp.getWriter().println("username:"+username);
            resp.getWriter().println("password:"+password);
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    <servlet>
        <servlet-name>sd5</servlet-name>
        <servlet-class>com.zr.servlet.ServletDemo05</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sd5</servlet-name>
        <url-pattern>/sd5</url-pattern>
    </servlet-mapping>
    
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.xml</exclude>
                </excludes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    
    //檔案 db.properties
    username=root
    password=123456
    

HttpServletResponse

web伺服器接收到客戶端的http請求,針對這個請求,分別建立一個代表請求的HttpServletRequest物件,代表響應一個HttpServletResponse。

  • 如果要獲取客戶端請求過來的引數:HttpServletRequest
  • 如果要給客戶端響應一些資訊:HttpServletResponse

簡單分類

負責向瀏覽器傳送資料的方法

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

響應的狀態碼

int SC_OK = 200;
...
int SC_MULTIPLE_CHOICES = 300;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
...
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_BAD_GATEWAY = 502;

下載檔案

  1. 向瀏覽器輸出訊息

  2. 下載檔案

    1. 獲取下載檔案的路徑
    2. 下載的檔名
    3. 讓瀏覽器支援下載我們需要的東西
    4. 獲取下載檔案的輸入流
    5. 建立緩衝區
    6. 獲得OutputStream物件
    7. 將FileOutputStream流寫入到buffer緩衝區
    8. 將OutputStream緩衝區中的物件輸出到客戶端
    public class FileServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //1. 獲取下載檔案的路徑
            String realPath = "D:\\IDEACode\\javaweb-02-servlet\\response\\src\\main\\resources\\1.PNG";
            System.out.println("下載檔案的路徑:"+realPath);
            //2. 下載的檔名
            String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
            //3. 讓瀏覽器支援下載我們需要的東西
            resp.setHeader("Content-Disposition","attachment;filename="+fileName);
            //4. 獲取下載檔案的輸入流
            FileInputStream in = new FileInputStream(realPath);
            //5. 建立緩衝區
            int len = 0;
            byte[] buffer = new byte[1024];
            //6. 獲得OutputStream物件
            ServletOutputStream out = resp.getOutputStream();
            //7. 將FileOutputStream流寫入到buffer緩衝區 將OutputStream緩衝區中的物件輸出到客戶端
            while ((len=in.read(buffer))>0){
                out.write(buffer,0,len);
    
            }
            in.close();
            out.close();
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

驗證碼功能

如何生成驗證碼:

  • 前端
  • 後端:需要用Java的圖片類,生成一個圖片
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //讓瀏覽器5秒重新整理一次
        resp.setHeader("refresh","5");
        //建立圖片
        BufferedImage image = new BufferedImage(300,60,BufferedImage.TYPE_INT_RGB);
        //得到圖片
        Graphics g = image.getGraphics(); //筆
        //設定圖片的背景顏色
        g.setColor(Color.green);
        g.fillRect(0,0,300,60);
        //給圖片寫資料
        g.setColor(Color.magenta);
        g.setFont(new Font(null,Font.BOLD,70));
        g.drawString(makeNum(),0,60);
        //瀏覽器以圖片的形式開啟
        resp.setContentType("image/png");
        //網站存在快取。不讓瀏覽器快取
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //把圖片顯示出來
        boolean write = ImageIO.write(image,"jpg",resp.getOutputStream());

    }
    //生成隨機數
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-num.length(); i++) {
            sb.append("0");
        }
        num = sb.toString()+num;
        return num;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--註冊Servlet-->
<servlet>
    <servlet-name>image</servlet-name>
    <servlet-class>com.zr.servlet.ImageServlet</servlet-class>
</servlet>
<!--Servlet請求路徑-->
<servlet-mapping>
    <servlet-name>image</servlet-name>
    <url-pattern>/image</url-pattern>
</servlet-mapping>

實現重定向

void sendRedirect(String var1) throws IOException;//重定向
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       /*
       resp.setHeader("Location","/r/image");
       resp.setStatus(302);
        */
       
        resp.sendRedirect("/r/image");
    }

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

配置web.xml測試

重定向和轉發的區別:

相同點:頁面都會發生跳轉

不同點:

  • 請求轉發的時候,url不會改變 307
  • 重定向的時候,url位址列會發生變化 302

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<%--提交的路徑需要尋找到當前專案的路徑--%>
<form action="${pageContext.request.contextPath}/login" method="post">
    使用者名稱:<input type="text" name="username"><br>
    密碼 :<input type="password" name="password"><br>
    <input type="submit">

</form>
</body>
</html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>success</h1>
</body>
</html>
public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("進入這個請求了");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("username:"+username);
        System.out.println("password:"+password);
        resp.sendRedirect("/r/success.jsp");
        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--註冊Servlet-->
<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>com.zr.servlet.RequestTest</servlet-class>
</servlet>
<!--Servlet請求路徑-->
<servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

HttpServletRequest

HttpServletRequest代表客戶端的請求,使用者通過http協議訪問伺服器,http請求中的所有的資訊會被封裝到HttpServletRequest,通過這個HttpServletRequest的方法,獲得客戶端的所有資訊。

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @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 password = req.getParameter("password");
        String[] hobbys = req.getParameterValues("hobbys");

        System.out.println("==================================");
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbys));

        //請求轉發
        //這裡的/代表當前的web應用
        req.getRequestDispatcher("/success.jsp").forward(req,resp);

    }
}

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登入</title>
</head>
<body>
<h1>登入</h1>
<div style="text-align: center">
    <form action="${pageContext.request.contextPath}/login" method="post">
        使用者名稱:<input type="text" name="username"><br>
        密碼:<input type="password" name="password"><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>

</div>
</body>
</html>

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登入成功</h1>
</body>
</html>

web.xml

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.zr.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

cookie

  • 客戶端技術(響應,請求)

session

  • 伺服器技術,可以儲存使用者的會話資訊,我們可以把資訊或資料放在session中

常見應用:網站登入一次後,下次可以直接進入。

從請求中拿到cookie資訊

伺服器響應給客戶端cookie

//儲存使用者上一次訪問的時間
public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解決中文亂碼
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        PrintWriter out= resp.getWriter();
        //cookie,伺服器端從客戶端獲取
        Cookie[] cookies = req.getCookies();//返回陣列,cookie可能存在多個
        //判斷cookie是否存在
        if (cookies!=null){
            //如果存在
            out.write("你上一次訪問的時間是:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //獲取cookie的名字
                if (cookie.getName().equals("lastlogintime")){
                    //獲取cookie中的值

                    long lastlogintime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastlogintime);
                    out.write(date.toLocaleString());

                }
            }
        }else{
            out.write("這是你第一次訪問本站!");
        }
        //伺服器給客戶端發一個cookie
        Cookie cookie = new Cookie("lastlogintime", System.currentTimeMillis()+"");
        //有效期為1天
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);
    }

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

web.xml

<servlet>
    <servlet-name>CookieDemo01</servlet-name>
    <servlet-class>com.zr.servlet.CookieDemo01</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>CookieDemo01</servlet-name>
    <url-pattern>/c1</url-pattern>
</servlet-mapping>

cookie:一般會儲存在本地的使用者目錄下appdata;

  • 一個cookie只能儲存一個資訊
  • 一個web站點可以給瀏覽器傳送多個cookie,最多存放20個cookie
  • cookie的大小有限制4kb
  • cookie瀏覽器上限300個

刪除cookie

  • 不設定有效期,關閉瀏覽器,自動失效
  • 設定有效期時間為0

Session

session:

  • 伺服器會給每一個使用者(瀏覽器)建立一個session物件

  • 一個session獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個session就存在

  • 使用者登入之後,整個網站都可以訪問,-->儲存使用者的資訊

session和cookie的區別:

  • cookie是把使用者的資料寫給使用者的瀏覽器,瀏覽器儲存(可以儲存多個)
  • session是把資料寫到使用者獨佔的session中,伺服器儲存(儲存重要的資訊,減少資源的浪費)
  • session物件由伺服器建立

session儲存資料

package com.zr.pojo;

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

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解決中文亂碼
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //得到session
        HttpSession session = req.getSession();

        //給session存東西
        session.setAttribute("name",new Person("週週",1));
        //獲得session的id
        String id = session.getId();
        //判斷session是不是新建立的
        if(session.isNew()){
            resp.getWriter().write("session建立成功,ID:"+ id);
        }else {
            resp.getWriter().write("session已經存在,ID:"+ id);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解決中文亂碼
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //得到session的資料
        HttpSession session = req.getSession();

        Person person = (Person) session.getAttribute("name");
        System.out.println(person);

    }

    @Overridejava
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
    <servlet-name>SessionDemo01</servlet-name>
    <servlet-class>com.zr.servlet.SessionDemo01</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>SessionDemo01</servlet-name>
    <url-pattern>/s1</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>SessionDemo02</servlet-name>
    <servlet-class>com.zr.servlet.SessionDemo02</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>SessionDemo02</servlet-name>
    <url-pattern>/s2</url-pattern>
</servlet-mapping>

session手動登出

public class SessionDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.removeAttribute("name");
        //手動登出session
        session.invalidate();
    }

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

session自動登出

<!--設定session登出時間-->
<session-config>
    <!--1分鐘後自動失效-->
    <session-timeout>1</session-timeout>
</session-config>

JSP

什麼是JSP

jsp:java server pages,Java伺服器端介面,和servlet一樣,用於開發動態web技術。

特點

  • 寫jsp就像寫html
  • 區別
    • html只給使用者提供靜態的資料
    • jsp頁面可以嵌入Java程式碼,為使用者提供動態資料

jsp原理

在伺服器內部,tomcat中有一個work目錄,jsp最終被轉化成了Java類, jsp本質就是一個servlet。

index_jsp.java原始碼

//初始化
 public void _jspInit() {
  }
//銷燬
  public void _jspDestroy() {
  }
//jspService
  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)

判斷請求

內建的一些物件

    final javax.servlet.jsp.PageContext pageContext; //頁面上下文
    javax.servlet.http.HttpSession session = null;  //session
    final javax.servlet.ServletContext application;  //applicationContext
    final javax.servlet.ServletConfig config;  //config
    javax.servlet.jsp.JspWriter out = null;  //out
    final java.lang.Object page = this;  //page 當前頁
	HttpServletRequest request  //請求
    HttpServletResponse respons  //響應


輸出頁面前增加的程式碼

	  response.setContentType("text/html"); //設定響應的頁面型別
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

以上的物件可以在jsp中直接使用

在jsp頁面中,java程式碼會原封不動的輸出,如果是html程式碼就會被轉化為out.write(".....");

JSP基礎語法

任何語言都有自己的語法 ,jsp作為Java技術的一種運用,它擁有一些自己擴充的語法(瞭解)。Java語法它都支援。

jsp表示式

<%--JSP表示式 輸出時間到客戶端--%>
<%= new java.util.Date()%>

jsp指令碼片段

<%--jsp指令碼片段--%>
<%
  int sum=0;
  for (int i = 0; i < 100; i++) {
    sum+=i;
  }
  out.println("<h1>sum="+sum+"</h1>");
%>

指令碼片段的再實現

<%
  int x=10;
  out.print(x);
%>
<p>這是一個jsp文件</p>
<%
  int y=20;
  out.print(y);
%>


<%--在程式碼中嵌入html元素--%>
<%
  for (int i = 0; i < 5; i++) {
%>
  <h1>helloworld<%=i%></h1>
<%
  }
%>

jsp宣告

<%!
  static {
    System.out.println("loding...");
  }
  private int globalvar=0;
  public void jspInit(){
    System.out.println("進入了方法");
  }
%>

JSP宣告:會被編譯到jsp生成的Java類中。其它的會被生成到jspServer方法中。

JSP的註釋不會在客戶端原始碼顯示,HTML的註釋會在哭護短原始碼顯示。

定製錯誤頁面

<error-page>
    <error-code>404</error-code>
    <location>/error/404.jsp</location>
</error-page>

<error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
</error-page>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>Title</title>
</head>
<body>
<img src="img/500.jpg" alt="500">
</body>
</html>

JSP指令

<%@page% args...>
<%@include file=""%>


<%--會將頁面合二為一--%>
<%@include file="common/header.jsp"%>
<h1>主體</h1>
<%@include file="common/footer.jsp"%>

<hr>
<%--jsp標籤  拼接頁面--%>
<jsp:include page="common/header.jsp"/>
<h1>主體</h1>
<jsp:include page="common/footer.jsp"/>

九大內建物件

  • PageContext 存東西
  • Request 存東西
  • Response
  • Session 存東西
  • Application 【ServletContext】存東西
  • config 【ServletConfig】
  • out
  • page
  • exception

四大作用域

<%--內建物件--%>
<%
    pageContext.setAttribute("name1","周1");//儲存的資料只在一個頁面內有效
    request.setAttribute("name2","周2");//儲存的資料只在一次請求中有效,請求轉發會攜帶
    session.setAttribute("name3","周3");//儲存的資料只在一次會話中有效,開啟瀏覽器到關閉瀏覽器
    application.setAttribute("name4","周4");//儲存的資料在伺服器中有效,開啟伺服器到關閉伺服器   
%>
<%--通過pageContext取值--%>
<%
    //通過尋找的方式
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");//不存在
%>

<%--使用EL表示式輸出  ${}--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>

    <hr>
<%=name5%>

request:客戶端向伺服器傳送資料,產生的資料,使用者看完就沒用了,比如:新聞

session:客戶端向伺服器傳送資料,產生的資料,使用者用完一會還會用,比如:購物車

application:客戶端向伺服器傳送資料,產生的資料,一個使用者使用完了,其它使用者可能還用,比如:聊天記錄

JSP標籤,JSTL標籤,EL表示式

 <!-- jstl表示式的依賴 -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- standard標籤庫 -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

EL表示式:${}

  • 獲取資料
  • 執行運算
  • 獲取web開發的常用物件

JSP標籤:

<%--jsp:include--%>

<%--轉發時候攜帶引數--%>
<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="zr"/>
    <jsp:param name="age" value="22"/>

</jsp:forward>

JSTL表示式

JSTL標籤庫的使用就是為了彌補HTML標籤的不足;它自定義了許多的標籤,可以供我們使用,標籤的功能和Java程式碼一樣。

核心標籤(掌握),格式化標籤,SQL標籤,XML標籤

<%--引入JSTL核心標籤庫--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

JSTL標籤使用步驟

  • 引入對應的taglib
  • 使用其中的方法
  • tomcat中需要引入JSTL的包,否則會報JSTL解析錯誤

c:if

<body>
<h1>if測試</h1>
<hr>
<form action="coreif.jsp" method="get">
    <%-- EL表示式獲取表單中的資料
        ${param.引數名}
    --%>
    <input type="text" name="username" value="${param.username}"/>
    <input type="submit" name="登入">

</form>

<%--    判斷如果提交的使用者是管理員,則登入成功--%>
<c:if test="${param.username=='admin'}" var="isadmin">
    <c:out value="管理員歡迎你!"/>
</c:if>
<c:out value="${isadmin}"/>
</body>

c:choose

<body>
<%--定義一個變數score 值為88--%>
<c:set var="score" value="88"/>
<c:choose>
    <c:when test="${score>=90}">
        你的成績優秀!
    </c:when>
    <c:when test="${score>=80}">
        你的成績良好!
    </c:when>
    <c:when test="${score>=60}">
        你的成績一般!
    </c:when>
    <c:when test="${score<=60}">
        你的成績不合格!
    </c:when>
</c:choose>
</body>

c:forEach

<body>
<%
    ArrayList<String> people = new ArrayList<String>();
    people.add(0,"張三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"趙六");
    people.add(4,"田七");
    request.setAttribute("list",people);
%>
<%-- var 每一次遍歷的變數  items每次遍歷的物件--%>
<c:forEach var="people" items="${list}">
    <c:out value="${people}"/><br>
</c:forEach>
<hr>
<%--開始 結束 步長--%>
<c:forEach var="people" items="${list}" begin="2" end="4" step="2">
    <c:out value="${people}"/><br>
</c:forEach>

</body>

JavaBean

實體類

JavaBean有特定的寫法:

  • 必須要有一個無參構造
  • 屬性必須私有化
  • 必須有對應的get/set方法

一般用來和資料庫的欄位做對映 ORM;

ORM物件關係對映

  • 表--->類
  • 欄位--->屬性
  • 行記錄--->物件

people表

id name age address
1 周1 18 武漢
2 周2 22 廣州
3 周3 100 佛山

建立資料庫相應的欄位後建立java實體類

package com.zr.pojo;
//實體類 一般是和資料庫中的表結構一一對應的
public class People {
    private int id;
    private String name;
    private int age;
    private String address;

    public People() {
    }

    public People(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

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

<%@ page import="com.zr.pojo.People" %><%--
  Created by IntelliJ IDEA.
  User: zr
  Date: 2020/10/11
  Time: 22:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
//    People people = new People();
//    people.setAddress();
//    people.setId();
//    people.setAge();
//    people.setName();
 //和下面的等價
%>
<jsp:useBean id="people" class="com.zr.pojo.People" scope="page"/>
<jsp:setProperty name="people" property="address" value="武漢"/>
<jsp:setProperty name="people" property="id" value="1"/>
<jsp:setProperty name="people" property="age" value="18"/>
<jsp:setProperty name="people" property="name" value="小周"/>

姓名:<jsp:getProperty name="people" property="name"/>
id:<jsp:getProperty name="people" property="id"/>
年齡:<jsp:getProperty name="people" property="age"/>
地址:<jsp:getProperty name="people" property="address"/>
</body>
</html>

MVC三層架構

MVC:model,view,controller 模型檢視控制器

Model

  • 業務處理,業務邏輯(Service)
  • 資料持久層,CRUD(Dao)

View

  • 展示資料
  • 提供操作發起Servlet請求(a,form,img ....)

Controller(Servlet)

  • 接收請求,(req:請求引數,session資訊...)
  • 交給業務層處理相應的程式碼
  • 控制檢視的跳轉
登入--->接收使用者的登入請求--->處理使用者的請求(獲得使用者登入的引數 username password)--->交給業務層處理登入的業務(判斷使用者名稱密碼是否正確)--->Dao層查詢使用者密碼是否正確--->資料庫

過濾器

Filter:過濾器,用來過濾網站的資料:

  • 處理中文亂碼
  • 登入驗證...

Filter編寫:先配置Servlet,jsp依賴

實現Filter(Servlet下的)介面,重寫對應的方法

public class CharacterEncodingFilter implements Filter {
    //初始化   web伺服器啟動就初始化了,隨時等待監聽物件出現
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }
    //Chain :鏈
    /*
    1,過濾器中的所有程式碼,在過濾特定請求時都會執行
    2,必須要讓過濾器過濾同行
    chain.doFilter(request,response);
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;character=UTF-8");

        System.out.println("CharacterEncodingFilter執行前....");
        chain.doFilter(request,response);//讓我們的請求繼續走 如果不寫,程式被攔截停止
        System.out.println("CharacterEncodingFilter執行後....");

    }
    //銷燬   web伺服器關閉的時候,過濾器銷燬
    public void destroy() {
        System.out.println("CharacterEncodingFilter銷燬");

    }
}

servlet顯示亂碼

public class ShowServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //resp.setCharacterEncoding("utf-8");
        //resp.setContentType("text/html");
        resp.getWriter().write("你好世界");
    }

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

配置web.xml

<servlet>
    <servlet-name>showServlet</servlet-name>
    <servlet-class>com.zr.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>showServlet</servlet-name>
    <url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>showServlet</servlet-name>
    <url-pattern>/show</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>CharacterEncoding</filter-name>
    <filter-class>com.zr.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CharacterEncoding</filter-name>
    <!--只要是/servlet的任何請求,都會經過這個過濾器-->
    <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

監聽器

統計網站線上人數:

實現一個監聽器的介面

//統計網站線上人數,統計Session
public class OnlineCountListener implements HttpSessionListener {
    //建立Session監聽
    //一旦建立一個Session就會觸發一次這個事件
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());
        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount==null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);
    }
    //銷燬Session監聽
    //一旦銷燬一個Session就會觸發一次這個事件
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.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);
    }
}
/*
    Session銷燬
    1.手動銷燬  se.getSession().invalidate();
    2.自動銷燬  xml中配置<session-config>
 */

顯示線上人數

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<h1>當前有<span style="color: hotpink"><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人線上</h1>
  </body>
</html>

配置web.xml

<!--註冊監聽器-->
    <listener>
        <listener-class>com.zr.listener.OnlineCountListener</listener-class>
    </listener>

過濾器,監聽器常見應用

監聽器GUI程式設計中經常使用

GUI應用

public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("中秋快樂!"); //新建一個窗體
        Panel panel = new Panel(null); //皮膚
        frame.setLayout(null); //設定窗體的佈局
        frame.setBounds(300,300,500,500); //座標
        frame.setBackground(new Color(0,0,255)); //背景顏色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,255));

        frame.add(panel);
        frame.setVisible(true);

        //監聽事件,監聽關閉事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

使用者登入後才能進入主頁,登出後不能進入主頁

1.使用者登入之後向session中放入使用者的資料

2.進入主頁的時候判斷使用者是否登入,要求在過濾器中實現login.jsp

login.jsp(web包下)

<body>
<h1>登入</h1>
<form action=" /servlet/login" method="post">
    <input type="text" name="username">
    <input type="submit">
</form>
</body>

success.jsp(web/sys包下)

<body>
<h1>主頁</h1>
<a href="/servlet/loginout">登出</a>
</body>

error.jsp(web包下)

<body>
<h1>錯誤</h1>
<h3>使用者名稱錯誤</h3>
<a href="/login.jsp">返回登入頁面</a>
</body>

Login

public class login extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //獲取前端請求的引數
        String username = req.getParameter("username");
        if (username.equals("admin")){
            req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
            resp.sendRedirect("/sys/success.jsp");
        }else {
            resp.sendRedirect("/error.jsp");
        }
    }

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

LoginOut

public class LoginOut extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object user_session = req.getSession().getAttribute("USER_SESSION");
        if (user_session!=null){
            req.getSession().removeAttribute("USER_SESSION");
            resp.sendRedirect("/login.jsp");
        }else {
            resp.sendRedirect("/login.jsp");
        }
    }

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

SysFilter:過濾器

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        filterChain.doFilter(request, response);

        if (req.getSession().getAttribute("USER_SESSION")==null){
            resp.sendRedirect("/error.jsp");
        }
    }

    public void destroy() {
        
    }
}

web.xml

<servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.zr.servlet.login</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/servlet/login</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>loginOut</servlet-name>
        <servlet-class>com.zr.servlet.LoginOut</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>loginOut</servlet-name>
        <url-pattern>/servlet/loginout</url-pattern>
    </servlet-mapping>


    <filter>
        <filter-name>CharacterEncoding</filter-name>
        <filter-class>com.zr.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncoding</filter-name>
        <!--只要是/servlet的任何請求,都會經過這個過濾器-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>SysFilter</filter-name>
        <filter-class>com.zr.filter.SysFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SysFilter</filter-name>
        <!--只要是/sys的任何請求,都會經過這個過濾器-->
        <url-pattern>/sys/*</url-pattern>
    </filter-mapping>

JDBC

Java連線資料庫,匯入JDBC依賴mysql-connector-java,IDEA中連線資料庫

public class TestJdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置資訊
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        //載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        //連線資料庫
        Connection connection = DriverManager.getConnection(url, username, password);
        //向資料庫傳送sql的物件
        Statement statement = connection.createStatement();
        //編寫sql
        String sql = "select * from users";
        //執行查詢sql,返回一個結果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }
        //關閉連線
        rs.close();
        statement.close();
        connection.commit();
    }
}

預編譯sql

public class TestJdbc2 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置資訊
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        //載入驅動
        Class.forName("com.mysql.jdbc.Driver");
        //連線資料庫
        Connection connection = DriverManager.getConnection(url, username, password);
        //向資料庫傳送sql的物件
        Statement statement = connection.createStatement();

        String sql = "insert into users(id,name,password,email,birthday) values(?,?,?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,4);
        preparedStatement.setString(2,"周七");
        preparedStatement.setString(3,"888888");
        preparedStatement.setString(4,"666@qwq.com");
        preparedStatement.setString(5, String.valueOf(new Date(new java.util.Date().getTime())));
        int i = preparedStatement.executeUpdate();
        if (i>0){
            System.out.println("插入成功");
        }
        //關閉連線

        statement.close();
        connection.commit();
    }
}

事務

要麼都成功,要麼都失敗 !

ACID原則,保證資料的安全。

開啟事務

事務提交 commi ()

事務回滾 rollback ()

關閉事務

Junit單元測試

依賴

<!--單元測試-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

簡單使用

@Test註解只在方法上有效,只要加了這個註解的方法,就可以直接執行。

public class TestJdbc3 {

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

轉賬事務(建立account表,欄位id,name,money),使用單元測試

public class TestJdbc3 {

    @Test
    public void test() {
        //配置資訊
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        Connection connection=null;
        //載入驅動
        try {
            Class.forName("com.mysql.jdbc.Driver");
        //連線資料庫
        connection = DriverManager.getConnection(url, username, password);
        //通知資料庫開啟事務
        connection.setAutoCommit(false);
        String sql1 = "update account set money=money-100 where name='A'";
        connection.prepareStatement(sql1).executeUpdate();

        //製造錯誤
        int i=1/0;

        String sql2 = "update account set money=money+100 where name='B'";
        connection.prepareStatement(sql2).executeUpdate();

        connection.commit();//以上sql都執行成功才提交
        System.out.println("提交成功!");
        } catch (Exception e) {
            try {
                //如果出現異常,就回滾事務
                connection.rollback();
                System.out.println("轉賬失敗!");
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

相關文章