靜態web資源(如html 頁面):指web頁面中供人們瀏覽的數據始終是不變。html
動態web資源:指web頁面中供人們瀏覽的數據是由程序產生的,不一樣時間點訪問web頁面看到的內容各不相同。前端
靜態web資源開發技術:HTML、CSS、JavaScript。java
動態web資源開發技術:JSP/Servlet、ASP、PHP等。在Java中,動態web資源開發技術統稱爲Java Web。mysql
ASP:微軟,國內最先流行的是ASP,在HTML中嵌入了VB的腳本,ASP+COM,維護成本高。web
PHP:開發速度很快,功能很強大,跨平臺,代碼簡單,可是沒法承載大訪問量的狀況(侷限性)。sql
JSP/Servlet:sun公司主推的B/S架構,基於java語言,能夠承載三高問題(高併發,高可用,高性能)。數據庫
B/S:瀏覽器和服務器;C/S:客戶端和服務器。apache
服務器用來處理用戶的一些請求,響應給用戶一些數據。編程
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:官網下載(http://tomcat.apache.org/)壓縮包,解壓至指定目錄(可選:配置環境變量)。
在bin目錄下點擊startup.bat啓動,在瀏覽器網址欄輸入localhost:8080測試。
網站是如何進行訪問的:
Http(超文本傳輸協議):http是一個簡單的請求-響應協議,它一般運行在TCP之上。(默認端口:80)
Https:443
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:項目架構管理工具,自動導入jar包(約定大於配置)。
下載Maven後解壓,配置環境變量,將bin目錄的路徑配置到path中,在cmd中輸入mvn-version,查看是否配置成功
在conf目錄下setting的
在conf目錄下setting的
<!-- 設置阿里雲鏡像--> <mirror> <id>alimaven</id> <mirrorOf>central</mirrorOf> <name>aliyun maven</name> <url>https://maven.aliyun.com/repository/public/</url> </mirror>
pom.xml:maven的核心配置文件
因爲maven的約定大於配置,咱們以後寫的配置文件可能沒法導出或者沒法生效,就須要在maven配置下面配置resouce。
servlet就是sun公司開發動態web的一門技術,sun公司在API中提供了一個接口叫Servlet,若是須要開發一個Servlet程序,須要編寫一個類去實現Servlet接口,再把開發好的java類部署到web服務器中。
sun公司有兩個Servlet接口的默認實現類:HttpServlet和GenericServlet
構建一個maven項目,刪除裏面的src項目,之後就直接新建model,這個空的工程就是Maven的主工程。
關於Maven父子工程的理解:
父項目中會有
<modules> <module>servlet-01</module> </modules>
子項目中有
<parent> <artifactId>javaweb-02-servlet</artifactId> <groupId>com.zr</groupId> <version>1.0-SNAPSHOT</version> </parent>
Maven環境優化:修改web.xml爲最新的,將Maven的結構搭建完整。
編寫一個普通類,實現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); } }
<!--註冊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>
Servlet是由Web服務器調用,web服務器收到請求後,會:
一個Servlet能夠指定一個映射路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
一個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>
一個Servlet能夠指定通用映射路徑
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
默認請求
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
一個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>
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
發現都被打包到了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
web服務器接收到客戶端的http請求,針對這個請求,分別建立一個表明請求的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;
向瀏覽器輸出消息
下載文件
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); } }
如何生成驗證碼:
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測試
重定向和轉發的區別:
相同點:頁面都會發生跳轉
不一樣點:
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表明客戶端的請求,用戶經過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
常見應用:網站登陸一次後,下次能夠直接進入。
從請求中拿到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
session:
服務器會給每個用戶(瀏覽器)建立一個session對象
一個session獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個session就存在
用戶登陸以後,整個網站均可以訪問,-->保存用戶的信息
session和cookie的區別:
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:java server pages,Java服務器端界面,和servlet同樣,用於開發動態web技術。
特色
在服務器內部,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做爲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>
<%@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.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:客戶端向服務器發送數據,產生的數據,一個用戶使用完了,其它用戶可能還用,好比:聊天記錄
<!-- 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表達式:${}
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標籤使用步驟
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有特定的寫法:
通常用來和數據庫的字段作映射 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:model,view,controller 模型視圖控制器
Model
View
Controller(Servlet)
登陸--->接收用戶的登陸請求--->處理用戶的請求(得到用戶登陸的參數 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>
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(); } } } }