高併發系統設計(二十):分散式架構如何跟蹤排查慢請求問題?
1 web的基本概念
進階路程
2 web伺服器
3 tomcat
下載tomcat
官網http://tomcat.apache.org/
解壓後
4 HTTP
5 maven
maven環境搭建
配置環境變數 :
/conf
下的settings.xml
中設定
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里雲公共倉庫</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
<1ocalRepository>D:\Environment\apache-maven-3.6.2\maven-repo</localRepository>
在IDEA中使用maven
根據模板建立maven專案
- 啟動idea
- 建立一個mavenWeb專案
- 等待資源載入
- maven本地倉庫中多了很多包
- IDEA中的maven設定
建立一個普通的maven專案
在IDEA中配置TomCat
maven 設定jdk版本
<properties> <maven.compiler.source>14</maven.compiler.source> <maven.compiler.target>14</maven.compiler.target> </properties>
一些問題
IDEA全域性配置
統一javaapps版本
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> </web-app>
6 servlet *
servlet簡介
- sun公司開發動態Web的技術
- 是sun公司的一個介面, 如果要開發一個servlet程式, 只需要兩個小步驟
1 編寫一個類實現servlet介面
2 把寫好的java類部署到web伺服器中 - 把實現了servlet的java程式叫做, servlet
hello servlet
sun公司有兩個預設的實現類: HTTPServlet
GenericServlet
- 構建一個普通的maven專案, 刪掉src資料夾, 以後的學習就可以在這個專案裡面
- 關於maven父子工程的理解
父專案中會有
<modules>
<module>servlet-01</module>
</modules>
子專案中會有
<parent>
<artifactId>HelloServlet</artifactId>
<groupId>com.karl</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父專案的java子專案可以直接使用
son extends parent
- Maven 環境優化
3.1 修改web.xml為最新的
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
3.2 將Maven結構搭建完整
4. 編寫一個servlet程式
4.1 編寫一個普通類
4.2 實現Servlet介面, 繼承HTTPServlet
package com.karl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.getOutputStream();
PrintWriter writer = resp.getWriter();//響應流
writer.println("hello, servlet! ");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
- 編寫Servlet的對映
為什麼需要對映: 我們寫的是java程式, 但需要通過瀏覽器訪問, 瀏覽器需要連線web伺服器, 所以我們需要在web服務中註冊我們寫的Servlet, 還需要給他一個瀏覽器能訪問的路徑;
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.karl.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 配置tomcat
注意配置專案釋出的目錄 - 啟動測試
servlet 原理
Servlet是由Web伺服器呼叫,web伺服器在收到瀏覽器請求之後,會
Maping
一個servlet可以指定多個對映
一個servlet可以指定通用路徑對映
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
指定字尾對映
優先順序問題
指定了固有的對映路徑優先順序最高,如果找不到就會走預設的處理請求;
servletContext物件
web容器在啟動的時候,它會為每個web程式都建立一個對應的ServletContext物件,它代表了當前的web應用
- 共享資料 : 我在這個Servlet中儲存的資料,可以在另外一個servlet中拿到 ;
放置資料類
package com.karl.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter();//初始化引數
// this.getServletConfig();//servlet配置
// this.getServletContext();//servlet上下文
ServletContext context = this.getServletContext();
String username = "karl";//資料
context.setAttribute("username", username);//將一個數據儲存到了servletContext中
}
}
讀取資料類
package com.karl.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
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.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("名字:"+username);
}
}
servletContext應用
獲取初始化引數
<!--可以配置一些web應用初始化引數-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//讀取初始化引數
ServletContext context = this.getServletContext();
String url = (String)context.getInitParameter("url");
resp.getWriter().println(url);
}
轉發和重定向
doGet(){
...
// RequestDispatcher requestDispatcher = context.getRequestDispatcher("");//轉發的路徑
// requestDispatcher.forward(req,resp);//實現轉發
context.getRequestDispatcher("").forward(req, resp);
...
}
讀取資原始檔
poperties
classpath: java和resource路徑
思路: 需要一個檔案流;
response
下載檔案
HttpServletResponse
web伺服器接收到客戶端的http請求,針對這個請求,分別建立一個代表請求的HttpServletRequest物件,代表響應的一個HttpServletResponse;
- 如果要獲取客戶端請求過來的引數:找HttpServletRequest
- 如果要給客戶端響應一些資訊:找HttpServletResponseI
簡單分類
- 負責向瀏覽器傳送資料的方法
public ServletOutputStream getOutputStream() throws IOException;//其他流
public PrintWriter getWriter() throws IOException;//寫中文
- 向瀏覽器傳送響應頭的方法
public void setDateHeader(String name, long date);
public void addDateHeader(String name, long date);
public void setHeader(String name, String value);
public void addHeader(String name, String value);
public void setIntHeader(String name, int value);
public void addIntHeader(String name, int value);
public void setCharacterEncoding(String charset);
public void setContentLength(int len);
public void setContentType(String type);
public void setBufferSize(int size);
下載檔案
//1 要下載的檔案路徑;
String realPath = "E:\\桌面快捷方式源\\code\\java\\project\\HelloServlet\\response\\src\\main\\resources\\林奚.png";
System.out.println(realPath);
//2 要下載的檔名;
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
System.out.println(fileName);
//3 瀏覽器支援我們下載檔案, 中文檔名用URLEncoder.encoder()編碼, 否則有可能亂碼;
resp.setHeader("Content-Disposition","attachment;filename = "+ URLEncoder.encode(fileName, StandardCharsets.UTF_8));
//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);
}
//8 關閉流
in.close();
out.close();
驗證碼
前端實現驗證碼: js
後端實現: 需要用到java的圖片類
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//瀏覽器5秒重新整理
resp.setHeader("refresh", "3");
//在記憶體中建立一個圖片
BufferedImage image = new BufferedImage(80, 100, BufferedImage.TYPE_INT_RGB);
//得到圖片
Graphics2D g = (Graphics2D)image.getGraphics();
//設定圖片的背景顏色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//給圖片寫資料
g.setColor(Color.blue);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告訴瀏覽器這個響應用圖片的形式開啟
resp.setContentType("image/png");
//網站有快取, 不讓瀏覽器快取
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "nocache");
//把圖片寫給瀏覽器
boolean write = ImageIO.write(image, "png", 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;
}
//生成隨機數
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999) + "";
num = "0".repeat(Math.max(0, 7 - num.length())) +num;
return num;
}
重定向
B一個web資源收到客戶端A請求後,B他會通知A客戶端去訪問另外一個web資源C,這個過程叫重定向
常見場景 :
- 使用者登入
/*
resp.setHeader("Location" , "/r/img");
resp.setstatus(302);
*/
resp.sendRedirect("/r/img");//重定向時候一定要注意路徑問題,否則404;
重定向和轉發的區別
相同點 : 頁面都會跳轉
不同點 : 轉發的時候URL不會變化; 重定向時URL會變化;
7 cookie和session
有狀態會話:一個同學來過教室,下次再來教室,我們會知道這個同學,曾經來過,稱之為有狀態會話;你能怎麼證明你是西開的學生?
1.發票
西開給你發票
2.學校登記
西開標記你來過了
一個網站,怎麼證明你來過?
客戶端
服務端
1.服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
2.伺服器登記你來過了,下次你來的時候我來匹配你; seesion
儲存會話的兩種技術
cookie
- 客戶端技術(響應, 請求)
session
- 伺服器技術,利用這個技術,可以儲存使用者的會話資訊?我們可以把資訊或者資料放在Session中!
常見:網站登入之後,你下次不用再登入了,第二次訪問直接就上去了!
cookie
1.從請求中拿到cookie資訊
2.伺服器響應給客戶端cookie
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//伺服器,告訴你,你來的時間,把這個時間封裝成為一個信件,你下帶來,我就知道你來了
//解決中文亂碼
req.setCharacterEncoding("utf-8");
resp.setHeader("Content-type", "text/html;charset=UTF-8");
resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();//返回陣列,cookie可能存在多個
//判斷cookie是否存在
if (null != cookies){
out.write("您上一次訪問的時間: ");
for (Cookie cookie : cookies) {
if (cookie.getName().equals("lastLoginTime")){
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toString());
}
}
}else {
out.write("這是您第一次訪問本站! ");
}
//服務給客戶端響應一個cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
//設定cookie有效期為一天, 預設為一次會話
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
cookie:一般會儲存在本地的使用者目錄下appdata;
一個網站cookie是否存在上限: (聊聊細節問題)
- 一個Cookie只能儲存一個資訊;
- 一個web站點可以給瀏覽器傳送多個cookie,最多存放20個cookie;
- Cookie大小有限制4kb;
- 300個cookie瀏覽器上限
刪除Cookie;
- 不設定有效期,關閉瀏覽器,自動失效;
- 設定有效期時間為0 ;
編碼解碼
URLEncoder.encode("卡爾", "utf-8")
URLDecoder. decode(cookie.getvalue(, "utf-8")
session
什麼是Session:
- 伺服器會給每一個使用者(瀏覽器)建立一個Seesion物件;
- 一個Seesion獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就存在;
- 使用者登入之後,整個網站它都可以訪問! -->儲存使用者的資訊;儲存購物車的資訊....
session: 會話:
使用者開啟一個瀏覽器,點選了很多超連結,訪問多個web資源,關閉瀏覽器,這個過程可以稱之為會話 ;
session 存入鍵值對
//解決亂碼問題
req.setCharacterEncoding( "UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType( "text/html;charset=utf-8");
//得到Session
Httpsession session = req.getSession();
//給Session中存東西
session.setAttribute( name: "name" , value: "秦疆");
//獲取Session 的ID
string sessionId = session.getId();
//判斷session是不是新建立
if (session.isNew()){
resp.getwriter().write( s: "session建立成功,ID: "+sessionId);
}else {
resp.getwriter().write( s: "session以及在伺服器中存在了,ID: "+sessionId);
}
session 存入物件
person類
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;
}
}
將person物件存入session
//得到Session
Httpsession session = req.getsession();
//給Session中存東西
session.setAttribute( name: "name" ,new Person( name:"秦疆" , age: 1));
取出person物件
//解決亂碼問題
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setcontentType( "text/htm1;charset=utf-8");
//得到Session
Httpsession session = req.getsession( );
Person person = (Person) session.getAttribute( name: "name" );
system.out.println(person.toString());
移除session物件和登出session
Httpsession session = req.getSession();
session.removeAttribute(name: "name");//移除session物件
session.invalidate(); //手動登出session
web.xml
<!--設定session預設的失效時間-->
<session-config>
<!--15分鐘後session自動失效,以分鐘為單位-->
<session-timeout>15</session-timeout>
</session-config>
使用場景:
- 儲存一個登入使用者的資訊;·購物車資訊;
- 在整個網站中經常會使用的資料,我們將它儲存在Session中;
Session和cookie的區別:
- Cookie是把使用者的資料寫給使用者的瀏覽器,瀏覽器儲存(可以儲存多個)
- Session把使用者的資料寫到使用者獨佔Session中,伺服器端儲存(儲存重要的資訊,減少伺服器資源的浪費).
- Session物件由伺服器建立;
8 JSP
什麼是Jsp?
java servlet pages : Java伺服器端頁面,也和Servlet—樣,用於動態Web技術!
最大的特點:
- 寫JSP就像在寫HTML
區別:
- HTML只給使用者提供靜態的資料
- JSP頁面中可以嵌入JAVA程式碼,為使用者提供動態資料;
Jsp原理
思路:JSP到底怎麼執行的!
-
程式碼層面沒有任何問題
-
伺服器內部工作
- tomcat中有一個work目錄;
- IDEA中使用Tomcat的會在IDEA的tomcat中生產一個work目
地址:c: \users \Administrator\.Inte1liJIdea2018.1\system\tomcat\Unnamed_javaweb-session-cookie\work \catalina\ loca1host\RooT\org\apache jsp
發現頁面轉變成了java程式
瀏覽器向伺服器傳送請求,不管訪問什麼資源,其實都是在訪問Servlet!
JSP最終也會被轉換成為一個Java類!
JSP本質上就是一個Servlet
//初始化
public void _jspinit() {
}
//銷燬
public void _jspDestroy() {
}
/ / JSPservice
public void _jspservice(.HttpservletRequest request,HttpservletResponse resp){
}
1.判斷請求
2.內建一些物件
final javax.servlet.jsp. Pagecontext pagecontext; //頁面上下文
javax.servlet.http.Httpsession session = nu71; //session
final javax.serv1et.servletcontext application; //app1ication contextfinal
javax.servlet.serv1etconfig config; // config
javax.servlet.jsp . 3spwriter out = nu17; // out
fina7 java.1ang. object page = this; //page:當前
HttpservletRequest request //請求
HttpservletResponse response //響應
3.輸出頁面前增加的程式碼
response. setcontentType( "text/html"); //設定響應的頁面型別
pagecontext = _jspxFactory.getPagecontext(this, request, response, nu71, true, 8192, true);
_jspx_page_context = pagecontext;
application = pagecontext. getservletcontext();
config = pagecontext.getservletconfig();
session = pagecontext.getsession();
out = pagecontext.getout();
_jspx_out = out;
4.以上的這些個物件我們可以在JSP頁面中直接使用!
在JSP頁面中;
只要是JAVA程式碼就會原封不動的輸出;
如果是HTML程式碼,就會被轉換為: out.write( "<html> \r\n ");
這樣的格式輸出到前端;
JSP基礎語法和指令
maven的依賴
pom.xml
-------
<dependencies>
<!--Servlet依賴-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--JSP依賴-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!--JSTL表示式的依賴-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jst1-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard -->
<dependency>
<groupid>taglibs</groupId>
<artifactId>standard</artifactId><version>1.1.2</version>
</dependency>
</dependencies>
JSP基礎語法
任何語言都有自己的語法,JAVA中有,JSP作為java技術的一種應用,支援Java所有語法,它還擁有一些自己擴充的語法 !(瞭解,知道即可! )
<%--
--JSP表示式
--作用:用來將程式的輸出,輸出到客戶端<%=變數或者表示式%>
--%>
<%= new java.util.Date();%>
<%--jsp指令碼片段--%>
<%
int sum = ;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println( "<h1>Sum="+sum+"</h1>");
%>
<%--在程式碼嵌入HTML元素--%>
<% for ( int i = 0; i < 5; i++){ %>
<h1>Hello,world<%=i %></h1>
<% } %>
jsp宣告 : 會被編譯到JSP生成Java的類中! 其他的,就會被生成到_jspService方法中!
在JSP,嵌入Java程式碼即可!
<% %>
<%= %>
<%! %>
<%--註釋--%>
JSP的註釋,不會在客戶端顯示,HTML就會!
JSP指令
<%apage args. . .. %>
<%@include file=""%>
<%--@include會將兩個頁面合二為一—-%>
<%@include file="common/header.jsp "%>
<h1>網頁主體</h1>
<%ainclude file="common/footer.jsp"%>
<%--jsP標籤
--jsp:include:拼接頁面,本質還是三個
--%>
<jsp:include page="/common/header.jsp" />
<h1>網頁主體</h1>
<jsp:include page="/common/footer.jsp" />
內建物件及作用域
9大內建物件
- PageContext 存內容
- Request 存內容
- Response
- Session 存內容
- Application 【SerlvetContext】存內容
- config【SerlvetConfig】
- out
- page
- exception
儲存內容的內建物件
<%--儲存內容的內建物件--%>
<%
pageContext.setAttribute("name1", "秦疆1號"); //儲存的資料只在一個頁面中有效
request.setAttribute("name2" ,"秦疆2號"); //儲存的資料只在一次請求中有效,請求轉發會攜帶這個資料
session.setAttribute("name3" , "秦疆3號"); //儲存的資料只在一次會話中有效,從開啟瀏覽器到關閉瀏覽版多結經
application.setAttribute("name4" , "秦疆4號"); //儲存的資料只在伺服器中有效,從開啟伺服器到關團
%>
<%--指令碼片段中的程式碼,會被原封不動生成到xxx_JSP.java: 要求 : 這裡面的程式碼必須保證Java語法正確--%>
<%
//從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>
request: 客戶端向伺服器傳送請求,產生的資料,使用者看完就沒用了,比如:新聞,使用者看完沒用的!
session: 客戶端向伺服器傳送請求,產生的資料,使用者用完一會還有用,比如:購物車;
application: 客戶端向伺服器傳送請求,產生的資料,一個使用者用完了,其他使用者還可能使用,比如:聊夫資料;
JSP標籤, JSTL標籤, EL表示式
pom.xml
-------
<!-- STL表示式的依賴-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jst1-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--%>
<%-- http://LocaLhost:8080/jsptag.jsp?name=kuangshen&age=12 --%>
<jsp: forward page="/jsptag2.jsp">
<jsp: param name="name" value="kuangshen"></jsp:param><jsp:param name="age" value="12"></jsp:param>
</jsp:forward>
JSTL標籤
JSTL標籤庫的使用就是為了彌補HTML標籤的不足;它自定義許多標籤,可以供我們使用,標籤的功能和Java程式碼一樣!
JSTL標籤庫使用步驟:
- 引入對應的taglib
- 使用其中的方法
- 在Tomcat也需要引入jstl的包,否則會報錯:JSTL解析錯誤
<%--引入JSTL核心標籤庫,我們才能使用JSTL標籤-%>
<%taglib prefix="c" uri="http://java.sun.com/jsp/jst1/core"%>
<form action="coreif.jsp" method="get">
<%-- EL表示式獲取表單中的資料${param.引數名} --%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登入">
</form>
<%--判斷如果提交的使用者名稱是管理員,則登入成功--%>
<c :if test="${param.username== 'admin'}" var="isAdmin">
<c :out value="管理員歡迎您!"/>
</c:if>
<%--自閉合標籤--%>
<c :out value="${isAdmin}" />
<%--定義一個變數score,值為85--%>
<c:set var="score" value="55"/>
<c:choose>
<c :when test="${score>=90}">
你的成績為優秀
</c :when>
<c : when test="${score>=80}">
你的成績為一般
</c:when>
<c :when test="${score>=70}">
你的成績為良好
</c :when>
<c :when test="${score<=60}">
你的成績為不及格
</c :when>
</c:choose>
<%
ArrayList<String> people = new ArrayList>;
people.add(O, "張三");
people.add(1, "李四");
people.add(2 , "王五");
people.add(3 , "趙六");
people.add(4, "田七");
request.setAttribute("list" , people);
%>
<%--
--var ,每一次遍歷出來的變數
--items,要遍歷的物件
--begin,哪裡開始
--end,到哪裡
--step,步長
--%>
<c:forEach var="people" items="${7ist}">
<c:out Value="${people}"/> br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1" >
<c:out value="${people}"/><br>
</c:forEach>
9 javaBean
實體類
JavaBean有特定的寫法:
- 必須要有一個無參構造屬性必須私有化
- 必須有對應的get/set方法;
- 一般用來和資料庫的欄位做對映ORM;
ORM:物件關係對映
<%
//People peopLe = new People();peoplLe.setAddress( );
//people.setId();
//people.setAge();
//peopLe.setName();
%>
<jsp:useBean id="people" class="com.kuang.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="3"/>
<jsp:setProperty name="people" property="name" value="小小"/>
<%--<%=people.getAddress( )%>--%>
姓名: <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" />
10 MVC三層架構
什麼是MVC: Model view Controller模型、檢視、控制器
10.1 早些年
使用者直接訪問控制層,控制層就可以直接操作資料庫;
servlet--CRUD-->資料庫弊端:程式十分臃腫,不利於維護
servlet的程式碼中:處理請求、響應、檢視跳轉、處理JDBC、處理業務程式碼、處理邏輯程式碼
架構:沒有什麼是加一層解決不了的!
程式猿呼叫
JDBC
Mysql oracle sqlserver ....
10.2 MVC三層架構
Model
-
業務處理:業務邏輯(Service)·資料持久層:CRUD(Dao)View
-
展示資料提供連結發起Servlet請求(a,form, img...)
controller (Servlet)
-
接收使用者的請求: (req:請求引數、Session資訊....)
-
交給業務層處理對應的程式碼
-
控制檢視的跳轉
登入--->接收使用者的登入請求--->處理使用者的請求(獲取使用者登入的引數,username,password)---->交給業務層處理登入業務(判斷使用者名稱密碼是否正確:事務)--->Dao層查詢使用者名稱和密碼是否正確-->資料庫
11 過濾器(Filter)
什麼是過濾器(Filter)
Filter:過濾器,用來過濾網站的資料;
- 處理中文亂碼
- 登入驗證....
Filter開發步驟:
-
導包
<dependencies> <!-- servlet依賴--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <!-- JSP依賴--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> </dependency> <!-- 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> <!-- 連線資料庫--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> </dependencies>
-
編寫過濾器
-
注意: 導包
import javax.servlet.*;
-
實現Filter介面, 重寫對應的方法
package com.karl.filter; import javax.servlet.*; import java.io.IOException; 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;charset=utf-8"); System.out.println("doFilter! 1"); chain.doFilter(request,response);//讓請求繼續走,如果不寫,程式到這裡就被攔截停止! System.out.println("doFilter! 2"); } //銷燬: web伺服器關閉的時候,過濾會銷燬 public void destroy() { System.out.println("CharacterEncodingFilter銷燬"); } }
-
在
web.xml
中配置filter
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.karl.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
-
12 監聽器
實現一個監聽器的介面
-
編寫一個監聽器
package com.karl.listener; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; //統計網站線上人數: 統計session public class OnlineCountListener implements HttpSessionListener { @Override //建立session監聽:看你的一舉一動 //一旦建立Session就會觸發一次這個事件! public void sessionCreated(HttpSessionEvent httpSessionEvent) { ServletContext servletContext = httpSessionEvent.getSession().getServletContext(); Integer onlineCount = (Integer)servletContext.getAttribute("OnlineCount"); if (null == onlineCount){ onlineCount = 1; }else { int count = onlineCount; onlineCount = count + 1; } servletContext.setAttribute("OnlineCount", onlineCount); } @Override //銷燬session監聽 //一旦銷燬Session就會觸發一次這個事件! public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { } }
-
web.xml中配置監聽器
<listener> <listener-class>com.karl.listener.OnlineCountListener</listener-class> </listener>
-
看情況使用
13 過濾器的常見使用
登入: 使用者登入之後才能進入主頁!使用者登出後就不能進入主頁了!
-
使用者登入之後,向Sesison中放入使用者的資料
package com.karl.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; 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 { //獲取前端請求的引數 String username = req.getParameter("username"); if (username.equals("admin")){//登入成功 req.getSession().setAttribute("USER_SESSION",req.getSession().getId()); resp.sendRedirect(req.getContextPath()+"/sys/success.jsp"); }else { resp.sendRedirect(req.getContextPath()+"/error.jsp"); } } }
-
進入主頁的時候要判斷使用者是否已經登入; 要求:在過濾器中實現!
package com.karl.filter; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class SysFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest servletReq = (HttpServletRequest)servletRequest; HttpServletResponse servletResp = (HttpServletResponse) servletResponse; if(null == servletReq.getSession().getAttribute("USER_SESSION")){ servletResp.sendRedirect(servletReq.getContextPath()+"/error.jsp"); } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
-
登出
package com.karl.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; public class LogoutServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Object user_session = req.getSession().getAttribute("USER_SESSION"); if (null != user_session){ req.getSession().removeAttribute("USER_SESSION"); resp.sendRedirect(req.getContextPath()+"/index.jsp"); }else { resp.sendRedirect(req.getContextPath()+"/index.jsp"); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
14 JDBC
什麼是JDBC : Java連線資料庫!
需要jar包的支援:
- java.sql
- javax.sql
- mysql-conneter-java.... 連線驅動((必須要匯入)
匯入資料庫依賴
<! --mysq1的驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysq1-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
CREATE TABLE users(
id lNT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id, `name`, `password` ,email, birthday)
VALUES(1,'張三','123456','[email protected]', '2000-01-01');
INSERT INTO users(id, `name`, `password` ,email, birthday)
VALUES(2,'李四';'123456', '[email protected]'; '2000-01-01');
NSERT INTO users(id, `name`, `password`, email, birthday)
VALUES(3,'王五','123456','[email protected]' ; '2000-01-01'");
package com.karl.test;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException,sQLException {
//配置資訊
//useUnicode=true&characterEncoding=utf-8解決中文亂碼
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
//1.載入驅動
Class.forName("com.mysql.jdbc.Driver" );
//2.連線資料庫,代表資料庫
Connection connection = DriverManager.getConnection(url,username,password);
//3.向資料庫傳送SQL的物件Statement : CRUD
Statement statement = connection.createstatement();
//4.編寫SQL
string sql = "select * from users";
//5.執行查詢SQL,返回一個Resultset :結果集
Resultset 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"));
}
//6.關閉連線,釋放資源(一定要做)先開後關
rs.close();
statement.close();
connection.close();
IDEA中連線資料庫
JDBC固定步驟:
- 載入驅動
- 連線資料庫,代表資料庫
- 向資料庫傳送SQL的物件Statement : CRUD
- 編寫SQL(根據業務,不同的SQL)
- 執行SQL
- 關閉連線
預編譯
//1.載入驅動
class.forName( "com.mysq1.jdbc.Driver" ) ;
//2.連線資料庫,代表資料庫
Connection connection = DriverManager.getConnection(url,username,password);
//3.編寫SQL
string sql = "insert into users(id,name,password,email, birthday) values (?,?,?,?,?);";
//4.預編譯
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt( parameterIndex: 1, x: 4);//給第一個佔位符?的值賦值為1;
preparedStatement.setString( parameterlndex: 2,x:"狂神說Java");//給第二個佔位符?的值賦值為狂神說Java;
preparedStatement.setString( parameterlndex: 3, x:"123456");//給第三個佔位符?的值賦值為123456;
preparedStatement . setString( parameterlndex: 4, x:"[email protected]");//給第四個佔位符?的值賦值;
preparedStatement.setDate( parameterlndex: 5,new Date(new java.util.Date().getTime()));
//5.執行SQL
int i = preparedstatement.executeUpdate();
if (i>0){
system.out.print1n("插入成功@");
}
//6.關閉連線,釋放資源(一定要做)先開後關
preparedStatement.close();
connection.close();
遇到的問題
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
SMBMS系統
資料庫
專案如何搭建?
專案搭建準備工作
-
搭建一個maven web專案
-
配置Tomcat
-
測試專案是否能夠跑起來
-
匯入專案中會遇到的jar包;
jsp,Servlet,mysql驅動,jstl,stand...5.
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2.1-b03</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> </dependencies>
-
建立專案包結構
-
編寫實體類;
ORM對映:表-類對映 -
編寫基礎公共類
-
資料庫配置檔案
driver = com.mysql.jdbc.Driver url = jdbc:mysql://localhost:3306?useUnicode=true&charEncoding=utf-8 username = root password = root
-
資料庫公共類
package com.karl.dao; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; //操作資料庫的公共類 public class BaseDao { public static String driver; public static String url; public static String username; public static String password; //靜態程式碼塊,類載入的時候就初始化了 { Properties properties = new Properties(); //通過類載入器讀取對應的資源 InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties"); try { properties.load(is); } catch (IOException e) { e.printStackTrace(); } driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); } //獲取資料庫的連線 public static Connection getConnection(){ Connection connection = null; try { Class.forName(driver); connection = DriverManager.getConnection(url, username,password); } catch (Exception e) { e.printStackTrace(); } return connection; } //查詢公共方法 public static ResultSet execute(Connection connection, String sql, Object[] params, ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException { //碩編譯的saL.在後面直接執行就可以了 preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < params.length; i++) { //setObject,佔位符從1開始,但是我們的陣列是從e開始! preparedStatement.setObject(i+1, params); } resultSet = preparedStatement.executeQuery(); return resultSet; } //增刪改公共方法 public static int execute(Connection connection, String sql, Object[] params, PreparedStatement preparedStatement) throws SQLException { preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < params.length; i++) { //setObject,佔位符從1開始,但是我們的陣列是從e開始! preparedStatement.setObject(i+1, params); } int updateRows = preparedStatement.executeUpdate(); return updateRows; } //釋放資源 public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){ boolean flag = true; if (null != resultSet){ try { resultSet.close(); //GC回收 resultSet = null; } catch (SQLException throwable) { throwable.printStackTrace(); flag = false; } } if (null != connection){ try { connection.close(); //GC回收 connection = null; } catch (SQLException throwable) { throwable.printStackTrace(); flag = false; } } if (null != preparedStatement){ try { preparedStatement.close(); //GC回收 preparedStatement = null; } catch (SQLException throwable) { throwable.printStackTrace(); flag = false; } } return flag; } }
-
字元編碼過濾器
package com.karl.filter; import javax.servlet.*; import java.io.IOException; public class CharacterEncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); chain.doFilter(request,response); } @Override public void destroy() { } }
web.xml
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.karl.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
-
匯入靜態資原始檔
登入功能實現
-
編寫前端頁面
-
設定首頁
<!--歡迎頁面--> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list>
-
編寫Dao層登入使用者登入的介面
package com.karl.dao.user; import com.karl.pojo.User; import java.sql.Connection; import java.sql.SQLException; public interface UserDao { //得到要登入的使用者 public User getLoginUser(Connection connection, String userCode) throws SQLException; }
-
編寫Dao介面的實現類
package com.karl.dao.user; import com.karl.dao.BaseDao; import com.karl.pojo.User; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class UserDaoImpl implements UserDao { @Override public User getLoginUser(Connection connection, String userCode) throws SQLException { PreparedStatement preparedStatement = null; ResultSet resultSet = null; User user = null; if (null != connection){ String sql = "select * from smbms_user where userCode=?"; Object[] params = {userCode}; resultSet = BaseDao.execute(connection,preparedStatement,resultSet,sql,params); if (resultSet.next()){ user = new User(); user.setId(resultSet.getInt("id")); user.setUserCode(resultSet.getString("userCode")); user.setUserName(resultSet.getString( "userName")); user.setUserPassword(resultSet.getString("userPassword" )); user.setGender(resultSet.getInt("gender" )); user.setBirthday(resultSet.getDate("birthday" )); user.setPhone(resultSet.getString("phone" )); user.setAddress(resultSet.getString("address")); user.setUserRole(resultSet.getInt("userRole")); user.setCreatedBy(resultSet.getInt("createdBy" )); user.setCreationDate(resultSet.getTimestamp("creationDate")); user. setModifyBy(resultSet.getInt("modifyBy" )); user.setModifyDate(resultSet.getTimestamp("modifyDate")); } BaseDao.closeResource(null, preparedStatement,resultSet); } return user; } }
-
業務層介面
public User login (String userCode, String password);
-
業務層實現類
public class UserServiceImpl implements UserService{ //業務層都會呼叫dao層,所以我們要引入Dao層; private UserDao userDao; public UserServiceImpl() { userDao = new UserDaoImpl(); } @Override public User login(String userCode, String password) { Connection connection = null; User user = null; try { connection = BaseDao.getConnection(); //通過業務層呼叫對應的具體資料庫操作 user = userDao.getLoginUser(connection, userCode); } catch (SQLException throwable) { throwable.printStackTrace(); }finally { BaseDao.closeResource(connection,null,null); } return user; }
-
登入servlet
package com.karl.servlet.user; import com.karl.pojo.User; import com.karl.service.user.UserService; import com.karl.service.user.UserServiceImpl; import com.karl.util.Constants; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LoginServlet extends HttpServlet { //servlet: 控制層業務層 service @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("LoginServlet start..."); String userCode = req.getParameter("userCode"); String userPassword = req.getParameter("userPassword"); //和資料庫中的密碼對比, 呼叫業務層 UserService userService = new UserServiceImpl(); User user = userService.login(userCode, userPassword);//查出登入的人了 if (null != user && userPassword.equals(user.getUserPassword())){//有此人且密碼正確, 可以登入 //將資訊放入session中 req.getSession().setAttribute(Constants.USER_SESSION, user); resp.sendRedirect(req.getContextPath() + "/jsp/frame.jsp");//重定向 }else{//使用者名稱或者密碼錯誤, 不可登入 //轉發回登入頁面,順帶提示它,使用者名稱或者密碼錯誤; req.setAttribute("error", "使用者名稱或密碼不正確"); req.getRequestDispatcher("/login.jsp").forward(req,resp);//轉發 } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
登入servlet的web.xml配置
<!--登入servlet--> <servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.karl.servlet.user.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login.do</url-pattern> </servlet-mapping>
-
登出servlet和servlet配置
package com.karl.servlet.user; import com.karl.util.Constants; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LogoutServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //移除使用者的Constants. USER_SESSION req.getSession().removeAttribute(Constants.USER_SESSION); //返回登入頁面 resp.sendRedirect(req.getContextPath()+"/login.jsp");//重定向 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<!-- 登出servlet--> <servlet> <servlet-name>LogoutServlet</servlet-name> <servlet-class>com.karl.servlet.user.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogoutServlet</servlet-name> <url-pattern>/jsp/logout.do</url-pattern> </servlet-mapping>
-
未登入過濾
package com.karl.filter; import com.karl.pojo.User; import com.karl.util.Constants; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.http.HttpRequest; public class SysFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; User user = (User)req.getSession().getAttribute(Constants.USER_SESSION);//過濾器,從session中獲取使用者, if (null == user){ resp.sendRedirect(req.getContextPath()+"/error.jsp"); } else{ chain.doFilter(request, response); } } @Override public void destroy() { } }
web.xml
<!-- 未登陸過濾--> <filter> <filter-name>SysFilter</filter-name> <filter-class>com.karl.filter.SysFilter</filter-class> </filter> <filter-mapping> <filter-name>SysFilter</filter-name> <url-pattern>/jsp/*</url-pattern> </filter-mapping>
修改密碼
-
匯入前端素材
<li><a href="${pagecontext.request.contextPath }/jsp/pwdmodify.jsp">密碼修改</a></1i>
-
寫專案,建議從底層向上寫
-
UserDao介面
//修改當前使用者密碼 int updatePwd(Connection connection, String id, String password) throws SQLException;
-
UserDao介面實現類
//修改當前使用者密碼 @Override public int updatePwd(Connection connection, String id, String password) throws SQLException { String sql = "update smbms_user set userPassword = ? where id = ?"; Object[] params = {password, id}; return BaseDao.executeU(connection, sql, params); }
-
UserService介面
//修改密碼業務 public int updatePwd(String id, String pwd);
-
UserService實現類
//修改密碼業務 @Override public boolean updatePwd(String id, String pwd) throws SQLException { boolean flag = false; Connection connection = null; connection = BaseDao.getConnection(); if (userDao.updatePwd(connection, id, pwd)>0){ flag = true; } BaseDao.closeResource(connection,null,null); return flag; }
-
servlet配置
<!-- 使用者操作--> <servlet> <servlet-name>UserServlet</servlet-name> <servlet-class>com.karl.servlet.user.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/jsp/user.do</url-pattern> </servlet-mapping>
-
servlet
-
實現複用需要提取方法
修改密碼的js(Ajax)
var oldpassword = null;
var newpassword = null;
var rnewpassword = null;
var saveBtn = null;
$(function(){
oldpassword = $("#oldpassword");
newpassword = $("#newpassword");
rnewpassword = $("#rnewpassword");
saveBtn = $("#save");
oldpassword.next().html("*");
newpassword.next().html("*");
rnewpassword.next().html("*");
oldpassword.on("blur",function(){
$.ajax({
type:"GET",
url:path+"/jsp/user.do",
data:{method:"pwdmodify",oldpassword:oldpassword.val()},
dataType:"json",
success:function(data){
if(data.result === "true"){//舊密碼正確
validateTip(oldpassword.next(),{"color":"green"},imgYes,true);
}else if(data.result === "false"){//舊密碼輸入不正確
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 原密碼輸入不正確",false);
}else if(data.result === "sessionerror"){//當前使用者session過期,請重新登入
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 當前使用者session過期,請重新登入",false);
}else if(data.result === "error"){//舊密碼輸入為空
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 請輸入舊密碼",false);
}
},
error:function(data){
//請求出錯
validateTip(oldpassword.next(),{"color":"red"},imgNo + " 請求錯誤",false);
}
});
}).on("focus",function(){
validateTip(oldpassword.next(),{"color":"#666666"},"* 請輸入原密碼",false);
});
newpassword.on("focus",function(){
validateTip(newpassword.next(),{"color":"#666666"},"* 密碼長度必須是大於6小於20",false);
}).on("blur",function(){
if(newpassword.val() != null && newpassword.val().length > 5
&& newpassword.val().length < 20 ){
validateTip(newpassword.next(),{"color":"green"},imgYes,true);
}else{
validateTip(newpassword.next(),{"color":"red"},imgNo + " 密碼輸入不符合規範,請重新輸入",false);
}
});
rnewpassword.on("focus",function(){
validateTip(rnewpassword.next(),{"color":"#666666"},"* 請輸入與上面一致的密碼",false);
}).on("blur",function(){
if(rnewpassword.val() != null && rnewpassword.val().length > 5
&& rnewpassword.val().length < 20 && newpassword.val() === rnewpassword.val()){
validateTip(rnewpassword.next(),{"color":"green"},imgYes,true);
}else{
validateTip(rnewpassword.next(),{"color":"red"},imgNo + " 兩次密碼輸入不一致,請重新輸入",false);
}
});
saveBtn.on("click",function(){
oldpassword.blur();
newpassword.blur();
rnewpassword.blur();
if(oldpassword.attr("validateStatus") === "true"
&& newpassword.attr("validateStatus") === "true"
&& rnewpassword.attr("validateStatus") === "true"){
if(confirm("確定要修改密碼?")){
$("#userForm").submit();
}
}
});
});
//js(Ajax)驗證
private void pwdmodifyServlet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String oldpassword = req.getParameter("oldpassword");
//從session裡面拿密碼
User user = (User) req.getSession().getAttribute(Constants.USER_SESSION);
//用map傳遞引數 結果集
HashMap<String, String> resultHashMap = new HashMap<>();
if (null == user){ //session過期
resultHashMap.put("result", "sessionerror");
}else if (oldpassword.isEmpty()){ //得到的密碼為空
resultHashMap.put("result", "error");
}else { //密碼不為空
if (oldpassword.equals(user.getUserPassword())){ //密碼正確
resultHashMap.put("result", "true");
}else { //密碼錯誤
resultHashMap.put("result", "false");
}
}
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
writer.write(JSONArray.toJSONString(resultHashMap));
writer.flush();
writer.close();
}
使用者管理實現
-
匯入分頁的工具類
package com.karl.util; public class PageSupport { //當前頁碼-來自於使用者輸入 private int currentPageNo = 1; //總數量(表) private int totalCount = 0; //頁面容量 private int pageSize = 0; //總頁數-totalCount/pageSize(+1) private int totalPageCount = 1; public int getCurrentPageNo() { return currentPageNo; } public void setCurrentPageNo(int currentPageNo) { if(currentPageNo > 0){ this.currentPageNo = currentPageNo; } } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { if(totalCount > 0){ this.totalCount = totalCount; //設定總頁數 this.setTotalPageCountByRs(); } } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { if(pageSize > 0){ this.pageSize = pageSize; } } public int getTotalPageCount() { return totalPageCount; } public void setTotalPageCount(int totalPageCount) { this.totalPageCount = totalPageCount; } public void setTotalPageCountByRs(){ if(this.totalCount % this.pageSize == 0){ this.totalPageCount = this.totalCount / this.pageSize; }else if(this.totalCount % this.pageSize > 0){ this.totalPageCount = this.totalCount / this.pageSize + 1; }else{ this.totalPageCount = 0; } } }
-
匯入使用者列表頁
獲取使用者數量
-
UserDaoImpl
/** * 根據使用者名稱或者角色名得到使用者的總數 * * @param connection 資料庫的連線 * @param username 使用者名稱 * @param userRole 使用者角色 * @return int 數量 */ @Override public int getUserCont(Connection connection, String username, int userRole) throws SQLException { int count = 0;//使用者數量 if (null == connection) { return 0; } StringBuilder sql = new StringBuilder();//新建字串緩衝區用來儲存SQL語句 sql.append("select count(1) as count from smbms_user u, smbms_role r where u.userRole = r.id "); ArrayList<Object> list = new ArrayList<>();//index由0開始 if (!username.isEmpty()){ sql.append("and u.userName like ? "); list.add("%"+username+"%");//sql中使用like模糊查詢時引數需要%%包裹 } if (!username.isEmpty()){ sql.append("and u.userRole = ? "); list.add(userRole); } // 把list轉化為陣列 Object[] objects = list.toArray(); ResultSet resultSet = BaseDao.executeQ(connection, sql.toString(), objects);//查詢, 並捕獲sql異常 if (resultSet.next()){ count = resultSet.getInt("count");//從結果集中的到的數量 } BaseDao.closeResource(connection,null,resultSet); return count; }
-
UserServiceIpml