測試、反射、註解、Mysql、JDBC、Tomcat、servlet、HTTP、EL表示式、JSTL、Filter過濾器、代理模式、監聽器、Redis、Maven
測試
1
黑白盒測試
黑盒測試:不需要寫程式碼,給輸入值,看程式能否給出期望的輸出值
白盒測試:需要寫程式碼,關注程式具體執行流程
2
測試步驟
1)定義測試類
包名:cn.itcast.test
類名:CaculatorTest
2)定義測試方法
方法名:test測試方法名
返回值:void
引數:空
3)使用註解@Test
執行後結果為紅色,執行失敗;綠色,執行成功。
4)斷言
Assert.assertEquals(期望值,結果值)
5)初始化方法和釋放資源方法
@Before//修飾的方法在測試方法之前執行
public void init(){}
@After//修飾的方法在測試方法之後執行,一般用於釋放資源
public void close(){}
反射
將類的各部分封裝為其他類物件,多用於框架(半成品軟體,簡化編碼)的開發。優勢在於,一是可以在程式執行過程中操作這些物件,二是解耦程式,提高程式可擴充套件性
1
獲取class物件的方式
1)class.forName(全類名)
多用於配置檔案
2)類名.class
多用於引數傳遞
3)物件.getClass()
多用於物件
同一位元組碼檔案在異常程式執行過程中,只會被載入一次,不論透過那隻方式獲取的Class物件都是同一個
2
Class物件的功能
1)獲取成員變數
//獲取public修飾的成員變數
public Field[] getFields() throws SecurityException;
public Field getField(String name);
//獲取所有宣告的成員變數
public Field[] getDeclaredFields() throws SecurityException;
public Field getDeclaredField(String name);
2)獲取構造方法
public Constructor<?>[] getConstructors() throws SecurityException;
public Constructor<T> getConstructor(Class<?>... parameterTypes);
public Constructor<?>[] getDeclaredConstructors() throws SecurityException ;
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);
3)獲取成員方法
public Method[] getMethods() throws SecurityException;
public Method getMethod(String name, Class<?>... parameterTypes);
public Method[] getDeclaredMethods() throws SecurityException;
public Method getDeclaredMethod(String name, Class<?>... parameterTypes);
4)獲取類名
public String getName();
5)獲取、改變成員變數的值
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException;
public void set(Object obj, Object value);
6)建立物件
(1)構造方法物件建立有參例項物件
public T newInstance(Object ... initargs);
(2)類物件建立例項無參物件
public T newInstance();
public class Person{
public String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void say(){
System.out.println("我是"+this.name+",今年"+this.age+"歲了");
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class Hello{
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//獲取類物件
Class ps=Person.class;
//獲取類名
System.out.println(ps.getName());
//獲取宣告的成員變數
Field[] fields=ps.getDeclaredFields();
Field name=ps.getDeclaredField("name");
Field age=ps.getDeclaredField("age");
System.out.println(Arrays.toString(fields));
System.out.println(name);
System.out.println(age);
//獲取宣告的構造方法
Constructor[] c=ps.getDeclaredConstructors();
System.out.println(Arrays.toString(c));
Constructor c1=ps.getDeclaredConstructor(String.class,int.class);
System.out.println(c1);
//獲取宣告的成員方法
Method[] mt=ps.getMethods();
System.out.println(Arrays.toString(mt));
Method m1=ps.getMethod("setAge", int.class);
System.out.println(m1);
Method m2=ps.getMethod("say");
System.out.println(m2);
//建立物件
Object person=c1.newInstance("zhang",22);//構造方法物件建立有參物件
System.out.println(person);
Object person1=ps.newInstance();//類物件建立無參物件
System.out.println(person1);
//透過成員變數物件獲取成員變數值
Object name_value=name.get(person);
System.out.println(name_value);
age.setAccessible(true);//忽略訪問許可權修飾符的安全檢測,無此語句會丟擲錯誤
Object age_value=age.get(person);//age是私有屬性
System.out.println(age_value);
//透過成員變數物件設定成員變數值
name.set(person,"zh");
System.out.println(person);
//透過成員方法物件執行物件的成員方法
m2.invoke(person);
}
}
2
手寫框架案例
要求:不改變類的任何程式碼的前提下,建立任意類物件,並執行其中的方法
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class Hello{
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//讀取配置檔案
Properties pro=new Properties();
ClassLoader cl=Hello.class.getClassLoader();
InputStream is=cl.getResourceAsStream("pro.Properties");
pro.load(is);
System.out.println(pro);//{ClassName=aaa.Person, MethodName=say}
//建立類及物件,並執行方法
Class ps = Class.forName(pro.getProperty("ClassName"));
Constructor c = ps.getConstructor(String.class,int.class);
Object person=c.newInstance("zhanghuan",22);
Method m=ps.getMethod(pro.getProperty("MethodName"));
m.invoke(person);//我是zhanghuan,今年22歲了
}
}
註解
JDK1.5後的新特性,對元素進行說明註釋,用於編譯檢查、生成doc文件、程式碼分析
1
自帶註解
@Override
檢測被該註解標註的方法是否是繼承自父類(介面)
@Deprecated
該註解標註的內容,表示已過時
@SuppressWarnings
壓制警告,可傳引數all,如@SuppressWarnings("all")
2
自定義註解
1)格式
元註解
Public @interface MyAnno{
}
2)本質
註解的本質是一個介面,將其編譯後再進行反編譯,發現其是一個繼承自java.lang.annotation.Annotation的介面
3)屬性
指介面中定義的抽象方法,具有返回值
(1)返回值型別
int,String,列舉,註解及以上資料型別的陣列
(2)屬性賦值
使用屬性前需要給屬性賦值,設定default預設值的可不賦值
只有一個屬性需要賦值,且屬性名是value,可省略value並直接賦值
陣列賦值時,需用{}包裹,只有一個值時,{}可省略
4)元註解
對註解進行註釋
(1)@Target
描述註解的作用範圍,引數分別是ElementType.TYPE類,ElementType.METHOD方法,ElementType.FIELD成員變數
(2)@Retention
註解被保留的階段,引數常用RetentionPolicy.RUNTIME
(3)@Documented
註解是否被抽取到api文件中
(4)@Inherited
闡述了某個被標註的型別是被繼承的
3
獲取類的註解
獲取到類的class物件時,呼叫該物件的getAnnotation(註釋名.class)方法
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
public String name();
public int age();
}
@MyAnno(name="zhanghuan",age=22)
public class Hello{
public static void main(String[] args) {
Class<Hello> hello=Hello.class;
MyAnno an= hello.getAnnotation(MyAnno.class);
//此方法相當於建立一個MyAnno的子類實現物件
/*類似於以下的類
class abc implements MyAnno{
String name;
int age;
public abc(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String name() {
return this.name;
}
@Override
public int age() {
return this.age;
}
}
*/
System.out.println(an.name());//zhanghuan
System.out.println(an.age());//zhanghuan
}
}
4
測試案例
//定義註解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}
//定義類,並在需要測試的方法上標註註解
public class Calculator {
@Check
public static int add(int a,int b){
return a+b;
}
@Check
public static int subtract(int a,int b){
return a-b;
}
@Check
public static int multiply(int a,int b){
return a*b;
}
@Check
public static int divide(int a,int b){
return a/b;
}
}
//定義測試類
public class TestCalculator {
public static void main(String[] args) throws ClassNotFoundException, IOException {
Class cal=Class.forName("aaa.Calculator");
Method[] m=cal.getMethods();
BufferedWriter bw=new BufferedWriter(new FileWriter("bug.txt"));
int num=0;
for (Method method:
m) {
if(method.isAnnotationPresent(Check.class)){
try {
Object result = method.invoke(cal.getInterfaces(), 10, 0);
System.out.println(result);
}catch (Exception e){
num++;
bw.write(method.getName()+"()方法出異常了");
bw.newLine();
bw.write(e.toString());
bw.newLine();
bw.write("___________________________________");
bw.newLine();
}
}
}
bw.write("一共測出了"+num+"個異常");
bw.close();
}
}
Mysql
1
資料檔案刪除
在mysql的安裝目錄可找到init檔案,開啟後找到有一行為datadir="c:\ProgrData\MySql\MySqlServer5.5\"
,找到該路徑,刪除裡面的檔案即可
2
常用命令
//開啟服務視窗
Service.msc
//停止服務
net stop mysql
//開啟服務
net start mysql
//登陸伺服器
mysql -h127.0.0.1 -uroot -p
//登陸伺服器方式二
myql --host=ip --user=root --password=abc
//退出mysql
exit
3
SQL結構化查詢語言
操作所有關係型資料庫的規則
1)語法規則
(1)SQL語言可單行、多行書寫,以分號結尾
(2)使用空格和縮排來則鞥去語句的可讀性
(3)mysql的SQL語言不區分大小寫,建議關鍵詞大寫
(4)註釋,--或#為單行註釋,其中#為mysql獨有;/**/為多行註釋
2)分類
(1)DDL(Data Defining langrage)定義語言
定義資料庫物件:資料庫,表,列等,如crete,drop,alter
(2)DML(Data Manipulation langrage)操作語言
對錶中資料進行增、刪、改,如insert,delete,update
(1)DQL(Data Query langrage)查詢語言
查詢表中記錄,如select where
(1)DCL(Data Control langrage)控制語言
定義訪問許可權和安全級別,如GRANT,REVOKE
5
對資料庫的操作
1)建立
//建立一個名為db1的資料庫
create database db1;
//建立一個資料庫db1(如果db1不存在才建立)並設定字符集為gbk
create database if not exists db1 character set gbk;
2)查詢
//檢視所有資料庫
show databases;
//檢視資料庫db1的建立語句
show create database db1;
3)修改
//將資料庫db1的字符集修改為utf8
alter database db1 character set utf8;
4)刪除
//刪除資料庫db1
drop database db1;
//刪除資料庫db1(如果存在才刪除)
drop database if exists db1;
5)使用資料庫
//檢視正在使用的資料庫
select database();
//使用資料庫db1
use db1;
6
對錶的操作
1)建立
//建立一個名為student的表
create table student(
name vachar(20),
age int(2)
);
//複製表student
create table stu like student;
資料型別
資料型別 | 說明 |
---|---|
int | 整數,有符號的整數範圍在正負21億之間。宣告時需要傳入一個引數size,即整數的長度 |
double | 雙精度浮點數。宣告時需要傳入兩個引數,分別指小數點左側數的長度和小數點右側數的長度 |
varchar | 可變長度字串,長度不超過255個字元。宣告時需要傳入字串的長度 |
date | 包含年月日的日期 |
datetime | 包含年月日時分秒的日期 |
timestamp | 包含年月日時分秒的時間戳,插入資料時會自動擷取當前時間存入 |
2)查詢
//查詢所有表
show tables;
//查詢表結構
dest student;
3)修改
(1)修改表名
alter table 表名 rename to 新表名;
(2)修改字符集
alter table 表名 character set 字符集名稱;
(3)新增列
alter table 表名 add 列名 資料型別;
(4)修改列名稱及其資料型別
alter table 表名 modify 列名 新列名 新資料型別;
(5)刪除列
alter table 表名 drop 列名;
4)刪除
//刪除表student
drop table student
//刪除表student(如果存在才刪除)
drop table if exists student
7
對資料操作
1)新增資料
insert into 表名(列名1,列名2) values(值1,值2);
注意
1.列名和值必須一一對應
2.表名後不寫列名,表示給所有列增加值
3.除數字外嗎,其他型別的值都需要用引號包裹
2)刪除資料
delet form 表名 [where條件]
注意
1.如果不加條件,表示刪除表中所有資料
2.如果要刪除表中所有資料,推薦使用
TRUNCATE TABLE 表名
,效率高,其原理是刪除表後再重新建立一張同名表
3)修改資料
update 表名 set 列名1=值1,列名2=值2 [where條件]
注意
如果不加條件,表中所有資料將會被修改
7
查詢表中資料
1)語法
select
欄位1,欄位2……
from
表1,表2……
where
條件列表
goroup by
分組欄位
having
分組之後條件
order by
排序
limit
分頁
2)基礎查詢
(1)去除重複結果
SELECT DISTINCT adress from student;
(2)計算列
SELECT name,math,english,math+IFNULL(english,0) FROM student;
IFNULL(english,0)是指如果english為null,當作0來處理
(3)起別名
//AS來替代欄位名進行顯示,AS可省略
SELECT name AS 姓名,math AS 數學,english AS 英語,math+IFNULL(english,0) AS 總分 FROM student;
(4)條件查詢
除了常規的運算子
<,>,>=,<=,=,!=,<>
還有
//BWTWEEN AND
SELECT name,math,english FROM student where math BETWEEN 70 AND 80;
//AND
SELECT name,math,english FROM student where math>70 AND math<80;
//OR
SELECT name,math,english FROM student where math<70 OR math>80;
//IN
SELECT name,math,english FROM student where math IN (50,52,64);
如果資料內容是null,則不可以用判斷
//找出english是null的資料
SELECT name,math,english FROM student where english IS NULL;
//找出english不是null的資料
SELECT name,math,english FROM student where english IS NOT NULL;
模糊查詢LIKE
SELECT name,math,english FROM student where name LIKE "%傑_";
/*
%是多個字元的佔位符
_是單個字元的佔位符
*/
(5)排序查詢
//將結果math進行預設排序(升序)
SELECT name,math,english FROM student ORDER BY math;
//將結果math進行升序排列
SELECT name,math,english FROM student ORDER BY math ASC;
//將結果math進行降序排列
SELECT name,math,english FROM student ORDER BY math DESC;
注意
1.預設按升序排列
2.有多個排序條件,則前面條件值一樣時,才會使用後面的排序條件
(6)聚合函式
將一列資料作為一個整體,縱向計算。包含COUNT,MAX,MIN,SUM,AVG
//計數
SELECT COUNT(name) FROM student;
//求最大值
SELECT MAX(math) FROM student;
//求最小值
SELECT MIN(math) FROM student;
//求和
SELECT SUM(math) FROM student;
//求平均
SELECT AVG(math) FROM student;
注意
聚合函式計算時會排除掉值為null的資料
(7)分組查詢
一般和聚合函式合用
SELECT AVG(math) FROM student GROUP BY male;
where和having的區別
/*
1.where在執行分組操作前限定,having在執行分組操作後限定
2.where後不可跟聚合函式
3.having子句中可以使用欄位別名,而where不能使用
*/
SELECT SUM(math) AS 數學 FROM `student` GROUP BY male HAVING 數學>150;
(8)分頁
LIMIT 開始索引,每頁條數
公式:開始索引=(當前頁碼-1)*每頁條數
只有mysql的分頁是limit,其他資料庫軟體不一樣
8
約束
對錶中資料進行限定,保證資料的正確性、有效性、完整性。分為:
主鍵約束(primarykey)、非空約束(notnull)、唯一約束(unique)、外來鍵約束(foreignkey)
1)非空約束
//建立表時新增索引
CREATE TABLE stu(
id int NOTNULL,
name varchar(20)
)
//建表後新增索引
ALTER TABLE stu MODIFY name VARCHAR(20) NOTNULL;
//刪除索引
ALTER TABLE stu MODIFY name VARCHAR(20);
2)唯一索引
//新增索引
ALTER TABLE stu MODIFY id INT UNIQUE;
//新增索引方式二
ALTER TABLE stu ADD UNIQUE(id);
//刪除索引
ALTER TABLE stu DROP INDEX id;
唯一索引裡的值可以為多個null
3)主鍵索引
//新增
ALTER TABLE student MODIFY id INT PRIMARY KEY;
//刪除
ALTER TABLE student DROP PRIMARY KEY;
//新增自增
ALTER TABLE student MODIFY id INT AUTO_INCREMENT;
//刪除自增
ALTER TABLE student MODIFY id INT;
非空且唯一
4)外來鍵約束
//建立方式一
CREATE TABLE employee(
dep_id INT,
CONSTRAINT enp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id)
);
//需要注意,department.id必須是主鍵,否則報錯;外來鍵名enp_dep_fk可省略
//建立方式二
ALTER TABLE employee ADD CONSTRAINT enp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id);
//刪除外來鍵
ALTER TABLE employee DROP FOREIGN KEY enp_dep_fk;
//建立帶級聯的外來鍵
ALTER TABLE employee ADD CONSTRAINT enp_dep_fk FOREIGN KEY (dep_id) REFERENCES department(id) ON UPDATE CASCADE ON DELETE CASCADE;
9
資料庫設計的正規化
1)函式依賴
A屬性值可確定唯一B屬性值,則B依賴於A
2)完全依賴
A為屬性組,B屬性值的確定需依賴A屬性組中所有的屬性值
3)部分依賴
A為屬性組,B屬性值的確定需依賴A屬性組中部分的屬性值
4)傳遞依賴
C屬性值依賴於B屬性值,B屬性值依賴於A屬性值,那麼C屬性值傳遞依賴於A屬性值
5)碼
屬性或屬性組被其他屬性完全依賴,那麼這個屬性或屬性組稱為碼
6)主屬性和非主屬性
碼是主屬性,其他的屬性是非主屬性
正規化 | 特點 |
---|---|
第一正規化 | 資料冗餘,存在函式依賴,出現新增異常和刪除異常 |
第二正規化 | 消除非主屬性對主屬性的部分函式依賴,但仍出現新增異常和刪除異常 |
第三正規化 | 所有主屬性不依賴於其他非主屬性,消除傳遞依賴 |
10
備份和還原
1)備份
mysql dump -u使用者名稱 -p密碼 資料庫名稱 >路徑
2)還原
//登陸資料庫、建立資料庫、使用資料庫
//執行命令,其中a.sql是備份的資料庫檔案
source a.spl
9
多表查詢
1)笛卡兒積
兩個集合A、B,取這兩個集合的所有組合情況
2)隱式內聯接
SELECT
t1.time,t1.gender,t1.name
FROM
emp t1,dep t2
WHRER
t1.dept_id=t2.id;
內聯接查詢的是兩張表的交集
3)顯式內聯接
SELECT * FROM exp INNER JOIN dept ON emp.dep_id=dept.id;
4)左外聯接
SELECT 欄位列表 FROM 表1 LEFT JOIN 表2 ON 條件;
查詢的是左表所有的資料交集部分
5)右外聯接
SELECT 欄位列表 FROM 表1 RIGHT JOIN 表2 ON 條件;
查詢的是右表所有的資料交集部分
6)子查詢
(1)子查詢結果單列、單行
SELECT * FROM emp WHERE salary=(SELECT MAX(salary) FROM emp);
(2子查詢結果單列、多行
SELECT * FROM emp WHERE id IN (SELECT id FROM emp WHERE salary>5000);
(3)子查詢結果多列、多行
SELECT
*
FROM
(SELECT * FROM emp WHERE salary>5000) t1,dep t2
WHERE
t1.dept_id=t2.id;
10
事務
一個包含多個步驟的操作,要麼成功,要麼失敗
START TRANSACTION;//開啟事務
……
COMMIT;//提交
1)事務提交的兩種方式
(1)自動提交
mysql預設自動提交,一個增、刪、改操作時,會自動提交一次事務
(2)手動提交
需開啟事務再提交,oracle預設是手動提交
2)修改事務提交的方式
(1)檢視
SELECT @@autocommit;
1為自動提交,0為手動提交
(2)修改
SET @@autocommit=0;
3)事務的四大特徵
原子性:不可分割的最小單位,要麼成功要麼失敗
永續性:提交後會永續性儲存
隔離性:事務之間相互獨立
一致性:資料操作前後總量不變
4)事務隔離級別
(1)事務操作存在的問題
髒讀:一個事務讀取到另一個事務沒有提交的資料
不可重複讀:同一事務,兩次讀到的資料不同
幻讀:一個事務運算元據表中的所有記錄,另一個事務新增一條資料,則第一個事務讀不到自己的修改
(2)隔離級別
隔離級別 | 存在問題 |
---|---|
read uncommitted | 髒讀、不可重複讀、幻讀 |
read committed(oracle預設) | 不可重複讀、幻讀 |
repeatable(mysql預設) | 幻讀 |
serializable | 無 |
級別從小到大,安全性越來越高,效率越來越低
(3)查詢隔離級別
SELECT @@tx_isolation;
(4)設定隔離級別
SET GLOBAL TRANSACTION ISOLATION LEVAL 級別字串;
11
管理使用者
1)檢視使用者
USE mysql;
SELECT host,user,password FROM user;
2)建立使用者
CREATE user '使用者名稱'@'主機名' IDENTIFIED BY '密碼';
3)刪除使用者
DROP user '使用者名稱'@'主機名';
4)修改密碼
UPDATE user SET password=PASSWORD('新密碼') WHERE user='使用者名稱';
5)忘記root密碼
(1)停止mysql,net stop mysql;
(2)使用無驗證方式啟動mysql,mysql --skip -grant-tables
(3)在cmd中輸入mysql,無需輸入賬號密碼進入
(4)改密碼
(5)重啟mysql
6)檢視許可權
SHOW GRANTS FOR '使用者名稱'@'主機名';
7)授予許可權
GRANT 許可權列表 ON 資料庫名,表名 TO '使用者名稱'@'主機名';
//授予全部許可權
GRANT All ON *.* TO 'zhanghuan'@'%';
許可權分別是select,delete,update,all
8)撤銷許可權
REVOKE 許可權列表 ON 資料庫名,表名 FROM '使用者名稱'@'主機名';
JDBC
簡單來說,java語言運算元據庫。官方定義一套操作所有關係型資料庫的規則(介面),由各個資料庫廠商實現這套介面,提供給開發者驅動資料庫的jar包。
1
快速入門
(1)匯入jar包
複製jar包到新建的libs資料夾,add as library
(2)註冊驅動
(3)獲取資料庫連線物件Connection
(4)定義sql
(5)獲取執行sql語句的物件statement
(6)執行sql,接收返回結果
(7)處理結果
(8)釋放資源
2
常用物件
物件 | 名 |
---|---|
DriverMannager | 驅動管理物件 |
Connection | 資料庫連線物件 |
Statement | 執行sql的物件 |
ResultSet | 結果集物件 |
PreparedSteatment | 執行sql的物件 |
3
DriverMannager
(1)註冊驅動
//driver類的成員方法
static void registerDriver(Driver driver);
mysql5之後的驅動可省略註冊
//原始碼摘取自driver
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
//寫入該句則完成註冊
Class.forName("com.mysql.jdbc.Driver");
(2)獲取資料庫連線
static Connection getConnection(String url,String user,String password);
url格式 jdbc:mysql://localhost:3306/db3,連線本機資料庫可省略localhost:3306
4
Connection
(1)獲取執行sql的物件
Statement createStatement();
PreparedStatement PrepareStatement(String sql);
(2)獲取資料庫連線
開啟:setAutoCommit(boolean autoCommit),引數欸false,開啟事務
提交:commit()
回滾:rollback()
5
Statement
(1)boolean execute(String sql)
執行任何sql語句,不常用
(2)int executeUpdate(String sql)
執行DML語句(insert,update,delete)。執行DDL時,返回值為0;返回值為影響的行數,可透過影響的行數判斷是否執行成功,返回值>0執行成功,反之執行失敗。
(3)ResultSet executeQuery(String sql)
執行DQL語句(select)
6
ResultSet結果集物件
//遊標向下移動一行,判斷當前位置是否位於最後一行,如果是返回值false
boolean next();
//獲取資料,可傳入兩種型別的引數,傳入int型別時,該引數代表列號;傳入String型別時,該引數代表列名
int getInt(引數);
String getString(引數);
import java.sql.*;
public class TestCalculator {
public static void main(String[] args) throws ClassNotFoundException {
//註冊
Class.forName("com.mysql.jdbc.Driver");
try (Connection con = DriverManager.getConnection("jdbc:mysql:///test1","root","")) {//連線資料庫
String sql="select * from student";
//獲取執行sql的物件
Statement st=con.createStatement();
//執行sql語句
ResultSet rs=st.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)+" "+rs.getString(4)+" "+rs.getString(5));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
7
PreparedSteatment
在拼接sql時,當有一些sql特殊關鍵字引數與字串拼接時,會造成安全問題,此時使用PreparedSteatment來解決
PreparedStatement Connection.PrepareStatement(String sql);
import java.sql.*;
public class TestCalculator {
public static void main(String[] args) throws ClassNotFoundException {
//註冊
Class.forName("com.mysql.jdbc.Driver");
try (Connection con = DriverManager.getConnection("jdbc:mysql:///test1","root","")) {//連線資料庫
String sql="select * from student where id=?";
//獲取執行sql的物件
PreparedStatement st=con.prepareStatement(sql);
//給問號賦值
st.setString(1,"1");
//執行sql語句
ResultSet rs=st.executeQuery();
while (rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)+" "+rs.getString(4)+" "+rs.getString(5));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
8
JDBCutils
(1)獲取配置檔案路徑
import java.net.URL;
public class JDBCutils {
public static void main(String[] args) {
ClassLoader cl=JDBCutils.class.getClassLoader();
URL res=cl.getResource("jdbc.properties");//jdbc.properties檔案必須在根目錄下才可讀出
String path=res.getPath();
System.out.println(path);// /C:/Users/admin/IdeaProjects/untitled1/out/production/untitled1/jdbc.properties
}
}
(2)完整實現
//配置檔案jdbc.properties
url=jdbc:mysql:///test1
user=root
password=
driver=com.mysql.jdbc.Driver
//JDBCutils
import java.io.FileReader;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JDBCutils {
static String url=null;
static String user=null;
static String password=null;
static String driver=null;
static{
try {
//獲取配置檔案路徑
ClassLoader cl=JDBCutils.class.getClassLoader();
URL res=cl.getResource("jdbc.properties");//jdbc.properties檔案必須在根目錄下才可讀出
String path=res.getPath();
//讀取配置檔案
Properties p=new Properties();
p.load(new FileReader(path));
url=p.getProperty("url");
user=p.getProperty("user");
password=p.getProperty("password");
driver=p.getProperty("driver");
//註冊驅動
Class.forName(driver);
}catch (Exception e){
System.out.println(e);
}
}
public static Connection getConnection(){//獲取連線
Connection con=null;
try {
con = DriverManager.getConnection(url, user, password);
}catch (Exception e){
System.out.println(e);
}
return con;
}
public static void close(ResultSet res, Statement st,Connection conn){//釋放資源
if(res!=null){
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
//使用JDBCutils
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Hello{
public static void main(String[] args) {
Connection con=JDBCutils.getConnection();
PreparedStatement st=null;
ResultSet rs=null;
String sql="select * from student where id=?";
try{
st = con.prepareStatement(sql);
st.setString(1,"2");
rs=st.executeQuery();
while (rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3)+" "+rs.getString(4));
}
}catch (Exception e){
System.out.println(e);
}finally {
JDBCutils.close(rs,st, con);
}
}
}
9
事務
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Hello{
public static void main(String[] args) {
Connection con=JDBCutils.getConnection();
Statement st=null;
ResultSet rs=null;
try{
con.setAutoCommit(false);//開啟事務
st = con.createStatement();
int res1=st.executeUpdate("update employee set salary=salary+500 where id=1");
System.out.println(res1);
int res2=st.executeUpdate("update employee set salary=salary-500 where id=2");
System.out.println(res2);
con.commit();//提交事務
}catch (Exception e){
try {
con.rollback();//回滾事務
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println(e);
}finally {
JDBCutils.close(rs,st, con);
}
}
}
10
資料庫連線池
當初始化後,容器被建立,容器會申請一些連線物件,當使用者訪問資料庫時,從池中取出連線物件進行連線;使用者訪問完後,將連線物件歸還給容器
(1)c3p0
//1.匯入兩個jar包,注意需先匯入mysql驅動包
//2.定義配置檔案,名稱c3p0.properties或c3p0-config.xml,放在src即可
//3.獲取連線物件new ComboPooledDataSource()
//4.獲取連線getConnection
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class Hello{
public static void main(String[] args) {
DataSource ds = new ComboPooledDataSource();//建立資料庫連線池
Connection con=null;
Statement st=null;
ResultSet rs=null;
try{
con=ds.getConnection();//獲取連線
System.out.println(con);
st=con.createStatement();
rs=st.executeQuery("select * from student");
while (rs.next()){
System.out.println(rs.getString(1));
}
}catch (Exception e){
System.out.println(e);
}finally {
JDBCutils.close(rs,st,con);
}
}
}
配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 這是預設配置資訊 -->
<default-config>
<!-- 連線四大引數配置 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test1</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password"></property>
<!-- 池引數配置 -->
<property name="acquireIncrement">3</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">2</property>
<property name="maxPoolSize">10</property>
</default-config>
<!-- 專門為oracle提供的配置資訊 -->
<named-config name="oracle-config">
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="acquireIncrement">3</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">2</property>
<property name="maxPoolSize">10</property>
</named-config>
</c3p0-config>
(2)druid
//1.匯入jar包
//2.定義配置檔案
//3.載入配置檔案
//4.配置檔案手動傳入,並獲取連線物件
//5.獲取連線
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
public class Hello{
public static void main(String[] args) throws IOException {
Properties p=new Properties();
p.load(Hello.class.getClassLoader().getResourceAsStream("druid.properties"));
try {
DataSource ds = DruidDataSourceFactory.createDataSource(p);//建立連線物件
Connection con=ds.getConnection();//獲取連線
Statement st=con.createStatement();
ResultSet rs=st.executeQuery("select * from student");
while (rs.next()){
System.out.println(rs.getString(1));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
封裝工具類
# druid.properties檔案的配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test1
username=root
password=
# 初始化連線數量
initialSize=5
# 最大連線數
maxActive=10
# 最大超時時間
maxWait=3000
//DRUIDutils
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class DRUIDutils {
static Properties p=new Properties();
static{
try {
p.load(DRUIDutils.class.getClassLoader().getResourceAsStream("druid.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){//獲取連線
Connection con=null;
try {
con=getDataSource().getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
public static DataSource getDataSource() throws Exception {//獲取datasource
return DruidDataSourceFactory.createDataSource(p);
}
public static void close(ResultSet res, Statement st, Connection conn){//釋放資源
if(res!=null){
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Statement st, Connection conn){//釋放資源過載方法
if(st!=null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
//測試DRUIDutils
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class Hello{
public static void main(String[] args) throws IOException {
Connection con=null;
Statement st=null;
ResultSet rs=null;
try {
con=DRUIDutils.getConnection();//獲取連線
st=con.createStatement();
rs=st.executeQuery("select * from student");
while (rs.next()){
System.out.println(rs.getString(1));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
DRUIDutils.close(rs,st,con);
}
}
}
(3)SpringJDBC
Spring框架對JDBC的簡單封裝,提供一個JDBCTemplate物件簡化JDBC的程式碼
//1.匯入jar包,共5個
//2.建立JdbcTemplate物件,依賴於資料來源DataSource
JdbcTemplate template=new JdbcTemplate(ds)
//3.呼叫JdbcTemplate的方法進行CRUD操作
import org.springframework.jdbc.core.JdbcTemplate;
public class Hello{
public static void main(String[] args) throws Exception {
JdbcTemplate template=new JdbcTemplate(DRUIDutils.getDataSource());
String sql="update employee set salary=5000 where id=?";
int rs=template.update(sql,1);//執行sql
System.out.println(rs);
}
}
常用CRUD操作
update();//執行DML語句,增刪改語句
queryFormap();//查詢結果封裝乘map集合,結果集長度只可是1
queryForList();//查詢結果封裝成list集合
query();//查詢結果封裝成JavaBean物件
queryForObject();//查詢結果封裝成物件,查詢聚合函式
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Map;
public class Hello{
public static void main(String[] args) throws Exception {
JdbcTemplate template=new JdbcTemplate(DRUIDutils.getDataSource());
String sql=null;
//queryForMap
sql="select * from student where id=1";
Map<String, Object> m=template.queryForMap(sql);
System.out.println(m);
//{id=1, male=男, name=周杰倫, math=78, english=81}
//queryForList
//將每一條記錄封裝成一個map集合,再將map集合封裝到list集合中
sql="select * from student";
List<Map<String,Object>> list_of_map=template.queryForList(sql);
System.out.println(list_of_map);
//query
//將資料封裝成javabean物件並返回一個javabean物件的list集合
sql="select * from student";
List<student> list_of_bean=template.query(sql,new BeanPropertyRowMapper<student>(student.class));
System.out.println(list_of_bean);
//queryForObject
//執行包含聚合函式的sql
sql="select count(*) from student";
Long count=template.queryForObject(sql,Long.class);
System.out.println(count);
}
@Test//可單獨執行方法
public void run(){
System.out.println("hello");
}
}
Tomcat
1
JAVAEE
java語言在企業計數規範的總和,一共規定了12項大的規範
2
主流服務軟體
軟體名 | 特點 |
---|---|
weblogic | oracle公司,收費 |
websophere | ibm公司,收費 |
jboss | jboss公司,收費 |
tomcat | apache組織,免費 |
3
tomcat檔案目錄
目錄 | 功能 |
---|---|
bin | 二進位制執行檔案 |
conf | 配置檔案 |
lib | 依賴jar包 |
logs | 日誌檔案 |
temp | 臨時檔案 |
webapps | 存放的web專案 |
work | 執行時資料 |
4
啟動和關閉
1)啟動
bin目錄下,執行startup.bat,在localhost:8080訪問
可能遇到問題
(1)黑視窗一閃而過
未正確配置java環境變數JAVA_HOME
(2)啟動報錯
8080埠被佔用,要麼殺程序,要麼在conf.server.xml修改埠號
2)關閉
bin目錄下,執行shutdown.bat或者在服務視窗ctrl+c
5
部署
1)將專案放到webapps目錄下
專案可打包成war,將war包防止到webapps目錄下
2)配置conf/server.xml檔案
新增一行<Contex docBase="D\hello" path"/hehe/">
3)在conf/Catalina/localhost下建立任意名的xml檔案
檔案內容是<Contex docBase="D\hello" >
,連線中訪問的path路徑就是xml的檔名
6
動態專案的目錄結構
--專案根目錄
--WEB-INF
--web,xml//web專案的核心配置檔案
--classes//放置位元組碼檔案的目錄
--lib//放置依賴的jar包
7
將tomcat部署到IDEA中
1)配置tomcat
run->edit configrations->templates->tomcat server->local
把tomcat的安裝路徑設定上
2)建立JAVAEE專案
file->new project->java enterprise
選中web application後點選下一步
輸入專案名點選下一步,然後執行
servlet
執行在伺服器上的小程式,本質上是一個介面
1
快速開始
1.建立javaee專案
2.定義類,實現Servlet
3.實現抽象方法
4.配置url,如配置web.xml檔案
//建立一個實現Servlet的類
import javax.servlet.*;
import java.io.IOException;
public class abc implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service……");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
//web.xml將新建的實現類註冊進去,並配置url
<?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">
<servlet>
<servlet-name>demo01</servlet-name>
<servlet-class>abc</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo01</servlet-name>
<url-pattern>/demo01</url-pattern>
</servlet-mapping>
</web-app>
2
執行原理
1)伺服器接收客戶端瀏覽器的請求後,會解析請求的url路徑,獲取訪問的servlet資源路徑
2)查詢web.xml檔案是否由對應的
3
servlet生命週期
1)被建立
建立後會執行一次實現類的init方法,預設情況是在第一次訪問實現類對應的url時才會被建立,這裡可以在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">
<servlet>
<servlet-name>demo01</servlet-name>
<servlet-class>abc</servlet-class>
<load-on-startup>2</load-on-startup><!--正數或0表示服務啟動時載入類,負數表示訪問url時載入類-->
</servlet>
<servlet-mapping>
<servlet-name>demo01</servlet-name>
<url-pattern>/demo01</url-pattern>
</servlet-mapping>
</web-app>
2)提供服務
每次呼叫servlet時,其service方法被執行一次
3)被銷燬
在servlet被銷燬前,執行destroy方法
總之,servlet是單例的,不要哦在servlet中定義變數,即使定義了,也不要修改值
4
註解配置url
在servlet3.0中,支援註解配置url,不再需要web.xml
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/demo")//註解配置url
public class abc implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init……");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service……");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
5
IDEA中的tomcat
1)IDEA為每一個tomcat部署的專案單獨建立一份配置檔案
2)IDEA會將工作空間裡的專案複製到tomcat上部署
3)WEB-INF目錄下的資源無法被訪問
4)端點除錯,需要使用小蟲子啟動
5
servlet的實現類
1)GenericServlet
該類是servlet的實現類,有一個抽象方法service
//原始碼摘取
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
2)HttpServlet
常需重寫doGet和doPost方法
//原始碼摘取
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
6
url定義
1)/xx
2)/xx/xx
3)*.do
HTTP
定義的客戶端與服務端通訊的資料格式
特點:
基於TCP/IP協議,預設埠為80,基於請求、響應模型,無狀態
版本
1.0每次請求、響應會重新建立連線,1.1複用連線
1
請求訊息的資料格式
1)請求行
2)請求頭
3)請求空行
4)請求體
2
GET和POST
GET請求的引數在請求行的url中,url裡的資料長度有限制
POST請求的引數在請求體中,長度無限制
3
請求頭中的refer
標記該請求的跳轉來源,用於防盜鏈和統計
4
request物件基礎體系結構
ServletRequest 介面
|繼承
HttpServletRequest 介面
|繼承
org.appache.catalina.connector.RequestFacade tomcat建立的實現類
5
request的功能
1)獲取獲取請求訊息資料
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo1")
public class abc extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1)獲取請求方式
String m=req.getMethod();
System.out.println(m);//GET
//2)獲取虛擬目錄
String cp=req.getContextPath();
System.out.println(cp);//
//3)獲取servlet路徑
String sp=req.getServletPath();
System.out.println(sp);///demo1
//4)獲取get請求引數
String qs=req.getQueryString();
System.out.println(qs);//null
//5)獲取uri
String uri=req.getRequestURI();
StringBuffer url=req.getRequestURL();
System.out.println(uri);//demo1
System.out.println(url);//http://localhost:8081/demo1
//6)獲取協議版本
String ptc=req.getProtocol();
System.out.println(ptc);//HTTP/1.1
//7)獲取客戶機ip地址
String rma=req.getRemoteAddr();
System.out.println(rma);//0:0:0:0:0:0:0:1
}
}
2)獲取請求頭資料
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/demo1")
public class abc extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration<String> headernames=req.getHeaderNames();
while (headernames.hasMoreElements()){
System.out.println(headernames.nextElement());//獲取請求頭的鍵
}
/*
host
connection
cache-control
upgrade-insecure-requests
user-agent
……
*/
}
}
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/demo1")
public class abc extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String agent=req.getHeader("user-agent");//獲取請求頭某個鍵對應的值
System.out.println(agent);
//Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36 Edg/81.0.416.62
}
}
3)獲取請求體資料
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/demo1")
public class abc extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("dopost....");
BufferedReader br=req.getReader();//獲取字元輸入流
char[] data=new char[1024];
int len;
while ((len=br.read(data))!=-1){
System.out.println(data);
}
//username=2323&password=232323
}
}
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo1")
public class abc extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("dopost....");
ServletInputStream sis=req.getInputStream();//獲取位元組輸入流
byte[] b=new byte[1024];
int len;
while ((len=sis.read(b))!=-1){
System.out.println(new String(b));
}
//username=2323&password=232323
}
}
4)其他方法
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
@WebServlet("/demo1")
public class abc extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取引數值
String username=req.getParameter("username");
System.out.println(username);//zhanghuan
//獲取引數值的陣列
String[] vls=req.getParameterValues("hobby");
System.out.println(Arrays.toString(vls));//[basketball, football]
//獲取引數的鍵集合
Enumeration<String> names=req.getParameterNames();
while (names.hasMoreElements()){
System.out.println(names.nextElement());
}
/*
username
password
hobby
*/
//獲取引數的鍵值對
Map<String,String[]> mp=req.getParameterMap();
Set<Map.Entry<String, String[]>> set=mp.entrySet();
for(Map.Entry<String,String[]> i:set){
System.out.println(i.getKey()+"="+Arrays.toString(i.getValue()));
}
/*
username=[zhanghuan]
password=[2323]
hobby=[basketball, football]
*/
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
//不管是get方式還是post方式,這些獲取引數的方法都生效
5)亂碼問題
在tomcat8以上,get方式提交的值無亂碼問題,而post方式提交的值存在亂碼
需要在doPost方法里加上
req.setCharacterEncoding("utf-8");
6)請求轉移
一種在伺服器內部的資源跳轉方式,因此瀏覽器的url不會發生變化,由於在伺服器內部轉移,所以只能轉發到伺服器內部的servlet物件,轉發過程中是伺服器自發與客戶端瀏覽器無關
req.getRequestDispatcher("/demo2").forward(req,resp);
7)共享資料
域物件:一個有作用範圍的物件,可在範圍內共享資料
request域:一次請求範圍,一般用於請求轉發的多個資源中共享資料
//設定共享值
void setAttribute(String var1, Object var2);
//獲取共享值
Object getAttribute(String var1);
//刪除共享值
void removeAttribute(String var1);
//獲取整個web應用的域物件
ServletContext getServletContext();
6)登陸案例
//目錄結構
--src
--dao
userdao.java
--doMain
user.java
--uitil
JDBCutils.java
--web
loginServlet.java
duoid.properties
--web
--WEB-INFO
--lib//這裡放jar包,如果放錯位置控制太不會報錯,頁面上會報500錯誤
index.jsp
//JDBCutils.java
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class JDBCutils {
static Properties p=new Properties();
static {
try {
InputStream is=JDBCutils.class.getClassLoader().getResourceAsStream("druid.properties");
p.load(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static DataSource getDataSource() {
DataSource ds=null;
try {
ds = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
return ds;
}
public static Connection getConnection(){
Connection con=null;
try {
con=getDataSource().getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
}
//Userdao.java
package dao;
import doMain.User;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import util.JDBCutils;
public class Userdao {
private JdbcTemplate tmplate=new JdbcTemplate(JDBCutils.getDataSource());
public User login(User loginuser){
try {
String sql="select * from user where username=? and password=?";
User user=tmplate.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),loginuser.getUsername(),loginuser.getPassword());
return user;
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
}
//user.java
package doMain;
public class User {
private Integer id;
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
//LoginServlet.java
package web;
import dao.Userdao;
import doMain.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/loginservlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User loginuser=new User();
loginuser.setUsername(req.getParameter("username"));
loginuser.setPassword(req.getParameter("password"));
Userdao dao=new Userdao();
System.out.println(loginuser);
User user=dao.login(loginuser);
if(user==null){
System.out.println("登陸失敗");
}else {
System.out.println("登陸成功");
}
System.out.println("dopost");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
<!--index.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login</title>
</head>
<body>
<form action="/login_war_exploded/loginservlet" method="post">
<input type="text" name="username" placeholder="username"><br>
<input type="text" name="password" placeholder="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
7)BeanUtils
主要提供了對於JavaBean進行各種操作,比如物件,屬性複製等等。使用前需匯入匯入commons-beanutils-1.8.3 包和commons-logging-1.1.3 包
注意方法 | 描述 |
---|---|
public static void setProperty(Object bean, String name, Object value) | 設定指定屬性的值 |
public static String getProperty(Object bean, String name) | 獲取指定屬性的值 |
public static void populate(Object bean, Map<String, ? extends Object> properties) | 將map資料複製到javabean中 |
import doMain.User;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
public class test {
@Test
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
User user=new User();
Map<String,String> map=new HashMap<>();//Map的第二個泛型可以是陣列,執行populate時會取陣列的第一個元素
map.put("username","zhanghuan");
map.put("password","123456");
BeanUtils.populate(user,map);
System.out.println(user);//User{id=null, username='zhanghuan', password='123456'}
}
}
/*
JavaBean
1.類必須被public修飾
2.必須提供空引數構造器
3.成員變數必須使用private修飾
4.提供公共的setter和getter方法
*/
6
響應
由響應行、響應頭、響應空行、響應體組成
1)響應行格式
協議/版本 響應狀態碼 狀態碼解釋
2)狀態碼錶示資訊
狀態碼 | 含義 |
---|---|
1XX | 伺服器接收客戶端訊息,但沒完成,等待一段時間後,傳送1XX狀態碼 |
2XX | 成功 |
3XX | 重定向,304表示訪問快取,302表示重定向 |
4XX | 客戶端錯誤,404請求路徑沒有對應的資源,405請求方式沒有對應的doXX方法 |
5XX | 伺服器錯誤,500伺服器內部錯誤 |
6)響應頭
(1)Content-Type
指定資料格式及編碼
(2)Content-disposition
指定以什麼格式開啟響應體,in-line當前頁面開啟,attachment;filename=xxx以附件形式開啟響應體,用於下載
7)響應體
傳輸的資料
8)獲取虛擬目錄
req.getContextPath();
9)重定向
package web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/index")
public class indexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//方式一
/*
resp.setStatus(302);
resp.setHeader("location",req.getContextPath()+"/login");
*/
//方式二
resp.sendRedirect(req.getContextPath()+"/login");
}
}
特點:
位址列裡的地址會發生變化,可訪問其他站點的資源,傳送了兩次請求
10)字元輸出流
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/login")
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設定writer的字元編碼
resp.setCharacterEncoding("utf-8");
//給客戶端指定字元編碼方式一
//resp.setHeader("Content-Type","text/html;charset=utf-8");
//給客戶端指定字元編碼方式二
resp.setContentType("text/html;charset=utf-8");
//獲取writer
PrintWriter pr=resp.getWriter();
//向響應體寫入資料
pr.write("這是登陸頁");
}
}
11)驗證碼案例
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Random;
public class randomPic {
static String[] strs=null;
public static String getRandomString(){
String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
String result_str="";
Random rd=new Random();
for (int i = 0; i <4 ; i++) {
int num=rd.nextInt(61);
result_str+=Character.toString(str.charAt(num));
}
return result_str;
}
public static void drawImg(String str,OutputStream os,int width,int height){
Random rd=new Random();
//建立畫布
BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//建立畫筆
Graphics g=img.createGraphics();
//設定畫筆顏色
g.setColor(Color.PINK);
//用畫筆填充畫布
g.fillRect(0,0,width, height);
//在畫布上寫字串
g.setColor(Color.BLUE);
Font f=new Font(null,Font.PLAIN,25);
g.setFont(f);//設定字型大小
strs=str.split("");//獲取隨機字串
for (int i = 0; i <strs.length ; i++) {
g.drawString(strs[i],width/4*i+8,rd.nextInt(height/4)+height/2);
}
//在畫布上畫干擾線
for (int i = 0; i <10 ; i++) {
g.drawLine(rd.nextInt(width),rd.nextInt(height),rd.nextInt(width),rd.nextInt(height));
}
//將圖片寫入到流中
try {
boolean jpg = ImageIO.write(img, "jpg", os);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import doMain.randomPic;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String str=randomPic.getRandomString();//獲取隨機字串
System.out.println(str);
ImageIO.setUseCache(false);//使用記憶體來儲存臨時檔案,無此句可能報錯
randomPic.drawImg(str,resp.getOutputStream(),100,50);
}
}
12)ServletContex
代表整個web應用,可以和程式容器(伺服器)通訊
該物件有3個功能:
獲取MIME型別,域物件,獲取檔案正式路徑
(1)獲取ServletContex物件
//1.透過req物件獲取
req.getServletContex();
//2.透過HttpServlet物件獲取
this.getServletContex();
(2)獲取MIME型別
MIME型別:網際網路通訊中定義的一種檔案型別,格式為:大型別/小型別
String getMimeType(String var1);
(3)域物件方法
//設定屬性
void setAttribute(String var1, Object var2);
//獲取屬性
Object getAttribute(String var1);
//刪除屬性
void removeAttribute(String var1);
(4)獲取正式路徑
String getRealPath(String var1);
注意:這裡獲取路徑的檔案預設是web目錄下的所有檔案,如果要獲取的檔案是src下的,需要進入WEB-INF/classes目錄下獲取
13)下載案例
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@WebServlet("/download")
public class downloadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext sc=this.getServletContext();
String contenttype=sc.getMimeType("2.jpg");
resp.setContentType( contenttype);
resp.setHeader("content-disposition","attachment;filename=2.jpg");
//檔名如果是中文需要特殊將中文進行編碼
String path=sc.getRealPath("/imgs/1.jpg");
InputStream is= new FileInputStream(path);
ServletOutputStream os=resp.getOutputStream();
int len;
byte[] b=new byte[1024];
while ((len=is.read(b))!=-1){
os.write(b,0,len);
}
os.close();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
7
cookie
客戶端會話技術
//建立cookie
Cookie c=new Cookie("name","zhanghuan");
//傳送cookie
response.addCookie(c);
//獲取cookie
Cookie[] cs=request.getCookies();
1)特點:
(1)一次可傳送多個cookie
(2)預設情況下,瀏覽器關閉cookie銷燬
(3)可設定cookie的存活時間
Cookie c=new Cookie("name","zhanghuan");
c.setMaxAge(30);//設定cookie存活時間為30秒
//setMaxAge的引數為int型別,負數表示刪除cookie,0表示瀏覽器關閉cookie銷燬
(4)cookie的鍵值對在tomcat8之後支援中文,但最好還是不要存中文,可對中文進行編碼
URLEncoder.encode(String s, String enc);//s是需要編碼的字串,enc是編碼格式,返回一個字串
URLDecoder.decode(String s, String enc);//s是需要解碼的字串,enc是解碼格式,返回一個字串
2)cookie共享問題
(1)預設情況下,同一伺服器下的不同專案不可共享,如果要共享需設定
setPath(String path);
//傳入path為“/”,表示共享
(2)預設情況下,不同伺服器下的專案不可共享,如果要共享需設定
setDomain(String path);
//與path匹配上的一級域名,可共享該cookie
8
session
服務端會話技術
//建立session
HttpSession s=request.getSession();
//設定session
s.setAttribute("name","zhanghuan");
//獲取session值
s.getAttribute("name");
//刪除session
s.removeAttribute("name");
1)存活時間
在伺服器存放的session資料能保留30分鐘,伺服器關閉或session物件呼叫invalidate方法會銷燬session,要修改session在伺服器的存活時間,需要到conf目錄下的web.xml修改配置
<session-config>
<session-timeout>30</session-timeout>
</session-config>
2)伺服器或瀏覽器關閉後對session的影響
(1)瀏覽器關閉
session依賴於cookie,瀏覽器關閉後未設定過期時間的cookie會被清除掉,再次開啟瀏覽器傳送請求後,伺服器讀取不到名為JSESSIONID的cookie,便把該次請求當作一個新請求並重新分配session;要解決這個問題,需要給名為JSESSIONID的cookie設定過期時間
(2)伺服器關閉
在IDEA中session會發生變化,在tomcat中會自動完成session的鈍化、活化操作,session不會發生變化
3)session和cookie的比較
session | cookie | |
---|---|---|
位置 | 伺服器 | 瀏覽器 |
可存入的資料大小 | 無限制 | 有限制 |
安全性 | 安全 | 不安全 |
9
驗證碼登陸案例
//獲取動態驗證碼的servlet服務
package web;
import midware.randomPic;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/getvalidpicServlet")
public class getvalidpicServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str= randomPic.getRandomString();
System.out.println(str);
HttpSession s=request.getSession();
s.setAttribute("validcode",str);
ImageIO.setUseCache(false);
randomPic.drawImg(str,response.getOutputStream(),100,50);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
<!--登陸頁面-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/login">
<table>
<tr>
<td>使用者名稱</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密碼</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td>驗證碼</td>
<td><input type="text" name="validcode"></td>
</tr>
<tr>
<td colspan="2"><img id="vpic" alt=""></td>
</tr>
<tr>
<td colspan="2"><input id="sub" type="submit"></td>
</tr>
</table>
</form>
</body>
</html>
<script>
window.onload=function () {
picsrc()
document.getElementById("vpic").onclick=function () {
picsrc()
}
}
function picsrc() {
var vpic=document.getElementById("vpic")
var date=new Date()
vpic.setAttribute("src","<%=request.getContextPath()%>/getvalidpicServlet?a="+date.getSeconds())
}
</script>
//登陸的servl服務
package web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class loginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取傳過來的資料
String username=req.getParameter("username");
String password=req.getParameter("password");
String validcode=req.getParameter("validcode");
//獲取session中存放的驗證碼
HttpSession s=req.getSession();
String session_valid=(String)s.getAttribute("validcode");
//響應
resp.setCharacterEncoding("utf-8");
resp.setHeader("Content-Type","text/html;charset=utf-8");
if(validcode.equalsIgnoreCase(session_valid)){
if(username.equals("zhanghuan") && password.equals("123")){
resp.getWriter().write("歡迎你,"+"zhanghuan");
}else{
resp.getWriter().write("登陸失敗,賬號或密碼錯誤");
}
}else{
resp.getWriter().write("登陸失敗,驗證碼錯誤");
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
10
JSP
java服務端頁面,可定義html標籤,也可定義java程式碼,本質是一個servlet
1)指令
用於配置jsp頁面,匯入資原始檔
格式
<%@ 指令名 屬性名=屬性值…… %>
指令分類
(1)page
配置jsp頁面常用4個屬性
屬性 | 功能 |
---|---|
contentType | 設定頁面的MIME屬性 |
import | 匯入java包 |
errorPage | 發生錯誤時跳轉到另一個目標頁面 |
isErrorPage | 標誌該頁面是否可使用exception物件 |
(2)incluede
頁面包含
<%@include file="abc.jsp"%>
(3)taglib
匯入標籤庫資源
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2)指令碼
<% 程式碼 %>//定義內容在service方法中
<%! 程式碼 %>//定義內容在jsp轉換的java類中的成員位置
<%= 程式碼 %>//定義內容輸出到頁面上
3)註釋
<!---->//只能註釋html程式碼
<%---->//能註釋所有內容,註釋後的內容不會在頁面上出現
4)內建物件
不需要建立,可直接使用的物件
物件名 | 真實型別 | 說明 |
---|---|---|
pageContex | pageContex | 可獲取其他8個物件,當前頁面資料共享 |
request | HttpServletRequest | 一次請求資料共享 |
session | HttpSession | 一次會話資料共享 |
application | ServletContext | 所有使用者資料共享 |
response | HttpServletResponse | 響應物件 |
page | Object | 當前頁面物件 |
out | JspWriter | 輸出物件 |
config | ServletConfig | Servlet配置物件 |
exception | Throwable | 異常物件 |
out和response.getWriter().write()都能輸出到頁面上,但後者輸出的內容在前者之前
MVC
解釋 | 實現元素 | 功能 | |
---|---|---|---|
M | 模型 | JavaBean | 查詢資料庫,封裝物件 |
V | 檢視 | JSP | 展示資料 |
C | 控制器 | Servlet | 獲取使用者輸入,呼叫模型,將資料交給檢視進行展示 |
優點
耦合性低,方便維護,重用性高
缺點
使得專案架構複雜
EL表示式
Expression Langarage表示式語言,用於替換、簡化JSP中的java程式碼
忽略el表示式
1)設定jsp中page的屬性isELIgnored=""設定為true
2)\${ 表示式 }
1
運算子
型別 | 詳細 |
---|---|
算術運算子 | + - * / div % mod |
比較運算子 | > < == >= <= != |
邏輯運算子 | & and | or ! not |
定運算子 | empty |
empty用於判斷字串、集合、陣列物件是否為null並且長度為0,是返回為true
${ empty list }
${ not empty list }
2
域物件獲取值
//1.從指定域中獲取指定值
${域名稱.鍵名}
//2.依次從最小域中找是否有對應鍵的值
${鍵名}
3
獲取物件屬性值
${物件.屬性名}
4
隱式物件
el表示式有11個隱式物件,可透過pageContext獲取其他8個物件
${ pageContext.request.contextPath }
JSTL
JavaServer Pages Tag Library jsp標準標籤庫,用於替換、簡化JSP中的java程式碼
使用步驟:
1.匯入jstl的兩個java包
2.JSP中透過指令引入標籤庫<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3.頁面中使用標籤
1
if
相當於java中的if語句
<c:if test="true">
該標籤內test屬性值為true,會顯示出來
</c:if>
<c:if test="false">
該標籤內test屬性值為false,不會顯示出來
</c:if>
2
choose
相當於java中的switch語句
<%
request.setAttribute("num",1);
%>
<c:choose>
<c:when test="${num==1}">星期一</c:when>
<c:when test="${num==2}">星期二</c:when>
<c:when test="${num==3}">星期三</c:when>
<c:when test="${num==4}">星期四</c:when>
<c:when test="${num==5}">星期五</c:when>
<c:when test="${num==6}">星期六</c:when>
<c:when test="${num==7}">星期七</c:when>
<c:otherwise>輸入錯誤</c:otherwise>
</c:choose>
3
forEach
相當於java中的for語句
<%--1.完成重複性操作--%>
<table>
<th> 變數i的值</th>
<th> 迴圈次數</th>
<th> 迴圈索引</th>
<c:forEach begin="1" end="5" var="i" step="1" varStatus="s">
<tr>
<td> ${i}</td>
<td> ${s.count}</td>
<td> ${s.index}</td>
</tr>
</c:forEach>
</table>
<%--執行結果
變數i的值 迴圈次數 迴圈索引
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
--%>
<%--2.遍歷容器--%>
<%
String[] ar={"a","b","c"};
request.setAttribute("ar",ar);
%>
<c:forEach items="${ar}" var="str">
${str}<br>
</c:forEach>
Filter過濾器
訪問伺服器資源時,過濾器可以將請求攔截下來,完成同一特殊功能。用於完成一些通用操作,如:登陸驗證、統一編碼處理、敏感字元過濾等
1
建立步驟
1)建立類實現Filter介面
2)實現抽象方法,在doFilter裡呼叫chain.doFilter(req, resp)
,放行請求
3)將該實現類進行註冊
<!--web.xml-->
<filter>
<filter-name>allFilter</filter-name>
<filter-class>allFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>allFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
//另一種方式時在類上面新增註解
@WebFilter(filterName = "/*")
2
生命週期方法
方法名 | 解釋 |
---|---|
init | 伺服器啟動後,會建立Filter物件,然後呼叫init方法,只執行一次,用於載入資源 |
doFilter | 每次請求被攔截資源時,會執行,執行多次 |
destroy | 在伺服器關閉後,Filter物件被銷燬;如果是正常關閉,會執行destroy方法,只執行一次,用於釋放資源 |
3
攔截路徑配置
1)具體資源路徑
@WebFilter("/index.jsp")
2)攔截目錄
@WebFilter("/user/*")
3)字尾名攔截
@WebFilter("*.jsp")
4
攔截方式配置
1)註解上配置
@WebFilter(value="*.jsp",dispatcherTypes=DispatcherType.REQUEST)
2)web.xml配置
<filter>
<filter-name>allFilter</filter-name>
<filter-class>allFilter</filter-class>
<dispatcher>REQUEST</dispatcher>
</filter>
3)攔截型別
型別 | 含義 |
---|---|
DispatcherType.REQUEST | 直接訪問時過濾 |
DispatcherType.FORWARD | 轉發訪問時過濾 |
DispatcherType.INCLUDE | 包含時過濾 |
DispatcherType.ERROR | 發生錯誤時過濾 |
DispatcherType.ASYNC | 非同步時過濾 |
5
多個過濾器執行的先後順序
1)註解配置的過濾器
安裝類名字串比較規則比較,值小的先執行
2)web.xml配置
誰定義在上面,誰先執行
6
過濾器驗證登陸案例思路
請求過來時,看這個請求訪問的資源,如果是登陸相關的就透過,如果不是就判斷使用者登陸狀態;如果使用者已登陸,放行透過;為登陸,跳轉到登陸介面
代理模式
代理模式給某一個物件提供一個代理物件,並由代理物件控制對原物件的引用。通俗的來講代理模式就是我們生活中常見的中介
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@WebFilter("/*")
public class allFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
ServletRequest proxy_req=(ServletRequest)Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//利用代理對引數進行過濾
if(method.getName().equals("getParameter")){
String value=(String) method.invoke(req,args);
value=value.replaceAll("zhanghuan","張歡");
System.out.println(value);
return value;
}
return method.invoke(req,args);
}
});
chain.doFilter(proxy_req,resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
監聽器
監聽觀察某個事件(程式)的發生情況,當被監聽的事件真的發生了的時候,事件發生者(事件源) 就會給註冊該事件的監聽者(監聽器)傳送訊息,告訴監聽者某些資訊,同時監聽者也可以獲得一份事件物件,根據這個物件可以獲得相關屬性和執行相關操作
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;//監聽ServletContext的建立和銷燬
import javax.servlet.annotation.WebListener;
@WebListener//註冊監聽器
public class ServletContexListener1 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {//監聽到建立後執行
System.out.println("ServletContext建立了……");
//獲取初始化引數
String str=sce.getServletContext().getInitParameter("name");
System.out.println(str);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {//監聽到銷燬後執行
}
}
註冊監聽器也可在web.xml中配置
<listener>
<listener-class>com.ygj.control.onLineCount</listener-class>
</listener>
初始化引數
在web.xml中配置
<init-param>
<param-name>username</param-name>
<param-value>moonlit</param-value>
</init-param>
可透過HttpServlet.getInitParameter(String Param)拿到
Redis
非關係型資料庫,鍵值對資料,value有5種不同的資料型別,分別是字串(string),雜湊(hash),列表(list),集合(set),有序集合(sortedset)
1
操作
型別 | 操作 | 命令 | 說明 |
---|---|---|---|
字串(string) | 存 | set key value | |
取 | get key | ||
刪 | del key | ||
雜湊(hash) | 存 | hset key field value | |
取 | hget key field | ||
hgetall key | 獲取所有的field和value | ||
刪 | hdel key field | ||
列表(list) | 存 | lpush key value | |
rpush key value | |||
取 | lrange key start end | ||
刪 | lpop key | ||
rpop key | |||
集合(set) | 存 | sadd key value | |
取 | smembers key | ||
刪 | srem key value | ||
有序集合(sortedset) | 存 | zadd key score value | |
取 | zrange key start end | ||
刪 | zrem key value | ||
通用 | keys * | 檢視所有的鍵 | |
type key | 檢視某一鍵的資料型別 | ||
del key | 刪除鍵 |
2
持久化
將記憶體種的資料儲存到硬碟上
(1)RDB
預設方式,無需配置。一定時間間隔中,檢測key變化情況,然後持久化資料
save 900 1
save 300 10
save 60 10000
# In the example below the behaviour will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed
(2)AOF
日誌記錄方式,可以記錄每一條命令的操作,每一次命令操作後,持久化資料
# enable the append only mode: when this mode is enabled Redis will append
# every write operation received in the file appendonly.aof.
appendonly no#改為yes
# appendfsync always
appendfsync everysec#每秒持久化一次
# appendfsync no
3
Jedis
透過java操作redis資料庫,需匯入2個jar包
(1)各型別資料操作
import redis.clients.jedis.Jedis;
import java.util.Map;
public class test01 {
static Jedis j=new Jedis("localhost",6379);//空引數預設值"localhost",6379
public static void main(String[] args) throws InterruptedException {
string_value();
hash_value();
list_value();
set_value();
sortedset_value();
j.close();//關閉連線
}
public static void string_value() throws InterruptedException {
//設定鍵值對
j.set("name","asdsdsd");
System.out.println(j.get("name"));//asdsdsd
//刪除鍵值對
j.del("name");
System.out.println(j.get("name"));//null
//設定具有過期時間的鍵值對
j.setex("age", 5, "25");
System.out.println(j.get("age"));//25
Thread.sleep(10000);
System.out.println(j.get("age"));//null
j.close();
}
public static void hash_value(){
//設定
j.hset("myhashset","name","zhanghuan");
System.out.println(j.hget("myhashset","name"));//zhanghuan
//獲取map
Map<String,String> map=j.hgetAll("myhashset");
System.out.println(map);//{name=zhanghuan, age=25}
//刪除map下的鍵
j.hdel("myhashset","name","age");
System.out.println(j.hgetAll("myhashset"));//{}
}
public static void list_value(){
//壓入
j.lpush("mylist","a");
j.rpush("mylist","b");
System.out.println(j.lrange("mylist",0,-1));//[a, b]
//彈出
System.out.println(j.lpop("mylist"));//a
System.out.println(j.rpop("mylist"));//b
}
public static void set_value(){
//存
j.sadd("myset","大毛");
j.sadd("myset","小毛");
//取
System.out.println(j.smembers("myset"));//[小毛, 大毛]
//刪除指定值
j.srem("myset","大毛");
System.out.println(j.smembers("myset"));//[小毛]sortedset
}
public static void sortedset_value(){
//存
j.zadd("mysortedset",10,"小黃");
j.zadd("mysortedset",18,"小黑");
j.zadd("mysortedset",14,"小白");
//取
System.out.println(j.zrange("mysortedset",0,-1));//[小黃, 小白, 小黑]
//刪除
j.zrem("mysortedset","小白");
System.out.println(j.zrange("mysortedset",0,-1));//[小黃, 小黑]
}
}
(2)封裝連線池物件
#jedis.properties
host=127.0.0.1
port=6379
MaxTotal=50
MaxIdle=10
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class JedisPoolUtils {
private static JedisPool pool;
static {
//讀取配置檔案
InputStream is=JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
Properties p=new Properties();
try {
p.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//建立配置物件
GenericObjectPoolConfig<String> config=new GenericObjectPoolConfig<>();
config.setMaxIdle(Integer.parseInt(p.getProperty("MaxIdle")));
config.setMaxTotal(Integer.parseInt(p.getProperty("MaxTotal")));
//生成連線池
pool=new JedisPool(config,p.getProperty("host"),Integer.parseInt(p.getProperty("port")));
}
public static Jedis getJedis(){
return pool.getResource();
}
}
4
省市二級聯動案例
1)資料庫
型別 | 欄位名 | 解釋 |
---|---|---|
int | CRI_ID | id |
varchar | CRI_CODE | 6位編碼,區分省、市,前3位代表省,第4位代表市,後2位代表取 |
varchar | CRI_NAME | 省、市、區名稱 |
2)目錄結構
-src
-dao
-impl
cn_regionDaoimpl.java
cn_regionDao.java
-domain
Cn_region.java
-service
-impl
getCitiesServiceimpl.java
getProvincesServiceimpl.java
getCitiesService.java
getProvincesService.java
-utils
JDBCutils.java
JEDISPOOLutils.java
-web
getCitiesServlet.java
getProvincesServlet.java
duid.properties
jedis.properties
web
-WEB-INF
-lib
web.xml
index.jsp
3)檔案內容
//cn_regionDaoimpl.java
package dao.impl;
import dao.cn_regionDao;
import doMain.Cn_region;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import utils.JDBCutils;
import java.util.ArrayList;
import java.util.List;
public class cn_regionDaoimpl implements cn_regionDao {
static private JdbcTemplate template=new JdbcTemplate(JDBCutils.getDataSource());
@Override
public List<Cn_region> findAll() {
List<Cn_region> list=template.query("select CRI_ID,CRI_CODE,CRI_NAME from cn_region_info",new BeanPropertyRowMapper<Cn_region>(Cn_region.class));
return list;
}
@Override
public List<Cn_region> getProvinces() {
List<Cn_region> alllist=findAll();
List<Cn_region> r_list=new ArrayList<Cn_region>();
String CRI_CODE_last_3;//最後3位,用來判斷是否是省
for (Cn_region item:
alllist) {
CRI_CODE_last_3=item.getCRI_CODE().substring(3,6);
if(CRI_CODE_last_3.equals("000")){
r_list.add(item);
}
}
return r_list;
}
@Override
public List<Cn_region> getCites(String province_code) {
List<Cn_region> alllist=findAll();
List<Cn_region> r_list=new ArrayList<Cn_region>();
String CRI_CODE_first_3;//擷取前三位
String CRI_CODE_4;//擷取第四位
String CRI_CODE_last_2;//最後兩位
for (Cn_region item:
alllist) {
CRI_CODE_first_3=item.getCRI_CODE().substring(0,3);
CRI_CODE_4=item.getCRI_CODE().substring(3,4);
CRI_CODE_last_2=item.getCRI_CODE().substring(4,6);
if( CRI_CODE_first_3.equals (province_code) && !CRI_CODE_4.equals ("0") && CRI_CODE_last_2.equals("00")){
r_list.add(item);
}
}
return r_list;
}
@Override
public List<Cn_region> getCity_areas() {
return null;
}
}
//cn_regionDao.java
package dao;
import doMain.Cn_region;
import java.util.List;
public interface cn_regionDao {
public List<Cn_region> findAll();
public List<Cn_region> getProvinces();
public List<Cn_region> getCites(String province_code);
public List<Cn_region> getCity_areas();
}
//Cn_region.java
package doMain;
public class Cn_region {
private int CRI_ID;
private String CRI_CODE;
private String CRI_NAME;
public int getCRI_ID() {
return CRI_ID;
}
public String getCRI_CODE() {
return CRI_CODE;
}
public String getCRI_NAME() {
return CRI_NAME;
}
public void setCRI_ID(int CRI_ID) {
this.CRI_ID = CRI_ID;
}
public void setCRI_CODE(String CRI_CODE) {
this.CRI_CODE = CRI_CODE;
}
public void setCRI_NAME(String CRI_NAME) {
this.CRI_NAME = CRI_NAME;
}
@Override
public String toString() {
return "Cn_region{" +
"CRI_ID=" + CRI_ID +
", CRI_CODE='" + CRI_CODE + '\'' +
", CRI_NAME='" + CRI_NAME + '\'' +
'}';
}
}
//getCitiesServiceimpl.java
package service.impl;
import dao.impl.cn_regionDaoimpl;
import doMain.Cn_region;
import org.codehaus.jackson.map.ObjectMapper;
import redis.clients.jedis.Jedis;
import service.getCitiesService;
import utils.JEDISPOOLutils;
import java.io.IOException;
import java.util.List;
public class getCitiesServiceimpl implements getCitiesService {
@Override
public String findAll(String province_code){
cn_regionDaoimpl dao=new cn_regionDaoimpl();
List<Cn_region> list=dao.getCites (province_code);
//序列化
ObjectMapper maper=new ObjectMapper();
String json= null;
try {
json = maper.writeValueAsString (list);
} catch (IOException e) {
e.printStackTrace ( );
}
return json;
}
@Override
public String findAllJson(String province_code){
//先從redis中查詢資料,如果沒有再從資料庫中查詢
Jedis jedis= JEDISPOOLutils.getJedis ();
String cities= jedis.hget ("cities",province_code);
String json;
if(cities==null || cities.length ()==0){
json=findAll (province_code);
jedis.hset("cities",province_code,json);
}else {
json=cities;
}
jedis.close ();
return json;
}
}
//getProvincesServiceimpl.java
package service.impl;
import dao.impl.cn_regionDaoimpl;
import doMain.Cn_region;
import org.codehaus.jackson.map.ObjectMapper;
import redis.clients.jedis.Jedis;
import service.getProvincesService;
import utils.JEDISPOOLutils;
import java.io.IOException;
import java.util.List;
public class getProvincesServiceimpl implements getProvincesService {
@Override
public String findAll() {
cn_regionDaoimpl dao=new cn_regionDaoimpl();
List<Cn_region> list=dao.getProvinces ();
//序列化
ObjectMapper maper=new ObjectMapper();
String json= null;
try {
json = maper.writeValueAsString (list);
} catch (IOException e) {
e.printStackTrace ( );
}
return json;
}
@Override
public String findAllJson(){
//先從redis中查詢資料,如果沒有再從資料庫中查詢
Jedis jedis=JEDISPOOLutils.getJedis ();
String provinces= jedis.get ("provinces");
String json;
if(provinces==null || provinces.length ()==0){
json=findAll ();
jedis.set("provinces",json);
}else {
json=provinces;
}
jedis.close ();
return json;
}
}
//getCitiesService.java
package service;
import doMain.Cn_region;
import java.io.IOException;
import java.util.List;
public interface getCitiesService {
public String findAll(String province_code);
public String findAllJson(String province_code);
}
//getProvincesService.java
package service;
import doMain.Cn_region;
import java.io.IOException;
import java.util.List;
public interface getProvincesService {
public String findAll();
public String findAllJson();
}
//getCitiesServlet.java
package web;
import service.impl.getCitiesServiceimpl;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/getCitiesServlet")
public class getCitiesServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
//獲取省份id
String province_id=request.getParameter ("province_id").substring (0,3);
//獲取資料
getCitiesServiceimpl getCitiesServiceimpl=new getCitiesServiceimpl();
String json=getCitiesServiceimpl.findAllJson (province_id);
//返回
response.setCharacterEncoding ("utf-8");
response.setHeader ("contentype","application/json;charset=utf-8");
response.getWriter ().write (json);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
this.doPost (request, response);
}
}
//getProvincesServlet.java
package web;
import service.impl.getProvincesServiceimpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@WebServlet("/getProvincesServlet")
public class getProvincesServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取資料
getProvincesServiceimpl getProvincesServiceimpl=new getProvincesServiceimpl();
String json=getProvincesServiceimpl.findAllJson ();
//返回
response.setCharacterEncoding ("utf-8");
response.setHeader ("contentype","application/json;charset=utf-8");
response.getWriter ().write (json);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
<%--index.jsp--%>
<%--
Created by IntelliJ IDEA.
User: admin
Date: 2020/5/1
Time: 下午 06:32
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>
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="panel">
<div class="panel-body">
<select class="form-control" id="select1">
<option value="0">請選則</option>
</select>
</div>
</div>
</div>
<div class="col-md-3">
<div class="panel">
<div class="panel-body">
<select class="form-control" id="select2">
<option value="0">請選則</option>
</select>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script>
<%--"${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/getProvincesServlet"--%>
$(function () {
$.ajax({
method:"post",
url:"http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/getProvincesServlet",
success:function (data) {
//cri_ID,cri_NAME,cri_CODE
console.log(data)
obj=JSON.parse(data)
for(var i=0;i<obj.length;i++){
$("#select1").append("<option value="+obj[i]["cri_CODE"]+">"+obj[i]["cri_NAME"]+"</option>")
}
}
})
$("#select1").change(function () {
province_id=$(this).val()
if($(this).val()!="0"){
$.ajax({
methd:"get",
data:{"province_id":province_id},
url:"http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/getCitiesServlet",
success:function (data) {
obj=JSON.parse(data)
$("#select2").children().remove()
$("#select2").append('<option value="0">請選則</option>')
for(var i=0;i<obj.length;i++){
$("#select2").append("<option value="+obj[i]["cri_CODE"]+">"+obj[i]["cri_NAME"]+"</option>")
}
}
})
}else{
$("#select2").children().remove()
$("#select2").append('<option value="0">請選則</option>')
}
})
})
</script>
</html>
Maven
為解決專案開發過程中,匯入jar包衝突問題。透過匯入jar包的座標,編譯時從倉庫中找到對應的包完成編譯
1
安裝及環境配置
1)解壓安裝包
2)配置環境變數
MAVEN_HOME指向解壓後的安裝包位置
注意:
maven執行需要java環境,確保環境變數中有JAVA_HOME
2
倉庫
分為本地倉庫、遠端倉庫、中央倉庫。maven會先在本地倉庫找jar包,如未找到再去遠端倉庫找。
要為maven指定本地倉庫,需要在conf/setting.xml中配置
<localRepository>C:\Users\admin\Desktop\maven_repository</localRepository>
路徑中不要有中文
3)配置映象
修改目錄下conf下的setting.xml在mirrors標籤中,新增文末這一段
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
3
maven專案標準目錄結構
src/main/java //核心程式碼部分
src/main/resources //配置檔案部分
src/test/java //測試程式碼部分
src/test/resources //測試配置檔案部分
src/main/webapp //靜態資源,如js,css,圖片等
4
命令
命令 | 功能 |
---|---|
mvn clean | 刪除編譯資訊 |
mvn compile | 編譯專案 |
mvn test | 編譯測試程式碼 |
mvn package | 專案編譯,並打成war包 |
man install | 專案編譯,並打成war包,將專案複製到本地庫 |
5
maven生命週期
生命週期 | 操作 | 命令 |
---|---|---|
清理生命週期 | 清除專案編譯資訊 | clean |
預設生命週期 | 編譯 | compile |
測試 | test | |
打包 | package | |
安裝 | install | |
釋出 | deploy | |
站點生命週期 |
6
專案物件模型pom和依賴管理模型dependency
1)專案物件模型pom
包含專案自身資訊,專案執行依賴的jar包,專案執行環境資訊(JDK,tomcat資訊)
2)依賴管理模型dependency
包含公司組織名稱、專案名、版本號
<dependency>
<!-- junit的專案名稱 -->
<groupId>junit</groupId>
<!-- junit的模組名稱 -->
<artifactId>junit</artifactId>
<!-- junit版本 -->
<version>4.9</version>
<!-- 依賴範圍:單元測試時使用junit -->
<scope>test</scope>
</dependency>
7
idea下使用maven
1)配置整合環境
在settins搜尋maven,將maven的解壓目錄配置上即可
2)建立maven專案
(1)新建專案,選中maven,點選下一步,填寫專案資訊,在點選下一步至finish
(2)建立專案後,裡面缺少的標準目錄需要自行新增,並標記為標準目錄
(3)webapp的目錄,需要進行靜態標記。project structure->modules->web->web resource dirictory中加入包的目錄
注意
建立web專案,勾選create from archetype後,選中org.apache.maven.archetpes.maven-archetype-webapp
3)專案中匯入jar包
在pom.xml中配置
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
注意
如果匯入jar包後,專案中仍無法識別匯入的包,可能與maven版本有關係
4)設定包的作用範圍
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--匯入的servlet和jsp的包要配置範圍provided-->
這裡的scope裡包含的就是包的作用範圍
依賴範圍 | 編譯 | 測試 | 執行 | 案例 |
---|---|---|---|---|
compile | 影響 | 影響 | 影響 | spring-core |
test | 影響 | junit | ||
provided | 影響 | 影響 | servlet-api | |
runtime | 影響 | 影響 | jdbc驅動 | |
system | 影響 | 影響 | 本地的maven庫之外的庫 |
5)配置執行環境
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path> <!--專案訪問路徑。當前配置的訪問是localhost:9090/, 如果配置是/aa,則訪問路徑為localhost:9090/aa -->
<port>9090</port>
<uriEncoding>UTF-8</uriEncoding><!-- 非必需項 -->
</configuration>
</plugin>
</plugins>
</build>
執行時指向tomcat7:run,不然會報錯