1. JDBC

1.1 基本使用

JavaWeb - 图1

概念:Java DataBase Connectivity Java 数据库连接

JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

导入驱动jar包:mysql-connector-java-5.1.37-bin.jar

将文件复制到项目包libs下,然后右击libs —> Add As Library

类详解:

  1. DriverManager:驱动管理对象

    1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
      static void registerDriver(Driver driver) :注册与给定的驱动程序DriverManager
      写代码使用: Class.forName("com.mysql.jdbc.Driver");
      通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
      1. static {
      2. try {
      3. java.sql.DriverManager.registerDriver(new Driver());
      4. } catch (SQLException E) {
      5. throw new RuntimeException("Can't register driver!");
      6. }
      7. }


注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。

  1. 获取数据库连接:
    方法:static Connection getConnection(String url, String user, String password)
    参数:url:指定连接的路径, user:用户名password:密码
    语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
    例子:jdbc:mysql://localhost:3306/db3
    细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///db3
  1. Connection:数据库连接对象

    1. 获取执行sql的对象

      • Statement createStatement()
      • PreparedStatement prepareStatement(String sql) 一般都使用这种方式去定义,更加安全,防止SQL注入
    2. 管理事务:为了对一套操作完整性的保证

      • 开启事务:setAutoCommit(boolean autoCommit)调用该方法设置参数为false,即开启事务,默认为true,表示开启自动commit(),使用位置为执行SQL
      • 提交事务:commit()使用位置在执行完所有SQL
      • 回滚事务:rollback()使用位置在抓取的异常处,抓一个Exception较大的异常类防止因其他异常产生
  2. Statement:执行SQL对象

  3. PreparedStatement:执行sql的对象

    • SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
      输入用户随便,输入密码:a’ or ‘a’ = ‘a
      sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
      为了解决注入问题,在定义SQL语句是通过?来对变量占位:select * from user where username = ? and password = ?
      然后通过preparedStatement.setXxx(位置几, 参数)设置参数pstmt1.setDouble(1,500);位置编号从1开始

    • int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
      返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。

    • ResultSet executeQuery(String sql):执行DQL(select)语句

  4. ResultSet:查询SQL后执行的结果集

    • boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true

    • getXxx(参数):获取数据

    • Xxx:代表数据类型 如: int getInt(), String getString()

    • 参数:

      1. int:代表列的编号,从1开始 如:getString(1)
      2. String:代表列名称。 如: getDouble("balance")
  1. // 基本的通过JDBC接口连接数据库,更新数据库
  2. Connection con = null; // 定义在try外部方便后面的finally释放资源
  3. Statement stam = null;
  4. try{
  5. // 1. 注册程序
  6. Class.forName("com.mysql.jdbc.Driver");
  7. // 2. 连接数据库
  8. // 如果本地默认连接可以写成 jdbc:mysql:///test
  9. con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1598");
  10. // 3. 创建SQL语句
  11. String s = "update student set sname = '孙七' where sid = 13";
  12. // 4. 创建SQL对象
  13. stam = con.createStatement();
  14. // 5. 执行SQL
  15. // stam.executeUpdate(s)执行SQL语句后,返回修改的行数,如果大于0则产生了修改
  16. int count = stam.executeUpdate(s);
  17. // 6. 处理结果
  18. if(count > 0) System.out.println("successd!!!");
  19. else System.out.println("failed!!!");
  20. }catch (ClassNotFoundException e){
  21. e.printStackTrace();
  22. } catch (SQLException e) {
  23. e.printStackTrace();
  24. }finally {
  25. // 7. 释放资源,关闭连接
  26. // 避免空指针异常
  27. if(stam != null) {
  28. try {
  29. stam.close();
  30. } catch (SQLException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. if(con != null){
  35. try{
  36. con.close();
  37. }catch(SQLException e){
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  1. // 对数据库访问用户和年龄,将获取的数据封装成Student类的列表,供后续使用
  2. // 1. 先定义学生类,有姓名和年龄属性
  3. public class Student {
  4. private String sname;
  5. private Date sage;
  6. public String getSname() { return sname; }
  7. public void setSname(String sname) { this.sname = sname;}
  8. .....
  9. }
  10. // 2. 定义JDBCDemo3类,一个main方法来使用getEmp()方法返回的学生列表
  11. public static void main(String[] args) {
  12. List<Student> ls = new JDBCDemo3().getEmp();
  13. for(Student e: ls){
  14. // System.out.println(e.getSname() +"---" +e.getSage());
  15. System.out.println(e);
  16. }
  17. }
  18. // 返回学生类的列表
  19. public List<Student> getEmp(){
  20. Connection con = null;
  21. Statement stat = null;
  22. ResultSet rs = null;
  23. List<Student> ls = null;
  24. try {
  25. Class.forName("com.mysql.jdbc.Driver");
  26. con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1598");
  27. // stat.executeQuery()查询SQL语句,返回结果集ResultSet,通过next()指针访问行,通过getString("列名称"),或者getString(1)第一列,很特殊第一列不是从0开始而是1。获取该列的字符串,如果该列为Int类型则getInt("列名称")
  28. String sql = "select * from student where sid = ? ";
  29. pstat = con.prepareStatement(sql);
  30. pstat.setString(1, "01");
  31. rs = pstat.executeQuery(); // 这里面不用再加SQL语句,已经加载了
  32. Student stu = null;
  33. ls = new ArrayList<Student>();
  34. while(rs.next()){
  35. stu = new Student();
  36. // 将查询的结果给Student对象,并生成Student的列表,最后返回该列表
  37. String sname = rs.getString("sname");
  38. Date sage = rs.getDate("sage");
  39. stu.setSage(sage);
  40. stu.setSname(sname);
  41. ls.add(stu);
  42. }
  43. } catch (ClassNotFoundException e) {
  44. e.printStackTrace();
  45. } catch (SQLException e) {
  46. e.printStackTrace();
  47. }finally {
  48. try {
  49. assert rs != null;
  50. rs.close();
  51. } catch (SQLException e) {
  52. e.printStackTrace();
  53. }
  54. try {
  55. assert stat != null;
  56. stat.close();
  57. } catch (SQLException e) {
  58. e.printStackTrace();
  59. }
  60. try {
  61. assert con != null;
  62. con.close();
  63. } catch (SQLException e) {
  64. e.printStackTrace();
  65. }
  66. }
  67. return ls;
  68. }

1.2 通过JDBC工具类:JDBCUtils

为了简化书写,自己写一个工具类将一些重复性较强的代码抽取为一个类

通过读取配置文件来方便以后对数据库的一些修改,而且Java代码还不需要变动,只需要修改配置文件即可

src包下新建jdbc.properties文件

  1. url=jdbc:mysql://localhost:3306/test
  2. user=root
  3. passwd=root
  4. driver=com.mysql.jdbc.Driver
  1. public class JDBCUtils2 {
  2. private static String url;
  3. private static String user;
  4. private static String passwd;
  5. private static String driver;
  6. static{
  7. try {
  8. Properties pro = new Properties();
  9. // pro.load(new FileReader("idea_demo\\src\\jdbc.properties"));
  10. // 自动寻找加载,不会因为后面项目迁移而改动代码
  11. pro.load( JDBCUtils.class.getClassLoader().getResource("jdbc.properties") );
  12. url = pro.getProperty("url");
  13. user = pro.getProperty("user");
  14. passwd = pro.getProperty("passwd");
  15. driver = pro.getProperty("driver");
  16. Class.forName(driver);
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. } catch (ClassNotFoundException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. // 连接数据库
  24. public static Connection getConnect() throws SQLException {
  25. return DriverManager.getConnection(url, user, passwd);
  26. }
  27. // 关闭释放资源
  28. public static void close(Connection con, PreparedStatement pstat, ResultSet rs){
  29. if(rs != null){
  30. try {
  31. rs.close();
  32. } catch (SQLException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. if(pstat != null){
  37. try{
  38. pstat.close();
  39. }catch (SQLException e){
  40. e.printStackTrace();
  41. }
  42. }
  43. if( con != null){
  44. try{
  45. con.close();
  46. }catch(SQLException e){
  47. e.printStackTrace();
  48. }
  49. }
  50. }
  51. public static void close(Connection con, PreparedStatement pstat){
  52. close(con, pstat, null); // 当只有更新数据等没有ResultSet返回值时
  53. }
  54. }
  1. Connection con = null;
  2. PreparedStatement pstat1 = null;
  3. PreparedStatement pstat2 = null;
  4. try {
  5. con = JDBCUtils2.getConnect(); // 使用自定义的类连接
  6. // 开启手动提交
  7. con.setAutoCommit(false);
  8. String sql1 = "update users set user = ? where id = ? ";
  9. String sql2 = "update users set user = ? where id = ? ";
  10. pstat1 = con.prepareStatement(sql1);
  11. pstat2 = con.prepareStatement(sql2);
  12. pstat1.setString(1, "zhang");
  13. pstat1.setInt(2, 1);
  14. pstat2.setString(1,"ahang");
  15. pstat2.setInt(2,3);
  16. int i = pstat1.executeUpdate();
  17. int s = 3/0;
  18. int j = pstat2.executeUpdate();
  19. if(i>0 && j>0) System.out.println("successd");
  20. else System.out.println("failed");
  21. // 成功执行后提交
  22. con.commit();
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. //事务回滚
  26. try {
  27. if(conn != null) {
  28. conn.rollback();
  29. }
  30. } finally {
  31. JDBCUtils2.close(con, pstat1, pstat2); //使用自定义的类关闭, 这里可以再JDBCUtils中再加一个close
  32. }
  33. }

1.3 数据库连接池

  • 概念:其实就是一个容器(集合),存放数据库连接的容器。
    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

  • 优点:节约资源、访问高效

  • 实现:

    • 标准接口(自己定义实现):DataSourcegetConnection()获取连接和Connection.close()归还连接而不是关闭连接
    • 由数据库厂商实现:C3P0, Druid
  • C3P0实现

    • 导入jar包:c3p0-0.9.5.2.jarmchange-commons-java-0.2.12.jar,以及数据库驱动MySQL包,并add as library

    • 定义配置文件:c3p0.properties或者 c3p0-config.xml放在src

      1. <c3p0-config>
      2. <!-- 使用默认的配置读取连接池对象 -->
      3. <default-config>
      4. <!-- 连接参数 -->
      5. <property name="driverClass">com.mysql.jdbc.Driver</property>
      6. <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
      7. <property name="user">root</property>
      8. <property name="password">root</property>
      9. <!-- 连接池参数 -->
      10. <!--初始化申请的连接数量-->
      11. <property name="initialPoolSize">5</property>
      12. <!--最大的连接数量-->
      13. <property name="maxPoolSize">10</property>
      14. <!--超时时间-->
      15. <property name="checkoutTimeout">3000</property>
      16. </default-config>
    1. ComboPooledDataSource ds = new ComboPooledDataSource(); // 资源池连接对象
    2. for (int i = 0; i < 11; i++) {
    3. Connection con = ds.getConnection(); // 获取连接
    4. System.out.println(i + ":" + con);
    5. if(i == 5) con.close(); // 归还连接
    6. }
  • Druid实现

    • 导入jar包 druid-1.0.9.jar

    • 定义配置文件druid.properties

      1. driverClassName=com.mysql.jdbc.Driver
      2. url=jdbc:mysql:///test
      3. username=root
      4. password=root
      5. # 初始化连接数量
      6. initialSize=5
      7. # 最大连接数
      8. maxActive=10
      9. # 最大等待时间
      10. maxWait=3000
  • 实现代码

    1. // 先定义一个工具类,供Druid方便使用
    2. public class DruidUtils {
    3. private static DataSource ds;
    4. static{
    5. Properties pro = new Properties();
    6. try {
    7. // 加载配置文件
    8. pro.load( DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties") );
    9. // 创建资源池
    10. ds = DruidDataSourceFactory.createDataSource(pro);
    11. } catch (IOException e) {
    12. e.printStackTrace();
    13. } catch (Exception e) {
    14. e.printStackTrace();
    15. }
    16. }
    17. public static Connection getConnect() throws SQLException {
    18. return ds.getConnection();
    19. }
    20. // 归还连接
    21. public static void close(Connection con, PreparedStatement pstat, ResultSet rs){
    22. if(con != null){
    23. try {
    24. con.close();
    25. } catch (SQLException e) {
    26. e.printStackTrace();
    27. }
    28. }
    29. if(pstat != null){
    30. try {
    31. pstat.close();
    32. } catch (SQLException e) {
    33. e.printStackTrace();
    34. }
    35. }
    36. if(rs != null){
    37. try {
    38. rs.close();
    39. } catch (SQLException e) {
    40. e.printStackTrace();
    41. }
    42. }
    43. }
    44. public static void close(Connection con, PreparedStatement pstat){
    45. close(con, pstat, null);
    46. }
    47. }
  1. Connection con = null;
  2. PreparedStatement pstat = null;
  3. try {
  4. // 使用自定义的工具类获取连接
  5. con = DruidUtils.getConnect();
  6. String sql = "update users set user = 'ahang' where id = 1";
  7. pstat = con.prepareStatement(sql);
  8. int count = pstat.executeUpdate();
  9. if(count > 0) System.out.println("succeed");
  10. } catch (SQLException e) {
  11. e.printStackTrace();
  12. } finally {
  13. // 使用自定义的工具类归还资源
  14. DruidUtils.close(con,pstat);
  15. }

1.4 Spring JDBC

  • Spring框架对JDBC的简单封装。提供了一个JDBC Template对象简化JDBC的开发

  • 导入jar包:spring-beans-5.0.0.RELEASE.jar,spring-core-5.0.0.RELEASE.jar,spring-jdbc-5.0.0.RELEASE.jar,spring-tx-5.0.0.RELEASE.jar,commons-logging-1.2.jar

  • 创建JdbcTemplate对象。依赖于数据源DataSource

  • JdbcTemplate template = new JdbcTemplate(ds);

  • 调用JdbcTemplate的方法来完成CRUD的操作 | 方法 | 用途 | | —- | —- | | update() | 执行DML语句。增、删、改语句 | | queryForMap() | 查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合,注意:这个方法查询的结果集长度只能是1 | | queryForList() | 查询结果将结果集封装为list集合,注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中 | | query() | 查询结果,将结果封装为JavaBean对象,query的参数:RowMapper一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装,new BeanPropertyRowMapper<类型>(类型.class), 对于类型为对象时,如果出现查询的结果有null类型数据,在定义对象的变量时使用引用数据类型Integer,Double而不是int,double基本数据类型 | | queryForObject | 查询结果,将结果封装为对象,一般用于聚合函数的查询 |

  1. public class SpringDemo1 {
  2. private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource());
  3. // 使用template.update来更新
  4. @Test
  5. public void test1(){
  6. String sql = "update users set passwd = 'root' where id = 2";
  7. int count = template.update(sql);
  8. System.out.println(count);
  9. }
  10. // 使用template.update来插入
  11. @Test
  12. public void test2(){
  13. String sql = "insert into users(user, passwd) values(?,?)";
  14. int count = template.update(sql,"root1", "root");
  15. System.out.println(count);
  16. }
  17. // 使用template.update来删除
  18. @Test
  19. public void test3(){
  20. String sql = "delete from users where id = ?";
  21. int count = template.update(sql, 4);
  22. System.out.println(count);
  23. }
  24. // 使用template.queryForMap来查询一行数据
  25. @Test
  26. public void test4(){
  27. String sql = "select * from users where id = ?;";
  28. Map<String, Object> map = template.queryForMap(sql, 3);
  29. System.out.println(map); // {user=zhang, passwd=root, id=3}
  30. }
  31. // 使用template.queryForList来查询多行数据,每行数据以map存在
  32. @Test
  33. public void test5(){
  34. String sql = "select * from users";
  35. List<Map<String, Object>> maps = template.queryForList(sql);
  36. for(Map<String, Object> e: maps){
  37. System.out.println(e);
  38. //{user=ahang, passwd=root, id=1}, {user=root, passwd=root, id=2}
  39. }
  40. }
  41. // 使用template.query来查询多行数据,每行数据以对象形式存在
  42. @Test
  43. public void test6(){
  44. String sql = "select * from student";
  45. List<Student> list = template.query(sql, new BeanPropertyRowMapper<Student>(Student.class));
  46. for(Student e: list){
  47. System.out.println(e);
  48. }
  49. }
  50. // 使用template.queryForObject将结果封装为对象
  51. @Test
  52. public void test7(){
  53. String sql = "select count(*) from student";
  54. Long count = template.queryForObject(sql, Long.class);
  55. System.out.println(count);
  56. }
  57. }

2. HTML

3. CSS

4. JavaScript

  • 概念:一门客户端脚本语言

    • 运行在客户端浏览器中的。每一个浏览器都有JavaScript的解析引擎
    • 脚本语言:不需要编译,直接就可以被浏览器解析执行了
  • 功能:可以来增强用户和html页面的交互过程,可以来控制html元素,让页面有一些动态的效果,增强用户的体验。

JavaScript = ECMAScript + JavaScript自己特有的东西(BOM+DOM)

4.1 基本语法

4.1.1 使用位置

内联<script> 语句 </script>

外联<script src="myScript.js"></script>

  1. <html lang="en">
  2. <head>
  3. <meta charset="UTF-8">
  4. <title>Title</title>
  5. <script>alert(a4)</script> // 可以放在任意位置,但是放在<body>前会先执行脚本后输出HTML页面
  6. </head>
  7. <script>alert(5)</script>
  8. <body>
  9. <script>alert(6)</script> // 放在<body>后会先输出HTML页面后执行脚本
  10. </body>
  11. <script>alert(7)</script>
  12. </html>

4.1.2 输出

alert(abc)弹出警告框abc

document.write(10)页面输出文字

  1. <body>
  2. <h2>我的第一张网页</h2>
  3. <p>我的第一个段落。</p>
  4. <p id="demo"></p> // 在body内通过id定位输出内容, 11
  5. <script>
  6. document.getElementById("demo").innerHTML = 5 + 6;
  7. </script>
  8. </body>

4.1.3 变量

  • 原始数据类型(基本数据类型):

    • number:数字。 整数/小数/

      • NaN(not a number 一个不是数字的数字类型),用来表示非法的数字,
      • var x = 100 / "String"此时x表示NaN
      • var x = 100 / "10"此时x = 10,自动转化类型后相除
      • NaN做运算的结果也为NaNa = NaN; b = 10; c = 10 + NaN;
      • 通过toFixed(i)精确小数点个数,x = 9.656; x.toFixed(4);// 返回 9.6560
    • string:字符串。 字符串 “abc” “a” ‘abc’,用单引号''和双引号""相同

      • 获取字符串长度str.length
      • 特殊字符通过加\如:\'\",\\
      • 转义字符:\r回车,\t水平制表符\v垂直制表符
      • 当写一行字符串过长产生自动换行,为了方便书写,建议写出"aaaa bbb" 换行 + "ccc ddd"
    • boolean: truefalse
    • null:一个对象为空的占位符
    • undefined:未定义。如果一个变量没有给初始化值,则会被默认赋值为undefined
  • 引用数据类型:对象var x = {firstName:"Bill", lastName:"Gates"};

  • 数组:var cars = ["Porsche", "Volvo", "BMW"];

  • 在开辟变量存储空间时,不定义空间将来的存储数据类型,可以存放任意类型的数据。

    • var 变量名 = 初始化值;

    • typeof(变量):获取变量的类型。

4.1.4 运算符

  • 一元运算符:

    • ++,--自增自减;

    • +,-正负号。

        1. var b1 = +"10"; // 1. String转化为number,通过给字符前加一个+
        2. var b2 = +"20";
        3. var b3 = b1+b2; // 2. 结果为两个number相加 30
        4. var bb1 = +"10";
        5. var bb2 = "20";
        6. var bb3 = bb1 + bb2; // String和number相加结果为"1020"字符串,此时+号表示连接符在两个字符串之间
        7. var c1 = false;
        8. var c2 = +true; // boolean转化为number类型:false = 0, true = 1;
        9. document.write(c1+c2); // boolean + number = number : 0+1=1结果为 1
  • 算数运算符:+,-,*,/

  • 赋值运算符:=,+=,-=

  • 比较运算符:>,<,>=,<=,==,===全等于。。。

    • 同类型:直接比较,字符串按照字典序逐个字符比较

    • 类型不同:先类型转换后比较

        1. var d1 = "123";
        2. var d2 = 123;
        3. document.write(d1 == d2,"<br>"); // 不同类型,先转换同类型后比较相同
        4. document.write(d1 === d2,"<br>"); // === 全等于,不同类型直接判定为false
  • 逻辑运算符:&&,||,!

    • 其他类型转boolean类型:

      • number: 0NaNfalse,其余为true
      • string:除了(””)空字符其余为true
      • nullundefined: false
      • 对象:true
  1. var f1 = !!"";
  2. var f2 = !!new Date();
  3. document.write(f1,"<br>"); // false
  4. document.write(f2, "<br>"); // true
  • 三元运算符:var a = b > c ? b : c

4.1.5 JS不同于Java语法

  1. function f() {
  2. s3 = 30 // 1. 可以省略结束分号; 2. 在函数内,如果不加var 声明则声明的是全局变量,函数外部也可以使用
  3. var s4 = 40; // 函数内的局部变量之能在函数内使用
  4. document.write(s3);
  5. }
  6. f()
  7. document.write(s3);
  8. document.write(s4); // 该条语句错误,不能使用函数内局部变量
  9. switch (a) { // 这里面的 a 可以为任意类型变量
  10. case 1: break;
  11. case "abc":break;
  12. case true:break;
  13. case null:break;
  14. case undefined: break;
  15. default:break;
  16. }

4.1.6 对象

一个拥有属性和方法的变量 ==》 对象

  1. var obj = {
  2. firstName : "Ahang", // 属性
  3. lastName : "Haha",
  4. fullName : function(){ // 方法
  5. return this.firstName + this.lastName;
  6. }
  7. };
  8. document.write("<br>", obj.firstName); // 对象.属性 "Ahang"
  9. document.write("<br>", obj.fullName()); // 对象.方法() 得到 "AhangHaha"
  10. document.write("<br>", obj.fullName); // 对象.方法 输出function(){ return this.firstName + this.lastName; }

new一个对象var date = new Date()

4.1.7 事件

事件 描述
onchange HTML 元素已被改变
onclick 用户点击了 HTML 元素
onmouseover 用户把鼠标移动到 HTML 元素上
onmouseout 用户把鼠标移开 HTML 元素
onkeydown 用户按下键盘按键
onload 浏览器已经完成页面加载
  1. // 通过点击触发事件
  2. <button onclick="document.getElementById('time1').innerHTML = Date()">点击获取时间</button>
  3. <p id="time1"></p>
  4. // 通过点击调用函数
  5. <button onclick="getDate()">点击获取时间</button>
  6. <script>
  7. function getDate() {
  8. document.getElementById("time2").innerHTML = Date();
  9. }
  10. </script>
  11. <p id="time2"></p>
  12. <button onmouseover="this.innerHTML = Date()">移动鼠标到该点上获取时间</button>

4.1.8 字符串详解

  1. var str = "HELLO WORLD";
  2. str[0] = "A"; //可以访问,但不能修改。 不产生错误,但不会工作
  3. str[0]; // 返回 H
  4. // 创建String对象,通过全局函数String()
  5. new String(s);
  6. var str = String(s);
  7. // 转换字符串为数值,通过全局函数parseInt()
  8. var i = parseInt("10");
  9. var f = parseFloat("10.5");

String 对象方法

方法 描述
bold() 使用粗体显示字符串。
charAt() 返回在指定位置的字符。
charCodeAt() 返回在指定的位置的字符的 Unicode 编码。
concat() 连接字符串。
fontcolor() 使用指定的颜色来显示字符串。
fontsize() 使用指定的尺寸来显示字符串。
indexOf() 检索字符串。
italics() 使用斜体显示字符串。
lastIndexOf() 从后向前搜索字符串。
link() 将字符串显示为链接。
localeCompare() 用本地特定的顺序来比较两个字符串。
match() 找到一个或多个正则表达式的匹配。
replace() 替换与正则表达式匹配的子串。
search() 检索与正则表达式相匹配的值。
slice() 提取字符串的片断,并在新的字符串中返回被提取的部分。
split() 把字符串分割为字符串数组。
strike() 使用删除线来显示字符串。
sub() 把字符串显示为下标。
substr() 从起始索引号提取字符串中指定数目的字符。
substring() 提取字符串中两个指定的索引号之间的字符。
sup() 把字符串显示为上标。
toLowerCase() 把字符串转换为小写。
toUpperCase() 把字符串转换为大写。
toString() 返回字符串。
valueOf() 返回某个字符串对象的原始值。

4.1.9 数组详解

  1. var arr = ["10", 20, true, null, f(), "abc"]; // 可以存储多个不同类型的变量及函数
  2. for(var i = 0; i < arr.length; i++){
  3. document.write("<br>")
  4. document.write(arr[i]);
  5. document.write(" : " + typeof(arr[i]));
  6. }

数组长度:arr.length

Array 对象方法

方法 描述
concat() 连接两个或更多的数组,并返回结果。arr1.concat(arr2, arr3,...);
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop() 删除并返回数组的最后一个元素fruits.pop();
push() 向数组的末尾添加一个或更多元素,并返回新的长度。fruits.push("Kiwi");
reverse() 颠倒数组中元素的顺序。可以先fruits.sort();fruits.reverse();实现降序
shift() pop对应,删除并返回数组的第一个元素fruits.shift();
slice() 从某个已有的数组返回选定的元素,fruits.slice(1);从第二个元素开始到最后的数组;fruits.slice(1, 3);返回从下标为1到下标为3(不包含3)的数组
sort() 对数组的元素进行排序fruits.sort();,里面可以放置函数以操控排序:points.sort(function(a, b){return b - a});
splice() 删除元素,并向数组添加新元素。var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 0, "Lemon", "Kiwi");第一个参数(2)定义了应添加新元素的位置(拼接)。第二个参数(0)定义应删除多少元素。其余参数(“Lemon”,“Kiwi”)定义要添加的新元素。返回的数组为Banana,Orange,Lemon,Kiwi,Apple,Mango
toString() 把数组转换为字符串,并返回结果。fruits.toString();返回"a,b,c,d"以逗号分隔的字符串
toLocaleString() 把数组转换为本地数组,并返回结果。
unshift() push对应,向数组的开头添加一个或更多元素,并返回新的长度。fruits.unshift("Lemon");
valueOf() 返回数组对象的原始值

4.1.10 数学

使用方式:Math.abs(-10)

Math 对象方法

方法 描述
abs(x) 返回 x 的绝对值
acos(x) 返回 x 的反余弦值,以弧度计
asin(x) 返回 x 的反正弦值,以弧度计
atan(x) 以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
atan2(y,x) 返回从 x 轴到点 (x,y) 的角度
ceil(x) 对 x 进行上舍入
cos(x) 返回 x 的余弦
exp(x) 返回 Ex 的值
floor(x) 对 x 进行下舍入
log(x) 返回 x 的自然对数(底为e)
max(x,y,z,…,n) 返回最高值
min(x,y,z,…,n) 返回最低值
pow(x,y) 返回 x 的 y 次幂
random() 返回 0 ~ 1 之间的随机数
round(x) 把 x 四舍五入为最接近的整数
sin(x) 返回 x(x 以角度计)的正弦
sqrt(x) 返回 x 的平方根
tan(x) 返回角的正切

4.1.11 正则表达式

语法: /表达式/修饰符 ==》 /haha/ihaha匹配,且由于修饰符为i对大小写忽略

使用:str.search(/w3school/i);,str.replace(/microsoft/i, "W3School");

修饰符 描述
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。

RegExp 对象方法

方法 描述
compile 编译正则表达式。
exec 检索字符串中指定的值。返回找到的值,并确定其位置。/e/.exec("The best things in life are free!");
test 检索字符串中指定的值。返回 true 或 false。/e/.test("The best things in life are free!");

支持正则表达式的 String 对象的方法

方法 描述
search 检索与正则表达式相匹配的值。str.search(regexp)
match 找到一个或多个正则表达式的匹配。str.match(regexp)
replace 替换与正则表达式匹配的子串。str.match(regexp,string)或者替换的字符串可以通过已匹配的字符串相比较$1...
split 把字符串分割为字符串数组。str.split(regexp)或者加上只显示前几个字符:str.split(regexp, 3)

5. MAVEN安装使用

5.1 安装

  1. 下载安装包后解压缩至无中文路径的文件夹中
  2. 设置系统变量:MAVEN_HOMED:\develop\apache-maven-3.5.2
  3. 设置PATH添加%MAVEN_HOME%\bin
  4. 通过cmd输入mvn -v测试

5.2 使用

  • 对于第一次使用创建项目,然后在项目里面创建多个module模块
  • 不同的模块下pom.xml之间默认相互独立,项目下的pom.xml和模块下的pom.xml默认时相互独立的,也就是说子模块下的依赖包和主项目下的依赖包默认相互独立,不共享
  • 子模块在创建时IDE中选择继承自主项目,则子模块下的会显示有主项目的jar包;也可以选择继承另一个子模块,则会有另一个子模块下的jar包
  • 子模块可以自主选择继承的父模块
  1. <!--此处设置父模块的信息:id和组id-->
  2. <parent>
  3. <artifactId>MyBatis</artifactId>
  4. <groupId>MyBatis</groupId>
  5. <version>1.0-SNAPSHOT</version>
  6. </parent>
  7. <modelVersion>4.0.0</modelVersion>
  8. <!--此处设置本模块的Id-->
  9. <artifactId>MyBatis_3</artifactId>

新建项目后—新建模块—-为了后面的JavaWeb,使用现成的webapp去建立

JavaWeb - 图2

5.3 Tomcat安装使用

下载:http://tomcat.apache.org/

安装:直接解压缩文件即可

使用:通过bin\startup.bat,浏览器通过http://localhost:8080即可访问,关闭:bin/shutdown.bat

部署项目的方式:

  1. 1. 直接将项目放到`webapps`目录下即可。
  2. * /hello:项目的访问路径-->虚拟目录
  3. * 简化部署:将项目打成一个war包,再将war包放置到webapps目录下。
  4. * war包会自动解压缩
  1. 配置conf/server.xml文件,在标签体中配置
    `docBase:项目存放的路径
    path:虚拟目录

  2. 推荐:在conf\Catalina\localhost创建任意名称的xml文件。
    在文件中编写<Context docBase="D:\hello" />
    虚拟目录:xml文件的名称

5.4 配置Tomcat

新建一个maven的module后配置TomCat服务器

JavaWeb - 图3

JavaWeb - 图4

JavaWeb - 图5

JavaWeb - 图6

JavaWeb - 图7

如果没有war包需要手动打包一个教程:手动war包

  1. 6. Servlet使用

6.1 基本概念

Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。

定义一个类实现servlet接口:public class ServletDemo1 implements Servlet

然后在web.xml中配置:

  1. <!--配置Servlet -->
  2. <servlet>
  3. <servlet-name>demo1</servlet-name>
  4. <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
  5. </servlet>
  6. <servlet-mapping>
  7. <servlet-name>demo1</servlet-name>
  8. <url-pattern>/demo1</url-pattern>
  9. </servlet-mapping>

执行原理

  1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径

  2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。

  3. 如果有,则在找到对应的<servlet-class>全类名

  4. tomcat会将字节码文件加载进内存,并且创建其对象

  5. 调用其方法
    Servlet 3.0中无需web.xml,通过注解配置

    1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
    2. 定义一个类,实现Servlet接口
    3. 复写方法
    4. 在类上使用@WebServlet注解,进行配置

      • @WebServlet(“资源路径”)

Servlet中的生命周期方法:

  1. 被创建:执行init方法,只执行一次
    Servlet什么时候被创建?
    默认情况下,第一次被访问时,Servlet被创建
    可以配置执行Servlet的创建时机。
    <servlet>标签下配置

    1. 第一次被访问时,创建<load-on-startup>的值为负数
    2. 在服务器启动时,创建<load-on-startup>的值为0或正整数
      Servletinit方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
      多个用户同时访问时,可能存在线程安全问题
      解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值
  2. 提供服务:执行service方法,执行多次
    每次访问Servlet时,Service方法都会被调用一次。

  3. 被销毁:执行destroy方法,只执行一次
    Servlet被销毁时执行。服务器关闭时,Servlet被销毁
    只有服务器正常关闭时,才会执行destroy方法。
    destroy方法在Servlet被销毁之前执行,一般用于释放资源
  1. // 在项目的src下创建Java文件,
  2. @WebServlet("/demo")
  3. // 通过WebServlet("资源路径")注解配置,给该Java资源起的名称,也叫做网页访问的资源路径,在web上通过http://localhost:8080/demo访问该资源
  4. public class servlet_demo1 implements Servlet {
  5. @Override // 初始化,默认在第一次访问时使用
  6. public void init(ServletConfig servletConfig) throws ServletException {System.out.println("init...");}
  7. @Override
  8. public ServletConfig getServletConfig() {return null;}
  9. @Override // 每次web调用该服务,便执行该方法
  10. public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
  11. System.out.println("service...");
  12. }
  13. @Override
  14. public String getServletInfo() {return null;}
  15. @Override // 最后正常结束时销毁
  16. public void destroy() {System.out.println("destroy...");}
  17. }

6.2 maven中使用servlet具体使用步骤:

6.2.1 构建Maven项目

删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven主工程;

JavaWeb - 图8

关于Maven父子工程的理解:

父项目中会有

  1. <modules>
  2. <module>servlet-01</module>
  3. </modules>

子项目会有 (local history ——>accept)

  1. <parent>
  2. <artifactId>javaweb-02-servlet</artifactId>
  3. <groupId>com.kuang</groupId>
  4. <version>1.0-SNAPSHOT</version>
  5. </parent>

父项目中的jar包子项目可以直接使用

6.2.2 Maven环境优化

  • 修改web.xml为最新的
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  5. http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  6. version="4.0"
  7. metadata-complete="true">
  8. </web-app>
  • mavenpom文件中添加依赖,为了后面使用jspservlet作准备

    1. <dependencies>
    2. <dependency>
    3. <groupId>javax.servlet</groupId>
    4. <artifactId>javax.servlet-api</artifactId>
    5. <version>4.0.1</version>
    6. </dependency>
    7. <dependency>
    8. <groupId>javax.servlet.jsp</groupId>
    9. <artifactId>jsp-api</artifactId>
    10. <version>2.0</version>
    11. </dependency>
    12. </dependencies>
  • 在maven的pom中添加资源路径,防止导入资源失败
  1. <build>
  2. <resources>
  3. <resource>
  4. <directory>src/main/resources</directory>
  5. <includes>
  6. <include>**/*.properties</include>
  7. <include>**/*.xml</include>
  8. </includes>
  9. <filtering>true</filtering>
  10. </resource>
  11. <resource>
  12. <directory>src/main/java</directory>
  13. <includes>
  14. <include>**/*.properties</include>
  15. <include>**/*.xml</include>
  16. </includes>
  17. <filtering>true</filtering>
  18. </resource>
  19. </resources>
  20. </build>
  • 将maven的结构搭建完整

JavaWeb - 图9

6.2.3 编写一个Servlet程序

编写一个普通类 HelloServlet

实现Servlet接口,这里我们直接继承HttpServlet

JavaWeb - 图10

重写方法(ctrl+o 快捷键)

  1. package com.kuang.servlet;
  2. public class HelloServlet extends HttpServlet {
  3. //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
  4. @Override
  5. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  6. //ServletOutputStream outputStream = resp.getOutputStream();
  7. PrintWriter writer = resp.getWriter(); //响应流
  8. writer.print("Hello,Serlvet");
  9. }
  10. @Override
  11. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  12. doGet(req, resp);
  13. }
  14. }

6.2.4 编写Servlet的映射

为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器(web.xml),所以我们需要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;

  1. <!--注册Servlet-->
  2. <servlet>
  3. <servlet-name>hello</servlet-name>
  4. <servlet-class>com.ylw.servlet.HelloServlet</servlet-class>
  5. </servlet>
  6. <!--Servlet的请求路径,上面的name和下面的name要一样-->
  7. <servlet-mapping>
  8. <servlet-name>hello</servlet-name>
  9. <url-pattern>/hello</url-pattern>
  10. </servlet-mapping>

6.2.5 配置Tomcat

详见 5.4

6.2.6 启动测试

详见6.4

JavaWeb - 图11

6.3 web.xml的配置mapper问题

  1. 一个Servlet可以指定一个映射路径
  1. <servlet-mapping>
  2. <servlet-name>hello</servlet-name>
  3. <url-pattern>/hello</url-pattern>
  4. </servlet-mapping>

2.一个Servlet可以指定多个映射路径

  1. <servlet-mapping>
  2. <servlet-name>hello</servlet-name>
  3. <url-pattern>/hello</url-pattern>
  4. </servlet-mapping>
  5. <servlet-mapping>
  6. <servlet-name>hello</servlet-name>
  7. <url-pattern>/hello1</url-pattern>
  8. </servlet-mapping>
  1. 一个Servlet可以指定通用映射路径
  1. <servlet-mapping>
  2. <servlet-name>hello</servlet-name>
  3. <url-pattern>/hello/*</url-pattern>
  4. </servlet-mapping>
  1. 默认请求路径
  1. <!--默认请求路径-->
  2. <servlet-mapping>
  3. <servlet-name>hello</servlet-name>
  4. <url-pattern>/*</url-pattern>
  5. </servlet-mapping>
  1. 指定一些后缀或者前缀等等….注意:这时候 * 前面就不要加路径了
  1. <!--可以自定义后缀实现请求映射
  2. 注意点,*前面不能加项目映射的路径
  3. hello/sajdlkajda.qinjiang
  4. -->
  5. <servlet-mapping>
  6. <servlet-name>hello</servlet-name>
  7. <url-pattern>*.do</url-pattern>
  8. </servlet-mapping>
  1. 优先级问题 指定了固有的映射路径优先级最高,如果找不到就会走默认的(/*)处理请求;
  1. <!--404-->
  2. <servlet>
  3. <servlet-name>error</servlet-name>
  4. <servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
  5. </servlet>
  6. <servlet-mapping>
  7. <servlet-name>error</servlet-name>
  8. <url-pattern>/*</url-pattern>
  9. </servlet-mapping>
  1. 如果默认(/)和前后缀的(.do)同时存在时,会使用默认的

6.4 TomCat服务重启热加载

  • Tomcat服务重启 ——-> 加载新添加的Java文件和资源文件properties

  • 如果仅仅对Java文件进行了修改,而没有添加新的Java,可以通过热加载不重启服务

JavaWeb - 图12

  1. 首先使用debug

JavaWeb - 图13

  • 如果只对web.xml配置文件进行了修改,可以通过redeploy来更新

JavaWeb - 图14

  • 如果同时添加了新文件Java和修改了web.xml的话,需要重启服务,然后redeploy

6.5 ServletContext 常用方法

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
主要方法:

  1. ServletContext context = this.getServletContext();

1、共享数据

用到的主要方法:

  1. //设置
  2. context.setAttribute("参数名",参数值(可以是变量名));
  3. //获取,如果没有先set直接get会创建一个,并赋值为null
  4. context.getAttribute("参数名");

在这个Servlet中保存的数据,可以在另外一个servlet中拿到;
JavaWeb - 图15
HelloServlet 里设置上下文数据

  1. package com.kuang.servlet;
  2. public class HelloServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //this.getInitParameter() 初始化参数
  6. //this.getServletConfig() Servlet配置
  7. //this.getServletContext() Servlet上下文
  8. ServletContext context = this.getServletContext();
  9. String username = "ahang"; //数据
  10. context.setAttribute("username",username); //将一个数据保存在了ServletContext,数据的名字为username,值为变量username的值
  11. System.out.println("Hello,进入doGet");
  12. }
  13. }

GetServlet里获取上下文

  1. package com.kuang.servlet;
  2. public class GetServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. ServletContext context = this.getServletContext(); //这里获取的上下文就是HellServlet里设置的
  6. String username = (String) context.getAttribute("username"); //获取上下文中名为username的值
  7. resp.setContentType("text/html"); //设置文本类型
  8. resp.setCharacterEncoding("utf-8"); //设置编码
  9. resp.getWriter().print("用户名:"+username); //写在网页上
  10. }
  11. @Override
  12. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  13. doGet(req, resp); //注意这里改成doGet(req, resp),形成一个规范
  14. }
  15. }

web.xml里的注册

  1. <servlet>
  2. <servlet-name>hello</servlet-name>
  3. <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>hello</servlet-name>
  7. <url-pattern>/hello</url-pattern>
  8. </servlet-mapping>
  9. <servlet>
  10. <servlet-name>getContext</servlet-name>
  11. <servlet-class>com.kuang.servlet.GetServlet</servlet-class>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>getContext</servlet-name>
  15. <url-pattern>/getContext</url-pattern>
  16. </servlet-mapping>

重启Tomcat。
然后打开浏览器,先访问/hello进行设置,再访问/getContext进行获取
JavaWeb - 图16

JavaWeb - 图17

2、获取初始化参数

用到的主要方法:

  1. context.getInitParameter("参数名");

先在web.xml文件里配置初始参数

  1. <!--配置一些web应用的初始化参数-->
  2. <context-param>
  3. <param-name>url</param-name>
  4. <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
  5. </context-param>

写一个类获取

  1. package com.kuang.servlet;
  2. public class ServletDemo03 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. ServletContext context = this.getServletContext(); //这里获取的上下文就是HellServlet里设置的
  6. String url = context.getInitParameter("url"); //获取上web.xml文件中设置的参数<context-param>
  7. resp.getWriter().print(url); //写在网页上
  8. }
  9. @Override
  10. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  11. doGet(req, resp);//注意这里改成doGet(req, resp),形成一个规范
  12. }
  13. }

在web.xml里注册这个类

  1. <servlet>
  2. <servlet-name>gp</servlet-name>
  3. <servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>gp</servlet-name>
  7. <url-pattern>/gp</url-pattern>
  8. </servlet-mapping>

重启Tomcat。
然后打开浏览器,访问/gp进行获取
JavaWeb - 图18

3、请求转发

A要访问C中的资源:有两种方式

JavaWeb - 图19

用到的主要方法:

  1. context.getRequestDispatcher("转发路径").forward(req,resp);

转发代码

  1. package com.kuang.servlet;
  2. public class ServletDemo04 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. ServletContext context = this.getServletContext(); //这里获取的上下文就是HellServlet里设置的
  6. System.out.println("进入了Demo04");
  7. // RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //设置转发路径
  8. // requestDispatcher.forward(req,resp); //调用forward实现请求转发
  9. //合并上面两句
  10. context.getRequestDispatcher("/gp").forward(req,resp);
  11. }
  12. @Override
  13. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  14. doGet(req, resp);//注意这里改成doGet(req, resp),形成一个规范
  15. }
  16. }

在web.xml里注册类

  1. <servlet>
  2. <servlet-name>sd4</servlet-name>
  3. <servlet-class>com.ylw.servlet.ServletDemo04</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>sd4</servlet-name>
  7. <url-pattern>/sd4</url-pattern>
  8. </servlet-mapping>

重启Tomcat,
打开浏览器,进入/sd4,发现路径没有变,但是显示的是/gp的页面,这就是转发的作用(重定向才会改变路径)
JavaWeb - 图20
由于我们设置了输出语句,在控制台里可以看到,确实进入了demo04,只不过显示的是转发页面
JavaWeb - 图21

4、读取资源文件 getResourceAsStream()

用到的主要方法:

  1. //获取文件,变成流
  2. this.getServletContext().getResourceAsStream("文件路径"
  3. //加载流
  4. Properties prop = new Properties();
  5. prop.load(inputStream); //加载上面文件转化成的流
  6. prop.getProperty("属性名"); //获取文件中的一个属性

Properties

比较分析:

  • 在java目录下新建properties
  • 在resources目录下新建properties

发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:

JavaWeb - 图22

在java目录下的properties,发现导出的target中没有该文件,就需要在pom.xml中添加配置,详见博客https://blog.csdn.net/qq_43594119/article/details/106199248中的**解决资源导出失败问题**

读取资源文件:
1在resources目录下新建一个db.properties文件作为资源文件
JavaWeb - 图23

  1. username=wuxinyu
  2. password=123456

2.写一个类用来读取这个资源文件,下面是截图和代码
JavaWeb - 图24

  1. package com.kuang.servlet;
  2. public class PropertiesServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //获得资源,变成一个流 路径是target下面的路径
  6. InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
  7. Properties prop = new Properties();
  8. prop.load(inputStream); //加载上面文件转化成的流
  9. String user = prop.getProperty("username"); //获取文件中的一个属性
  10. String pwd = prop.getProperty("password"); //获取文件中的一个属性
  11. //在网页上显示出来
  12. resp.getWriter().print("user: " + user +'\n' + "pwd: " + pwd);
  13. }
  14. @Override
  15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16. doGet(req, resp); //注意这里改成doGet(req, resp),形成一个规范
  17. }
  18. }

注意这里的路径是 /WEB-INF/classes/db.properties 第一个 / 代表当前项目
JavaWeb - 图25
3.在web.xml中注册该类

  1. <servlet>
  2. <servlet-name>sd5</servlet-name>
  3. <servlet-class>com.ylw.servlet.ServletDemo05</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>sd5</servlet-name>
  7. <url-pattern>/sd5</url-pattern>
  8. </servlet-mapping>

4.重启tomcat,访问/sd5
JavaWeb - 图26

6.6、HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpServletResponse

1、简单分类

负责向浏览器发送数据的方法

  1. servletOutputstream getOutputstream() throws IOException;
  2. Printwriter getwriter() throws IOException;

负责向浏览器发送响应头的方法

2、下载文件

  1. 向浏览器输出消息(一直在讲,就不说了)
  2. 下载文件

    1. 要获取下载文件的路径
    2. 下载的文件名是啥?
    3. 设置想办法让浏览器能够支持下载我们需要的东西
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取OutputStream对象
    7. 将FileOutputStream流写入到bufer缓冲区
    8. 使用OutputStream将缓冲区中的数据输出到客户端!
  1. package com.kuang.servlet;
  2. public class FileServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. // 1. 要获取下载文件的路径
  6. String realPath = "D:\\WorkingSpace\\Idea_workingspace\\JavaWeb\\javaweb-02-servlet\\response\\src\\main\\resources\\1.png";
  7. System.out.println("下载文件的路径为:"+realPath);
  8. // 2. 下载的文件名是啥?
  9. String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
  10. // 3. 设置想办法让浏览器能够支持下载我们需要的东西
  11. System.out.println(fileName);
  12. resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
  13. // 4. 获取下载文件的输入流
  14. FileInputStream fileInputStream =new FileInputStream(realPath);
  15. // 5. 创建缓冲区
  16. int len = 0;
  17. byte[] buffer = new byte[1024];
  18. // 6. 获取OutputStream对象
  19. ServletOutputStream out = resp.getOutputStream();
  20. // 7. 将FileOutputStream流写入到bufer缓冲区
  21. while((len=fileInputStream.read(buffer))!=-1){
  22. out.write(buffer,0,len);
  23. }
  24. fileInputStream.close();
  25. out.close();
  26. // 8. 使用OutputStream将缓冲区中的数据输出到客户端!
  27. }
  28. @Override
  29. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  30. super.doPost(req, resp);
  31. }
  32. }
  1. <servlet>
  2. <servlet-name>FileServlet</servlet-name>
  3. <servlet-class>com.kuang.servlet.FileServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>FileServlet</servlet-name>
  7. <url-pattern>/fs</url-pattern>
  8. </servlet-mapping>

3. 实现重定向

JavaWeb - 图27

常见场景:

  • 用户登录
  1. void sendRedirect(String var1) throws IOException;

测试:

  1. package com.kuang.servlet;
  2. public class RedirectServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. resp.sendRedirect("/img");//重定向
  6. /*
  7. resp. setHeader("Location","/r/img");
  8. resp. setstatus (302);
  9. */
  10. }
  11. @Override
  12. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  13. super.doPost(req, resp);
  14. }
  15. }
  1. <servlet>
  2. <servlet-name>RedirectServlet</servlet-name>
  3. <servlet-class>com.kuang.servlet.RedirectServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>RedirectServlet</servlet-name>
  7. <url-pattern>/reditect</url-pattern>
  8. </servlet-mapping>

面试题:请你聊聊重定向和转发的区别?

  • forward(转发):307

是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址.

  • redirect(重定向):302

是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

转发是服务器行为,重定向是客户端行为。

相同点:页面都会跳转

不同点:

  • 请求转发时:url不会产生变化
  • 重定向:url会产生变化

JavaWeb - 图28
index.jsp

  1. <html>
  2. <body>
  3. <h2>Hel1o World!</h2>
  4. 《%--这里提交的路径,需要寻找到项目的路径--%>
  5. <%--${pageContext. request, contextPath}代表当前的项目--%>
  6. <form action="${pageContext. request.contextPath}/login" method="get">
  7. 用户名: <input type="text" name="username"> <br>
  8. 密码: <input type="password" name="password"> <br>
  9. <input type="submit">
  10. </form>
  11. </body>
  12. </html>

RequestTest.java

  1. package com.kuang.servlet;
  2. public class RequestTest extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //处理方求
  6. String username = req.getParameter( "username");
  7. String password =req.getParameter( "password");
  8. System.out.println(username+":"+password);
  9. resp.sendRedirect("/success.jsp");
  10. }
  11. @Override
  12. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  13. super.doPost(req, resp);
  14. }
  15. }

重定向页面success.jsp

  1. <%@ page contentType="text/html; charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <h1>success</h1>
  8. </body>
  9. </html>

web.xml配置

  1. <servlet>
  2. <servlet-name>requset</servlet-name>
  3. <servlet-class>com.kuang.servlet.RequestTest</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>requset</servlet-name>
  7. <url-pattern>/login</url-pattern>
  8. </servlet-mapping>

导入依赖的jar包

  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>javax.servlet</groupId>
  9. <artifactId>javax.servlet-api</artifactId>
  10. <version>4.0.1</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>javax.servlet.jsp</groupId>
  14. <artifactId>javax.servlet.jsp-api</artifactId>
  15. <version>2.3.3</version>
  16. </dependency>
  17. </dependencies>

6.7、HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;

获取前端传递的参数、请求转发

  1. String username = req.getParameter("username"); // 从前端传来的变量
  2. String password = req.getParameter("password");
  3. String[] hobbys = req.getParameterValues("hobbys"); // 从前端传来的数组

前端页面传来数据

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>登录</title>
  5. </head>
  6. <body>
  7. <div style="text-align: center">
  8. <form action="${pageContext.request.contextPath}/login" method="post">
  9. 用户名:<input type="text" name="username"><br>
  10. 密码:<input type="password" name="password"><br>
  11. 爱好:
  12. <input type="checkbox" name="hobbys" value="女孩">女孩
  13. <input type="checkbox" name="hobbys" value="代码">代码
  14. <input type="checkbox" name="hobbys" value="唱歌">唱歌
  15. <input type="checkbox" name="hobbys" value="电影">电影
  16. <br>
  17. <input type="submit">
  18. </form>
  19. </div>
  20. </body>
  21. </html>

获取前端传过来的数据

  1. package com.kuang.servlet;
  2. public class LoginServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. super.doGet(req, resp);
  6. }
  7. @Override
  8. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  9. req.setCharacterEncoding("utf-8");
  10. resp.setCharacterEncoding("utf-8");
  11. String username = req.getParameter("username");
  12. String password = req.getParameter("password");
  13. String[] hobbys = req.getParameterValues("hobbys");
  14. System.out.println("==========");
  15. //后台接收中文乱码问题
  16. System. out.println(username);
  17. System. out.println(password);
  18. System. out.println(Arrays.toString(hobbys));
  19. System. out.println("============");
  20. System. out.println(req.getContextPath());
  21. //通过请求转发
  22. //这里的/代表当前的web应用
  23. req.getRequestDispatcher("/success.jsp").forward(req,resp);
  24. }
  25. }

web.xml中配置映射,让服务器能通过映射找到Java文件

  1. <servlet>
  2. <servlet-name>LoginServlet</servlet-name>
  3. <servlet-class>com.kuang.servlet.LoginServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>LoginServlet</servlet-name>
  7. <url-pattern>/login</url-pattern>
  8. </servlet-mapping>

7. Web服务

缺点:

  • 加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布; 停机维护。

优点:

  • Web页面可以动态更新,所有用户看到都不是同一个页面
  • 它可以与数据库交互 (数据持久化:注册,商品信息,用户信息…)

JavaWeb - 图29

7.1 现有技术

ASP:

  • 微软:国内最早流行的就是ASP;
  • 在HTML中嵌入了VB的脚本, ASP + COM;
  • 在ASP开发中,基本一个页面都有几千行的业务代码,页面极其换乱
  • 维护成本高!
  • C#
  • IIS

php:

  • PHP开发速度很快,功能很强大,跨平台,代码很简单 (70% , WP)
  • 无法承载大访问量的情况(局限性)

JSP/Servlet :

B/S:浏览器和服务器

C/S: 客户端和服务器

  • sun公司主推的B/S架构
  • 基于Java语言的 (所有的大公司,或者一些开源的组件,都是用Java写的)
  • 可以承载三高(高并发、高可用、高性能)问题带来的影响;
  • 语法像ASP , ASP–—转——->JSP , 加强市场强度;

7.2 状态响应码

200:请求响应成功 200

3xx:请求重定向

  • 重定向:你重新到我给你新位置去;

4xx:找不到资源 404

  • 资源不存在;

5xx:服务器代码错误 500 502:网关错误

7.3 Cookie

客户端———————————————-服务端

  1. 服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下次你来的时候我来匹配你; seesion

获取cookies列表:Cookie[] cookies = req.getCookies();

设置cookieresp.addCookie(cookie);

Cookie获取上次访问浏览器的时间

  1. package com.kuang.servlet;
  2. public class CookieDemo01 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //服务器给客户端发一个cookie 告你你来的时间,封装成一个信件,你下次来带来,我就知道你来了
  6. //解决中文乱码
  7. req.setCharacterEncoding("utf-8");
  8. resp.setCharacterEncoding("utf-8");
  9. resp.setContentType("text/html;charset=utf-8");
  10. // 获取输出对象
  11. Writer out = resp.getWriter();
  12. out.write("上次访问时间: ");
  13. // 获取访问时间cookie
  14. Cookie[] cookies = req.getCookies();
  15. for (int i = 0; cookies != null && i < cookies.length; i++) {
  16. Cookie cookie = cookies[i];
  17. if (cookie.getName().equals("lastAccess")) {
  18. String value = cookie.getValue();
  19. Date date = new Date(Long.parseLong(value));
  20. out.write(date.toString());
  21. }
  22. }
  23. // 设置最新的访问时间cookie
  24. Cookie cookie = new Cookie("lastAccess", System.currentTimeMillis() + "");
  25. // 设置cookie有效时间 单位:秒
  26. cookie.setMaxAge(3600);
  27. // 设置cookie有效路径
  28. cookie.setPath(req.getContextPath());
  29. //System.out.println(request.getContextPath());
  30. //System.out.println(this.getServletContext().getContextPath());
  31. resp.addCookie(cookie);
  32. }
  33. @Override
  34. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  35. super.doPost(req, resp);
  36. }
  37. }
  1. <servlet>
  2. <servlet-name>CookieDemo01</servlet-name>
  3. <servlet-class>com.kuang.servlet.CookieDemo01</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>CookieDemo01</servlet-name>
  7. <url-pattern>/c1</url-pattern>
  8. </servlet-mapping>

JavaWeb - 图30

JavaWeb - 图31

  1. 从请求中拿到cookie信息
  2. 服务器响应给客户端cookie
  1. Cookie[] cookies = req.getCookies(); //获得Cookie
  2. cookie.getName(); //获得cookie中的key
  3. cookie.getValue(); //获得cookie中的vlaue
  4. new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
  5. cookie.setMaxAge(24*60*60); //设置cookie的有效期
  6. resp.addCookie(cookie); //服务器响应给客户端一个cookie

cookie:一般会保存在本地的 用户目录下 appdata;

JavaWeb - 图32

一个网站cookie是否存在上限!聊聊细节问题

  • 一个Cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie最多存放20个cookie
  • Cookie大小有限制4kb
  • 300个cookie浏览器上限

删除Cookie;

  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效期时间为 0 ;

7.4 Session(重点)

JavaWeb - 图33
什么是Session

  • 服务器会给每一个用户(浏览器)创建一个Seesion对象;
  • 一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
  • 用户登录之后,整个网站它都可以访问!–———> 保存用户的信息;保存购物车的信息……

Sessioncookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务创建;

使用场景:

  • 保存一个登录用户的信息;
  • 购物车信息;
  • 在整个网站中经常会使用的数据,我们将它保存在Session中;

使用Session

得到Session: HttpSession session = req.getSession();
Session中存东西,可以存很多东西,如变量,对象session.setAttribute("name",new Person("秦疆",1));
获取Session的ID: String sessionId = session.getId();

使用Session存入对象,并获取当前默认创建的session ID

  1. package com.kuang.servlet;
  2. public class SessionDemo01 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //解决乱码问题
  6. req.setCharacterEncoding("UTF-8");
  7. resp.setCharacterEncoding("UTF-8");
  8. resp.setContentType("text/html;charset=utf-8");
  9. //得到Session
  10. HttpSession session = req.getSession();
  11. //给Session中存东西,可以存很多东西,如变量,对象
  12. session.setAttribute("name",new Person("秦疆",1));
  13. //获取Session的ID
  14. String sessionId = session.getId();
  15. //判断Session是不是新创建
  16. if (session.isNew()){
  17. resp.getWriter().write("session创建成功,ID:"+sessionId);
  18. }else {
  19. resp.getWriter().write("session以及在服务器中存在了,ID:"+sessionId);
  20. }
  21. //Session创建的时候做了什么事情;
  22. // Cookie cookie = new Cookie("JSESSIONID",sessionId);
  23. // resp.addCookie(cookie);
  24. }
  25. @Override
  26. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  27. doGet(req, resp);
  28. }
  29. }

JavaWeb - 图34

获取Session存入的对象

  1. package com.kuang.servlet;
  2. public class SessionDemo02 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //解决乱码问题
  6. req.setCharacterEncoding("UTF-8");
  7. resp.setCharacterEncoding("UTF-8");
  8. resp.setContentType("text/html;charset=utf-8");
  9. //得到Session
  10. HttpSession session = req.getSession();
  11. Person person = (Person) session.getAttribute("name");
  12. System.out.println(person.toString());
  13. }
  14. @Override
  15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16. super.doPost(req, resp);
  17. }
  18. }

JavaWeb - 图35

最后要在web.xml中添加配置

  1. <servlet>
  2. <servlet-name>SessionDemo01</servlet-name>
  3. <servlet-class>com.kuang.servlet.SessionDemo01</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>SessionDemo01</servlet-name>
  7. <url-pattern>/s1</url-pattern>
  8. </servlet-mapping>
  9. <servlet>
  10. <servlet-name>SessionDemo02</servlet-name>
  11. <servlet-class>com.kuang.servlet.SessionDemo02</servlet-class>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>SessionDemo02</servlet-name>
  15. <url-pattern>/s2</url-pattern>
  16. </servlet-mapping>

删除会话:注销

  1. package com.kuang.servlet;
  2. public class SessionDemo03 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //解决乱码问题
  6. req.setCharacterEncoding("UTF-8");
  7. resp.setCharacterEncoding("UTF-8");
  8. resp.setContentType("text/html;charset=utf-8");
  9. //得到Session
  10. HttpSession session = req.getSession();
  11. session.removeAttribute("name");
  12. //删除session
  13. session.invalidate();
  14. }
  15. @Override
  16. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  17. super.doPost(req, resp);
  18. }
  19. }

自动定时注销

  1. <!--设置Session默认的失效时间-->
  2. <session-config>
  3. <!--15分钟后Session自动失效,以分钟为单位-->
  4. <session-timeout>15</session-timeout>
  5. </session-config>

8、JSP

Java Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!

最大的特点:

  • 写JSP就像在写HTML
  • 区别:

    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入JAVA代码,为用户提供动态数据;

8.1 JSP原理

思路:JSP到底怎么执行的!

  • 代码层面没有任何问题

  • 服务器内部工作
    tomcat中有一个work目录;
    IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目录
    JavaWeb - 图36
    JavaWeb - 图37
    我电脑的地址:
    C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2020.3\tomcat\4c2427d8-18f1-41a5-9c10-3480b51c0536\work\Catalina\localhost\javaweb_01_maven01_war\org\apache\jsp
    发现页面转变成了Java程序!
    JavaWeb - 图38

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

JSP最终也会被转换成为一个Java类!

JSP 本质上就是一个Servlet 帮助简化了Servlet的使用

  1. //初始化
  2. public void _jspInit() {
  3. }
  4. //销毁
  5. public void _jspDestroy() {
  6. }
  7. //JSPService
  8. public void _jspService(.HttpServletRequest request,HttpServletResponse response)
  1. 判断请求

  2. 内置一些对象

    1. final javax.servlet.jsp.PageContext.pageContext; //页面上下文
    2. javax.servlet.http.HttpSession session = null; //session
    3. final javax.servlet.ServletContext application; //applicationContext
    4. final javax.servlet.ServletConfig config; //config
    5. javax.servlet.jsp.JspWriter out = null; //out
    6. final java.lang.Object page = this; //page:当前
    7. HttpServletRequest request //请求
    8. HttpServletResponse response //响应
  1. 输出页面前增加的代码
    1. response.setContentType("text/html"); //设置响应的页面类型
    2. pageContext = _jspxFactory.getPageContext(this, request, response,
    3. null, true, 8192, true);
    4. _jspx_page_context = pageContext;
    5. application = pageContext.getServletContext();
    6. config = pageContext.getServletConfig();
    7. session = pageContext.getSession();
    8. out = pageContext.getOut();
    9. _jspx_out = out;
  1. 以上的这些个对象我们可以在JSP页面中直接使用!

JavaWeb - 图39

在JSP页面中;

只要是 JAVA代码就会原封不动的输出;

JavaWeb - 图40

JavaWeb - 图41

如果是HTML代码,就会被转换为:

  1. out.write("<html>\r\n");

这样的格式,输出到前端!

8.2 JSP依赖

mavenpom.xml中添加

  1. <!-- Servlet依赖-->
  2. <dependency>
  3. <groupId>javax.servlet</groupId>
  4. <artifactId>javax.servlet-api</artifactId>
  5. <version>4.0.1</version>
  6. </dependency>
  7. <!-- JSP依赖-->
  8. <dependency>
  9. <groupId>javax.servlet.jsp</groupId>
  10. <artifactId>javax.servlet.jsp-api</artifactId>
  11. <version>2.3.3</version>
  12. </dependency>
  13. <!--JSTL表达式依赖-->
  14. <dependency>
  15. <groupId>javax.servlet.jsp.jstl</groupId>
  16. <artifactId>jstl-api</artifactId>
  17. <version>1.2</version>
  18. </dependency>
  19. <!--standard标签库-->
  20. <dependency>
  21. <groupId>taglibs</groupId>
  22. <artifactId>standard</artifactId>
  23. <version>1.1.2</version>
  24. </dependency>

8.3 JSP语法

JSP声明<%! declaration; [ declaration; ]+ ... %>

示例:

  1. <%!
  2. int a = 10;
  3. static {System.out.print(10);}
  4. public void ahang(){int b = 20;}
  5. %>

JSP表达式:只能写一个表达式<%= 表达式 %>

<%= new java.util.Date()%>

JSP注释<%-- 该部分注释在网页中不会被显示--%>

JSP脚本

  1. <%
  2. int sum = 0;
  3. for (int i = 1; i <=100 ; i++) {
  4. sum+=i;
  5. }
  6. out.println("<h1>Sum="+sum+"</h1>");
  7. %>
  1. <%--在代码嵌入HTML元素--%>
  2. <%
  3. for (int i = 0; i < 5; i++) {
  4. %>
  5. <h1>Hello,World <%=i%> </h1>
  6. <%
  7. }
  8. %>

EL表达式${ } 使用教程

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象

JSP指令

指令 描述
<%@ page … %> 定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等
<%@ include … %> 包含其他文件
<%@ taglib … %> 引入标签库的定义,可以是自定义标签

<%@ page errorPage="errorpage/500.jsp"%>

JSP行为

<jsp:include page="error.jsp" flush="true"/>

经过转化为Java文件后:

所在位置:C:\Users\105\.IntelliJIdea2018.2\system\tomcat\Unnamed_JavaWeb\work\Catalina\localhost\ROOT\org\apache\jsp\index_jsp.java

  1. public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase{
  2. // <%! 声明 %>声明的变量方法进入Java类的变量
  3. int a = 10;
  4. static {System.out.print(10);}
  5. public void ahang(){
  6. int b = 20;
  7. }
  8. ...
  9. // 这里面是页面显示的内容
  10. try {
  11. response.setContentType("text/html;charset=UTF-8");
  12. pageContext = _jspxFactory.getPageContext(this, request, response,
  13. null, true, 8192, true);
  14. _jspx_page_context = pageContext;
  15. application = pageContext.getServletContext();
  16. config = pageContext.getServletConfig();
  17. session = pageContext.getSession();
  18. out = pageContext.getOut();
  19. _jspx_out = out;
  20. out.write("\n");
  21. out.write("\n");
  22. // HTML页面代码直接通过out.write("html代码")
  23. out.write("<html>\n");
  24. out.write(" <head>\n");
  25. out.write(" <title>$Title$</title>\n");
  26. out.write(" </head>\n");
  27. // <%= 表达式%>
  28. out.print( new java.util.Date());
  29. // <% 脚本 %>
  30. int sum = 0;
  31. for (int i = 1; i <=100 ; i++) {
  32. sum+=i;
  33. }
  34. out.println("<h1>Sum="+sum+"</h1>");
  35. // <% 嵌套的脚本 %>
  36. for (int i = 0; i < 5; i++) {
  37. out.write("\n");
  38. out.write(" <h1>Hello,World ");
  39. out.print(i);
  40. out.write(" </h1>\n");
  41. out.write(" ");
  42. }
  43. // JSP指令<%@ page errorPage="errorpage/500.jsp"%>
  44. org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "error.jsp", out, true);
  45. // JSP行为动作<jsp:include page="error.jsp" flush="true"/>
  46. out.write("<html>\r\n");
  47. out.write("<head>\r\n");
  48. out.write(" <title>Title</title>\r\n");
  49. out.write("</head>\r\n");
  50. out.write("<body>\r\n");
  51. out.write("<h1>账号或密码不对,正在跳转登录界面。。。</h1><br>\r\n");
  52. out.write("<meta http-equiv=\"Refresh\" content=\"3;/index.jsp\">\r\n");
  53. out.write("<a href=\"/index.jsp\">或点此手动跳转登录页面</a>\r\n");
  54. out.write("</body>\r\n");
  55. out.write("</html>\r\n");
  56. }
  57. }

8.4 定制错误页面

先建好错误页面,然后在web.xml中添加映射

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  5. http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  6. version="4.0"
  7. metadata-complete="true">
  8. <error-page>
  9. <error-code>404</error-code>
  10. <location>/errorpage/404.jsp</location>
  11. </error-page>
  12. </web-app>

8.5 九大内置对象

对象 描述
request HttpServletRequest类的实例,【存东西】
response HttpServletResponse类的实例
out PrintWriter类的实例,用于把结果输出至网页上
session HttpSession类的实例,【存东西】
application ServletContext类的实例,与应用上下文有关,【存东西】
config ServletConfig类的实例
pageContext PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问,【存东西】
page 类似于Java类中的this关键字
Exception Exception类的对象,代表发生错误的JSP页面中对应的异常对象

8.5.1 数据存取

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <%
  8. pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
  9. request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
  10. session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
  11. application.setAttribute("name4","秦疆4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
  12. %>
  13. <%
  14. String name1 = (String) pageContext.findAttribute("name1");
  15. String name2 = (String) pageContext.findAttribute("name2");
  16. String name3 = (String) pageContext.findAttribute("name3");
  17. String name4 = (String) pageContext.findAttribute("name4");
  18. String name5 = (String) pageContext.findAttribute("name5");
  19. %>
  20. <%--使用输出 --%>
  21. <h1>取出的值为:</h1>
  22. <h1>${name1}</h1>
  23. <h1>${name2}</h1>
  24. <h1>${name3}</h1>
  25. <h1>${name4}</h1>
  26. <h1><%= name5%></h1>
  27. </body>
  28. </html>

JavaWeb - 图42

8.5.2 请求转发

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <%
  8. pageContext.forward("/index.jsp");
  9. request.getRequestDispatcher("/index.jsp").forward(request,response);
  10. %>
  11. </body>
  12. </html>

JavaWeb - 图43

JavaWeb - 图44

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;

9. MVC三层架构

  • 什么是MVC: Model view Controller 模型、视图、控制器

9.1 以前的架构

JavaWeb - 图45

用户直接访问控制层,控制层就可以直接操作数据库;

  1. servlet--CRUD-->数据库
  2. 弊端:程序十分臃肿,不利于维护
  3. servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
  4. 架构:没有什么是加一层解决不了的!
  5. 程序猿调用
  6. 数据库
  7. JDBC (实现该接口)
  8. Mysql Oracle SqlServer ....(不同厂商)

9.2 MVC三层架构

JavaWeb - 图46

Model

  • 业务处理 :业务逻辑(Service)
  • 数据持久层:CRUD (Dao - 数据持久化对象)

View

  • 展示数据
  • 提供链接发起Servlet请求 (a,form,img…)

Controller (Servlet)

  • 接收用户的请求 :(req:请求参数、Session信息….)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

    1. 登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,usernamepassword)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库

10 Filter 过滤器处理乱码

比如 Shiro安全框架技术就是用Filter来实现的

Filter:过滤器 ,用来过滤网站的数据;

  • 处理中文乱码
  • 登录验证….

(比如用来过滤网上骂人的话)

JavaWeb - 图47
Filter开发步骤:

  1. 导包
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.kuang</groupId>
  7. <artifactId>javaweb-05-filter</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <properties>
  10. <maven.compiler.source>8</maven.compiler.source>
  11. <maven.compiler.target>8</maven.compiler.target>
  12. </properties>
  13. <dependencies>
  14. <dependency>
  15. <groupId>javax.servlet</groupId>
  16. <artifactId>servlet-api</artifactId>
  17. <version>2.5</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>javax.servlet.jsp</groupId>
  21. <artifactId>javax.servlet.jsp-api</artifactId>
  22. <version>2.3.3</version>
  23. </dependency>
  24. </project>

中文乱码解决

  1. 编写过滤器

    1. 导包不要错 (注意)

JavaWeb - 图48

显示页面有中文,默认会乱码

  1. package com.kuang.servlet;
  2. public class ShowServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. resp.getWriter().write("你好呀,世界!");
  6. }
  7. @Override
  8. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  9. super.doPost(req, resp);
  10. }
  11. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  5. http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  6. version="4.0"
  7. metadata-complete="true">
  8. <servlet>
  9. <servlet-name>ShowServlet</servlet-name>
  10. <servlet-class>com.kuang.servlet.ShowServlet</servlet-class>
  11. </servlet>
  12. <servlet-mapping>
  13. <servlet-name>ShowServlet</servlet-name>
  14. <url-pattern>/Servlet/Show</url-pattern>
  15. </servlet-mapping>
  16. </web-app>

JavaWeb - 图49

2.实现filer:

实现Filter接口,重写对应的方法即可

注意:一定要重写init()destroy()方法,即使为空也需要显示表示,否则报错

  1. public class CharacterEncodingFilter implements Filter {
  2. //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. System.out.println("CharacterEncodingFilter初始化");
  5. }
  6. //Chain : 链
  7. /*
  8. 1. 过滤中的所有代码,在过滤特定请求的时候都会执行
  9. 2. 必须要让过滤器继续同行
  10. chain.doFilter(request,response);
  11. */
  12. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  13. request.setCharacterEncoding("utf-8");
  14. response.setCharacterEncoding("utf-8");
  15. response.setContentType("text/html;charset=UTF-8");
  16. System.out.println("CharacterEncodingFilter执行前....");
  17. chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
  18. System.out.println("CharacterEncodingFilter执行后....");
  19. }
  20. //销毁:web服务器关闭的时候,过滤器会销毁
  21. public void destroy() {
  22. System.out.println("CharacterEncodingFilter销毁");
  23. }
  24. }

3.在web.xml中配置 Filter

  1. <servlet>
  2. <servlet-name>ShowServlet</servlet-name>
  3. <servlet-class>com.kuang.servlet.ShowServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>ShowServlet</servlet-name>
  7. <url-pattern>/Servlet/Show</url-pattern>
  8. </servlet-mapping>
  9. <!-- 访问/Show就不会通过服务器-->
  10. <servlet-mapping>
  11. <servlet-name>ShowServlet</servlet-name>
  12. <url-pattern>/Show</url-pattern>
  13. </servlet-mapping>
  14. <filter>
  15. <filter-name>CharacterEncodingFilter</filter-name>
  16. <filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
  17. </filter>
  18. <filter-mapping>
  19. <filter-name>CharacterEncodingFilter</filter-name>
  20. <!--只要是 /servlet的任何请求,会经过这个过滤器-->
  21. <url-pattern>/Servlet/*</url-pattern>
  22. <!--<url-pattern>/*</url-pattern>-->
  23. <!-- 别偷懒写个 /* -->
  24. </filter-mapping>

JavaWeb - 图50

11. Listener监听统计人数

实现一个监听器的接口;(有n种监听器)

  1. 编写一个监听器
    实现监听器的接口…
    统计网站在线人数 ```java package com.kuang.listener;

public class OnlineCountListener implements HttpSessionListener { //创建session监听: 看你的一举一动 //一旦创建Session就会触发一次这个事件! @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { ServletContext servletContext = httpSessionEvent.getSession().getServletContext();

  1. System.out.println(httpSessionEvent.getSession().getId());
  2. Integer onlineCount = (Integer) servletContext.getAttribute("OlineCount");
  3. if(onlineCount==null){
  4. onlineCount = new Integer(1);
  5. }else{
  6. int count = onlineCount.intValue();
  7. onlineCount = new Integer(count++);
  8. }
  9. servletContext.setAttribute("OlineCount",onlineCount);
  10. }
  11. //销毁session监听
  12. //一旦销毁Session就会触发一次这个事件!
  13. @Override
  14. public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
  15. ServletContext servletContext= httpSessionEvent.getSession().getServletContext();
  16. Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
  17. if (onlineCount==null){
  18. onlineCount = new Integer(0);
  19. }else {
  20. int count = onlineCount.intValue();
  21. onlineCount = new Integer(count-1);
  22. }
  23. servletContext.setAttribute("OnlineCount",onlineCount);
  24. }

}

/* Session销毁:

  1. 1. 手动销毁 getSession().invalidate();
  2. 2. 自动销毁
  3. */
  1. 2.
  2. web.xml中注册监听器
  3. ```xml
  4. <!--注册监听器-->
  5. <listener>
  6. <listener-class>com.kuang.listener.OnlineCountListener</listener-class>
  7. </listener>
  1. 看情况是否使用!

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Title</title>
    5. </head>
    6. <body>
    7. <h1>当前在线人数:<span><%=this.getServletConfig().getServletContext().getAttribute("OlineCount")%></span></h1>
    8. </body>
    9. </html>
  1. JavaWeb - 图51

12. 登录权限过滤

用户登录之后才能进入主页!用户注销后就不能进入主页了!

登录流程:

  1. 用户通过index.jsp也就是默认站点登录

  2. 输入用户密码正确后进入http://localhost:8080/sys/success.jsp登录成功页面,点击页面上注销后即退出登录返回至http://localhost:8080/index.jsp默认界面

  3. 输入用户密码错误后进入http://localhost:8080/error.jsp登录错误页面,三秒后自动跳转至主页面

  4. 如果直接输入url为:http://localhost:8080/sys/success.jsp会因为没有权限而跳转至http://localhost:8080/error.jsp错误页面
    JavaWeb - 图52
    JavaWeb - 图53
    JavaWeb - 图54

实现思路:

  1. 在首页实现post提交用户名密码,交给后台验证

  2. 后端通过实现一个Loginservlet.java来对数据验证,如果数据匹配则给该请求创建一个Session来给过滤器使用,然后跳转成功页面;如果不匹配则直接跳转错误页面

  3. 注销实现一个LogOutservlet.java来删除该Session,然后重定向到错误页面

  4. 为了防止用户在没有登录时,直接访问http://localhost:8080/sys/success.jsp页面,需要添加一个过滤器在filter中添加SysFilter.java来判断请求是否携带Session,如果没有携带则跳转至错误页面,否则通过放行

JavaWeb - 图55

  1. 首页index.jsp
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>Title</title>
  5. </head>
  6. <body>
  7. <form action="/servlet/login" method="post">
  8. <input type="text" name="username">
  9. <input type="submit">
  10. </form>
  11. </body>
  12. </html>
  1. 登录成功后的页面success.jsp
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Title</title>
    5. </head>
    6. <body>
    7. <h1>主页</h1>
    8. <p> <a href="/servlet/logout">注销</a> </p>
    9. </body>
    10. </html>
  1. 登录出错或没有权限的错误页面
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>Title</title>
    5. </head>
    6. <body>
    7. <h1>账号或密码不对没有权限,3秒后跳转登录界面。。。</h1><br>
    8. <meta http-equiv="Refresh" content="3;/index.jsp">
    9. <a href="/index.jsp">或点此手动跳转登录页面</a>
    10. </body>
    11. </html>
  1. 登录后通过后端Loginservlet判断
  1. package com.kuang.servlet;
  2. public class Loginservlet extends HttpServlet {
  3. @Override
  4. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. //获取前端传来的参数
  6. String username = req.getParameter("username");
  7. if(username.equals("admin")){
  8. // 给当前Session设一个特定属性,方便后面filter判断
  9. req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
  10. // 登录成功后跳转至成功页面并给设定一个Session
  11. resp.sendRedirect("/sys/success.jsp");
  12. }else{
  13. // 登录失败跳转错误页面
  14. resp.sendRedirect("/error.jsp");
  15. }
  16. }
  17. @Override
  18. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  19. super.doGet(req, resp);
  20. }
  21. }
  1. 登出注销通过后端LogoutServlet.java来实现
  1. package com.kuang.servlet;
  2. public class LogoutServlet extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. Object user_session = req.getSession().getAttribute("USER_SESSION");
  6. // 用户注销,删除session,跳转首页
  7. if(user_session!=null){
  8. req.getSession().removeAttribute("USER_SESSION");
  9. resp.sendRedirect("/Login.jsp");
  10. }else{
  11. resp.sendRedirect("/Login.jsp");
  12. }
  13. }
  14. @Override
  15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  16. super.doPost(req, resp);
  17. }
  18. }
  1. 通过过滤实现权限管理
  1. package com.kuang.filter;
  2. public class SysFilter implements Filter {
  3. @Override
  4. public void init(FilterConfig filterConfig) throws ServletException {
  5. }
  6. @Override
  7. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  8. HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
  9. HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
  10. if((httpServletRequest.getSession().getAttribute("USER_SESSION"))==null){
  11. httpServletResponse.sendRedirect("/error.jsp");
  12. }
  13. filterChain.doFilter(servletRequest,servletResponse);
  14. }
  15. @Override
  16. public void destroy() {
  17. }
  18. }
  1. 最后在web.xml中添加映射的配置
  1. <servlet>
  2. <servlet-name>LoginServlet</servlet-name>
  3. <servlet-class>com.kuang.servlet.Loginservlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>LoginServlet</servlet-name>
  7. <url-pattern>/servlet/login</url-pattern>
  8. </servlet-mapping>
  9. <servlet>
  10. <servlet-name>LogoutServlet</servlet-name>
  11. <servlet-class>com.kuang.servlet.LogoutServlet</servlet-class>
  12. </servlet>
  13. <servlet-mapping>
  14. <servlet-name>LogoutServlet</servlet-name>
  15. <url-pattern>/servlet/logout</url-pattern>
  16. </servlet-mapping>
  17. <filter>
  18. <filter-name>SysFilter</filter-name>
  19. <filter-class>com.kuang.filter.SysFilter</filter-class>
  20. </filter>
  21. <filter-mapping>
  22. <filter-name>SysFilter</filter-name>
  23. <!--只要是 /sys的任何请求,会经过这个过滤器-->
  24. <url-pattern>/sys/*</url-pattern>
  25. <!--<url-pattern>/*</url-pattern>-->
  26. <!-- 别偷懒写个 /* -->
  27. </filter-mapping>