【JavaWeb】基础知识梳理笔记

时间:2024-11-18 07:39:21

Java Web


基础概念

illust_77186528_20191015_163349.jpg

web开发:

  • web–网页
  • 静态web
    • html, css…
    • 提供给所有人看不会发生变化的.
  • 动态web
    • 京东…几乎所有的网站
    • 提供的数据始终在变化,每个人看到的都不相同
    • 技术栈:Servlet/jsp, asp, php

在java中,动态web资源开发的技术统称javaweb

web应用程序:

  • 可以提供浏览器访问的程序,例如…
  • 我们每一个访问的页面或资源,都存在于世界上某一个角落的计算机上
  • 这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat:服务器
  • 一个web应用由多部分组成 (静态web,动态web)
    • html,css,js
    • jsp,servlet
    • Java程序
    • jar包,配置文件 (Properties)…

静态web:

*.htm/ *.html这些都是网络后缀,需要一个统一的服务器管理;

图片.png

缺点:除了不能动,不能更新,没有特效,无法跟数据库交互,无法跟用户交互几乎没有缺点.

动态web:

缺点:当动态资源出现问题时,我们需要重新编写我们的后台程序,重新发布;(停机维护)

web服务器(实现手段)

ASP:

  • 微软: 国内最早流行的
  • 在html中嵌入VB脚本
  • 在ASP开发中,基本上一个页面上有html,java,css等代码,全部嵌套在一起
  • 主要应用c#语言,维护成本高,iis服务器

PHP:

  • 开发速度快,功能强大,跨平台,代码简单(优点)
  • 无法承载大访问量的情况–中小型开发(缺点)

JSP(Servlet):

  • sun公司主推的B/S架构
  • 基于java语言开发(几乎所有大公司都用java)
  • 可以解决高并发,高可用,高性能(三高问题)

搭建Web环境

illust_77278556_20191015_142115.jpg

c/s架构与b/s架构

  • c/s架构需要有客户端才能进行操作,需要进行更新等
  • b/s架构只需要打开浏览器就可以直接操作
  • b/s架构原理:基于请求与响应–客户发送请求信息,服务器运行程序返回检索到的信息

随着5G时代的到来,b/s架构会更受欢迎

URL

/news/200/?page=6

其中:

  • http 是协议
  • 是主机地址
  • /news/200/ 是目标资源地址
  • ?page=6 是传递的参数

URL (Uniform Resource Locator) “统一资源定位符"

万维网中统一默认端口号是80,默认协议是http,这些都是不用你直接输入的

WEB服务器

服务器是一种被动的操作,用来处理用户请求返回一些响应信息.

Web服务器可以向发出请求的浏览器提供文档的程序,以提供上网的功能(运行Web程序的)

常见的web服务器
  • IIS: 微软自带服务器
  • Nainx
  • Apache: Tomcat

Tomcat服务器

Tomcat是由Apacha软件基金会出品,Apacha是一个专门支持开源软件的基金会.

Tomcat官网; http://tomcat.apache.or

启动:

  • bin\
  • 访问Tomcat主页: http://localhost:端口号
  • 关闭: bin\

访问:

  • 将解压好的项目放进webapps文件夹里面,必须以文件夹的形式
  • 先启动Tomcat然后再在浏览器里输入localhost:8080/文件夹名

特点:

  • Apache Jakarta的开源项目
  • 轻量级应用服务器
  • 开源,稳定,资源占用小

坑:

  • 如果Tomcat运行不了,那就去配置jdk,(只能有一个jdk)
  • 提示80端口被占用,那就去卸载 服务-sql sever
  • 放进webapps里的文件想要打开就必须放进文件夹里

目录:

  • bin : 执行与开关闭
  • conf : 配置文件
  • lib : 所有的jar包
  • logs ; 日志文件
  • temp : 临时文件
  • webapps : 今后所有程序的放置位置
  • work : Tomcat把由jsp生成的Servlet放于此(无意义)

小结:

  • Tomcat浏览器访问方式: localhost:8080(本地ip地址:端口号)

  • conf/文件

    • 可以更改端口号

    • 可以更改主机名称

补充:高难度面试题:

请你谈谈网站是如何进行访问的!

  1. 输入一个域名;回车

  2. 检查本机的 C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;

    1. 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问

      127.0.1    www.linghuchong.com//在hosts文件里
      
      • 1
    2. 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;

Http

含义

HTTP(超文本传输协议):一个简单的请求-响应协议,通常运行在Tcp之上

		 端口:80
  • 1

HTTPS: 端口443

两个时代:
  1. http1.0: 客户端与web服务器连接后,只能获得一个web资源并断开连接
  2. http1.1: 一次可以获得多个web资源
Http请求
  • 客户端 – 发请求 – 服务器
Http响应
  • 服务器 – 响应 – 客户端

部署自己的web项目(idea)

视频在–第十五周–1213–视频文件夹

  1. 在idea里面先创建一个java项目
  2. 项目右键添加框架支持–web应用程序4.0
  3. 添加配置-汤姆猫
  4. 项目结构-全局库-添加进去
  5. // 上边栏设置按钮–工件–点击+号–web应用程序:存档–对于’…’
  6. // 点击最上方栏–构建–构建工件–项目名:war–构建
  7. // 构建完左边项目里就会出现out文件夹(里面找到war文件)
  8. // 将war文件放入Tomcat里的webapps文件夹,然后点击Tomcat运行,就会解压,解压成一个文件夹的形式
  9. 在浏览器里输入localhost:8080/项目文件夹名访问自己创建的项目
  • 一个网站应该有的结构:
--webapps :Tomcat服务器的web目录
    -ROOT
    -linghuchong :网站的目录名
    	- WEB-INF-classes : java程序
    	-lib:web应用所依赖的jar包
    	-web.xml :网站配置文件
    - index.html 默认的首页
    - static
        -css
        -style.css
        -js
        -img-...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在idea里面配置Tomcat

  • 在idea中右上角有个添加配置-- 点击+号
  • 找到Tomcat服务器-本地
  • 注意这里也可以进行端口号的修改
  • 修改jdk,找到自己的jdk安装目录
  • 在上栏找到部署 --工件–可选war包跟war exploded(扩展包)

war包跟war exploded包的区别:

  • 前者是需要解压然后才能运行的, 后者不需要.一般练习用测试包就可以,这样减少资源的浪费,上传到服务器端项目的时候才会用war包

  • 然后睡觉哦应用程序的上下文–这里注意小写英文字母就可以了


JSP(Java跟html的结合)

illust_75910823_20191015_170658.jpg

初识 jsp

JSP:(Java Server Pages)

在 JSP 文件中,HTML 代码与 Java 代码共同存在,其中,HTML 代码用来实现网页中静态内容的显 示,Java 代码用来实现网页中动态内容的显示。

特点:

  • 跨平台:适用于各大主流系统平台运行
  • 业务代码相分离(运行原理)
  • 组件重用
  • 预编译

运行原理:

一些jsp代码指令

基本结构: <% 内容 %>

<%@ **page **contentType=“text/html;charset=UTF-8” language=“java” %>

page指令:

  • 用于表明这是一个jsp;

  • 他用来设置JSP文件中的全局属性;

  • language=“java"声明脚本语言的种类,暂时只能用"java”.

注意:

  • 在 page 指令中区分大小写,不限制指令的位置、个数,JSP 指令对整个页面有效

  • contentType主要是告诉浏览器自己是什么类型的文件,同时要求浏览器以什么编码进行解析

out 输出:

//  向页面输出
<% (); %>  /  <% (); %>
  • 1
  • 2

注意做到这一步会产生一个报错,具体解决的途径是导入jar包,具体步骤如下:

  1. 导包: 找到Tomcat安装目录–lib–找到
  2. 在 idea 目录中 WEB-INF 中新建一个 lib 文件夹复制刚才的 jar 文件
  3. 右键点击 jar 包–添加为库
  4. 右侧栏–项目结构–右键点击–置于…

注意:

  • 直接用上面的语句会产生一个问题-- 可读性不好(java代码与heml代码混在一起,且不利于修改)

    解决方法: 声明变量,利用标签进行解决

    如下:

    <%
    String name = "张三";//声明变量
    //  向页面输出
    ("我叫"+name);
    %>
    <%="我叫"+name%>//<!--跟上面的是一样的,注意name后面不要写;-->
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 使用< %@page%>导包 如:< %@page import=“”%>

  • 输出转义字符。 如:<%=“谈”\北京精神\ “”%>(转义字符代表的是你先使用/输出这个符号,而不是它在这里面本身的作用–这里指字符串用“”括起来。)

注释:

  • HTML注释:
  • JSP注释: <%–JSP注释–%>
  • JSP脚本中注释<%//单行注释%> <%/* 多行注释*/%>
<%@ page import="" %>
<%@ page import="" %><%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/12/13
  Time: 10:38
  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>
    <h1>Hello Web !!!</h1>
<%--    向页面输出 谈KJDE1037学习精神--%>
  <%
    // 脚本   里面可以写Java代码
    //    int a  = 10;
    //    if(a > 5){
    //      ("Hello"); // 向控制台输出
    //    }
    String name = "张三";
    //  向页面输出
    ("谈KJDE1037学习精神");
    ("我叫"+name);

    // 输出当前日期
    Date date  = new Date();
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    String dateString = (date);
    ("当前时间是"+dateString);
  %>
  <%--    向页面输出   \转义  代表你想使用的是符号本身 --%>
  <%="现在时间\"是\""+dateString%>
  </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

JSP执行原理

此处省略一万字… …

局部变量与全局变量

<%
// 声明局部变量
    int i = 0;
    i++;

// 局部变量 : 声明在脚本的内部  每次使用都初始化
// 全局变量 声明在外部  只会在加载的时候初始化一次(每次使用都变化一次)
// out在局部可用,全局用不了,因为局部有参数,全局没有参数
  %>
  <!--  声明全局变量  -->
  <%! int k = 0; %>
  <!--  声明全局变量  -->
  public void show(){
      ("我是全局方法,我被执行了")
  }
  <%="局部变量"+i%>
  <%="全局变量"+(k++)%>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

常见错误

  • 404: 地址写错了/页面没有在WEB-INF下/外部启动了Tomcat,未部署项目
  • 500: jsp页面代码有错误
  • … …

JSP实现数据传递和保存

illust_75943001_20191015_173637.png

一.request请求

// 获取表单数据
getParameter();

// 获取多个相同的name
getParameterValues()

// 解决中文字符乱码问题
// 设置字符编码  解决post请求,而get不会有这个问题
setCharacterEncoding()
setCharacterEncoding("utf-8") 

// 存储数据 request作用域  数据只存在与一次请求只间   
setAttribute(key,value)

// 获取数据  可能有空指针异常 返回值是object需要强转
Object getAttribubte(key)

// 请求转发
// forward(request,response) 是固定写法 
request.getRequestDispatcher("转发地址").forward(request,response)    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

二.response响应

// 重定向
response.sendRedirect()
  • 1
  • 2

三.请求转发和重定向区别

转发 重定向
地址栏不会发生变化 地址发生变化
请求一次 请求两次
携带请求 不携带请求
作用域web程序(不能转发到程序以外的界面) 任意的地址(URL)都可以重定向

转发:

图片.png

重定向:

get与post的区别

比较项 Get Post
参数是否出现在url(地址栏)中
安全性
URL可传播
长度限制

四.示例

登录界面

<form action="" method="get">
    <p>
      用户名: <input type="text" name="name">
    </p>
    <p>
      密码: <input type="password" name="pwd">
    </p>
    <p>
      <input type="submit" value="登录">
    </p>
  </form>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

处理请求页面

 // 2.接收参数
    String name = request.getParameter("name");
    String pwd = request.getParameter("pwd");

    // 3.验证密码是否正确
    String uname = "渣渣辉";
    String upwd = "123456";

    if (name.equals(uname) && pwd.equals(upwd)){

        // 存储数据  键值对  key value
        request.setAttribute("name",name);//存储一次数据
        //对应下方欢迎界面的get

        // 4.进行请求转发
        request.getRequestDispatcher("").forward(request,response);
    }else{
        // 5.正常情况下密码错误 回到
                            //("").forward(request,response);
        // 使用重定向
        response.sendRedirect("");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

欢迎界面

<%--如果没有数据会出现空指针异常所以要判空   得到的数据是object类型 所以要进行数据类型转换--%>
<h1>
    欢迎你 <%= request.getAttribute("name") == null ? "" : //获取这一次值时进行判空
    (String) request.getAttribute("name")%> //强转
</h1>
  • 1
  • 2
  • 3
  • 4
  • 5

session

作用域: 一次会话中实现数据共享

request

作用域: 只在一次请求实现数据传递

session.getAttribute()
session.setAttribute()    
// 设置有效期 和获取有效期 s:秒
session.setMaxInactiveInterval()
// 获取有效期
session.getMaxInactiveInterval()
// 清除session数据
session.invalidate();    
// 删除session属性
session.removeAttribute()
// 在中设置session有效期   m:分  
<session-config>
   <session-timeout>1</session-timeout>
</session-config>    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

application

作用域: 整个web程序之间实现数据共享

application.getAttribute()
application.setAttribute()    
  • 1
  • 2
<%
int count = 0 ;//初始化
  if(application.getAttribute("count")==null){
    count++;//第一次进入这个页面,给你设置为1
    application.setAttribute("count",count);
  }else{//只要不是第一次进入这个页面,获取你的值,++,然后再设置
    count = (int) application.getAttribute("count");
    count++;
    application.setAttribute("count",count);
  }
%>  
<h1>欢迎您能在百忙之中莅临本站,<%=count%>号客人</h1>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

cookie

作用域: 以文件的形式保存数据到浏览器(客户端)中

并且只能存字符串,

// 添加cookie
response.addCookie(Cookie cookie)
// 创建cookie对象
Cookie cookie = new Cookie("key",value)
// 设置cookie有效期
cookie.setMaxAge() //s:秒
// 获取cookie
Cookie[] request.getCookie()    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

JDBC

illust_75987050_20191015_145225.png

Java DataBase Connectivity(Java 语言连接数据库)

  • 本质

    JDBC是SUN公司制定的一套接口(interface)

    –原因就是因为每一个数据库都有自己的实现原理,为了方便连接数据库,方便使用跟书写代码

    接口都有调用者与实现者

    面向接口调用,面相接口写实现类这都属于面向接口编程

  • 为什么要面向接口编程?

    降低程序的耦合性,提高程序的可读性跟拓展性

    多态机制就是典型的面相抽象编程

    例如:

    建议:

    Animal a = new Cat();

    Animal a = new Dog();

    //喂养的方法

    public void feed(Animal a){

    }

    不建议:

    Dong d = new Dog();

    Cat c = new Cat();

单例模式(2种)

    懒汉模式:

        线程不安全    同步锁

        延迟加载    调用时才会产生实例

    饿汉模式:

        线程安全    不具备延迟加载特性

        当虚拟机加载时直接创建好对象

        不管什么时候过来都直接返回创建好的对象
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

数据源以及分层开发

illust_76320407_20191015_193917.jpg

数据源

由于JDBC在访问数据库数据的时候会有效率低,安全性差,稳定性差的问题,所以java给出了连接池与数据源解决的方案.

  • 连接池的工作原理

  • JNDI :

      配置    tomcat数据源   
    
    • 1
<!-- 配置Tomcat的conf/context.xml  -->
    <!--想要获取tomcat集成的dbcp连接池  使用接口可以接收  -->
    <!--
        name:自行设置  唯一
        auth:Container 固定 容器来托管数据源
        type:javax.sql.DataSource 当服务器启动的时候 会自动帮你创建一个DataSource数据源的实现类
        maxActive:最大活跃 (最大连接)
        maxIdle:最大闲置(备胎)
        maxWait:最大等待时间 
        username:数据库用户名
        password:数据库密码
        driverClassName:驱动名称
        url:数据库地址

        & :与符号&
        useUnicode=true&characterEncoding=utf-8 防止项目编码和数据库编码不一致的情况  统一采用UTF-8
    -->
    <Resource name="jdbc/news" auth="Container" type=""
      maxActive="100" maxIdle="30" maxWait="10000" username="root"
      password="root" driverClassName=""
      url="jdbc:mysql://127.0.0.1:3306/kgcnews?
              useUnicode=true&characterEncoding=utf-8" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
    引用    连接池代码   (获取连接对象) 
  • 1
    public static void getConnection() throws Exception{
        // 1.加载驱动
        Class.forName(driver);
        // 2.获取连接对象
        //conn = (url,username,password);
        // 通过连接池技术获取连接对象 每次关闭连接对象时并不会关闭掉  而是让连接对象返回到连接池
        // 以下是重点
        Context context = new InitialContext();
        DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/news");
        conn = dataSource.getConnection();

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

分层开发

层与层之间是依赖关系 dao -> service -> jsp

  • 第一层:

      dao: 数据访问层
    
    • 1
  • 第二层:

      service: 业务逻辑层
    
    • 1
  • 第三层:

      jsp: 访问层(展示与控制页面)
    
    • 1

    以后会分出来: controller: 控制层

以下是代码演示

  • 登录

分析: 输入完用户名 密码 点击登录

验证 接收form表单中的信息

// 字符编码
 request.setCharacterEncoding("utf-8");
 // 接收参数
 String uname = request.getParameter("uname");
 String upassword = request.getParameter("upassword");

 // 去找userDao 帮我们去数据库查询
 UserDao userDao = new UserDaoImpl();
 // 查询用户名密码是否正确
 User user = userDao.login(uname,upassword);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.创建数据访问层 UserDao 的UserDaoImpl 实例 访问数据库查询是否有数据

public User login(String uname, String upassword) {
 User user = null;
 // 1.写sql语句
 String sql = " select * from news_user where userName = ? and password = ? ";
 // 2.执行
 try {
 select(sql,uname,upassword);
 // 3.遍历结果集
 while (rs.next()){
 int id = rs.getInt("id");
 String userName = rs.getString("userName");
 String password = rs.getString("password");
 String email = rs.getString("email");
 int userType = rs.getInt("userType");
 user = new User(id,userName,password,email,userType);
 }
 } catch (Exception e) {
 e.printStackTrace();
 }finally {
 try {
 closeAll();
 } catch (Exception exception) {
 exception.printStackTrace();
 }
 }
 return user;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

3.实现跳转

//3. 实现跳转
if (user == null){
      // 提示用户名密码输入错误
      request.setAttribute("msg","用户名或者密码错误!");
      request.getRequestDispatcher(request.getContextPath()+"/").forward(request,response);
  }else{
      // 重定向
      session.setAttribute("user",user);
      response.sendRedirect(request.getContextPath()+ "/pages/");
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 注销

$(".fr").click(function (){
    location.href = "../controller/"
})
  • 1
  • 2
  • 3

2.点击注销按钮

// 实现注销功能
  session.removeAttribute("user");
  response.sendRedirect("../");
  • 1
  • 2
  • 3
  • 查询列表

1.当进入到admin界面

// 当进入此页面的时候应该去后台将新闻列表查询出来
    List<NewsDetail> newsList = (List<NewsDetail>) session.getAttribute("newsList");
    // 如果没有获取到 说明还没去查询
    if (newsList == null || newsList.size() == 0){
        response.sendRedirect(request.getContextPath()+"/controller/");
        return;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.控制跳转

// 查询新闻列表
    NewsDetailService newsDetailService = new NewsDetailServiceImpl();


    List<NewsDetail> newsList = newsDetailService.findNewsList();

    session.setAttribute("newsList",newsList); // 设置数据到作用域中
    // 跳转
    request.getRequestDispatcher(request.getContextPath()+"/pages/").forward(request,response);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

查询新闻列表

public List<NewsDetail> findNewsList() {
        List<NewsDetail> newsList = new ArrayList<>();
        String sql = " select * from news_detail ";
        try {
            select(sql);
            while (rs.next()){
                int id = rs.getInt("id");
                int categoryId = rs.getInt("categoryId");
                String title = rs.getString("title");
                String summary = rs.getString("summary");
                String content = rs.getString("content");
                String picPath = rs.getString("picPath");
                String author = rs.getString("author");
                Date createDate = rs.getDate("createDate");
                Date modifyDate = rs.getDate("modifyDate");
                NewsDetail newsDetail = new NewsDetail(id,categoryId,title,summary,content,picPath,author,createDate,modifyDate);
                newsList.add(newsDetail);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                closeAll();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return newsList;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

4.数据展示

<%
    for (NewsDetail newsDetail : newsList) {
        %>
            <tr class="admin-list-td-h2">
                <td>
                <a href='?id=2'><%=newsDetail.getTitle()%></a>
                </td>
                <td><%=newsDetail.getAuthor()%></td>
                <td><%=newsDetail.getModifyDate() != null ? format.format(newsDetail.getModifyDate()):""%></td>
                <td>
                <a href='?id=2'>修改</a>
                <a href="javascript:if(confirm('确认是否删除此新闻?')) location='?id=2'">删除</a>
                </td>
                </tr>
                <%
    }
%>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

补充: 解决404路径问题

​ 1. 清除idea缓存与重启

​ 2. 设置绝对路径

​ 3. 更改浏览器地址栏路径

根据id删除新闻流程

illust_76545259_20191015_165650.jpg

一.点击删除新闻界面

关键代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFhKVjcx-1640771308145)(/imgs/2021/12/)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-91kOHz2t-1640771308146)(/imgs/2021/12/)]

二.删除控制页jsp

<%
    // 接收id
    String id = request.getParameter("id");
    System.out.println(id);

    // 根据id 去删除新闻
    NewsDetailService newsDetailService = new NewsDetailServiceImpl();
    int result = newsDetailService.deleteNewsById(id);
    if (result > 0){

        out.write("<script type='application/javascript' >");
        out.write("alert('删除成功!'); ");
        out.write(" = ''; ");
        out.write("</script>");

    }else if(result == 0){
        out.write("<script type='application/javascript' >");
        out.write("alert('没有要删除的新闻了!'); ");
        out.write(" = ''; ");
        out.write("</script>");
    }else{
        out.write("<script type='application/javascript' >");
        out.write("alert('删除失败,系统异常,请重试!'); ");
        out.write(" = ''; ");
        out.write("</script>");
    }


%>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

三.业务逻辑层关键代码

 @Override
    public int deleteNewsById(String id) {
        int newsRow = 0;
        Connection conn = null;
        try {
            conn = BaseDao.getConnection();
            // 1. 开启事务
            conn.setAutoCommit(false);  // 关闭自动提交
            // 2.删除相关评论
            int commentRow = newsCommentDao.deleteCommentByNewsId(id);
            if (commentRow >= 0){
                // 3.删除新闻
                newsRow = newsDao.deleteNewsById(id);
            }

            // 如果没有异常提交
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
            // 4.如果出现异常 回滚
            try {

                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }finally {
            // 5.开启自动提交
            try {
                if (conn != null) {
                    conn.setAutoCommit(true);
                    // 一次性关闭
                    BaseDao.closeAll();
                }
            } catch (Exception throwables) {
                throwables.printStackTrace();
            }
        }

        return newsRow;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

四.数据库工具类的一些修改 原本的连接池改为了单例获取对象

 // 2.获取连接对象   ():连接对象是关闭状态也要创建对象
if (conn == null || conn.isClosed()){
    conn = DriverManager.getConnection(url,username,password);
}
return conn;
  • 1
  • 2
  • 3
  • 4
  • 5

五.数据访问层关键代码

评论

@Override
public int deleteCommentByNewsId(String id) {

    String sql = " delete from news_comment where newsId = ? ";
    try {
        return update(sql, id);
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

新闻

@Override
public int deleteNewsById(String id) {
    String sql = " delete from  news_detail where id = ? ";

    try {
        return update(sql, id);
    } catch (Exception e) {
        e.printStackTrace();
        return -1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

每日一测

//1、写出的获取参数方法、获取cookie的方法、获取HttpSession的方法、转发的方法

获取参数方法:
    String getParameter(String name)
    String[] getParameterValues(String name)

获取cookie的方法:
    Cookie[]  getCookies()

获取HttpSession的方法:
    HttpSession getSession()
    HttpSession getSession(boolean create)

转发的方法:
    RequestDispatcher getRequestDispatcher(java.lang.String path)
    request.getRequestDispatcher(url).forward(request,response)

//2、写出的重定向的方法,添加cookie对象的方法

重定向的方法:
    void sendRedirect(String url)

添加cookie对象的方法:
    void addCookie(Cookie cookie)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

第三方控件

illust_77187069_20191011_122317.jpg

1.文件上传

  1. 在form表单里添加一个文件域
  2. 修改form表单的enctype属性: application/x-www-form-urlencoded(键值对name-value)->multipart/form-data(文件项)
  3. 修改form表单请求方式改为post
    1. 原因: 理论上post没有上传大小限制
<form action= "" method="post" enctype="multipart/form-data">
    <p>内容...</p>
    </form>
  • 1
  • 2
  • 3
  • 需要导入和img

  • 使用commons-fileupload组件进行文件接收

//核心1.创建文件项工厂
FileItemFactory fif = new DiskFileItemFactory();
//核心2.工人进驻工厂
ServletFilrUpload upload = new ServletFileUpload(fif);
// 额外功能1:限制上传文件大小(单位字节byte)   30kb = 30*1024;
upload.setSizeMax(30*1024);
// 核心3:判断是否符合上传要求:enctype="multipart/form-data"和method="post" 
if(ServletFileUpload.isMultipartContent(request)){
// 核心4:解析请求并转换为文件项集合
List<FileItem> fileItemList  = upload.parseRequest(request);
// 核心5:遍历所有的文件项
for(FileItem fileItem : fileItemList){
// 核心6:判断当前文件项是否是普通表单(表单分为:普通表单type=text...   文件域表单:type=file)
if(fileItem.isFormField()){ // 如果是普通表单则为true
// 获取表单的name值
String name = fileItem.getFieldName();
// 获取普通表单的value值
// String value = ();
String value = fileItem.getString("UTF-8"); // 解决中文乱码
System.out.println("普通表单:name属性值:"+name+"  value属性值:"+value);
					}else{ // 文件域表单
						// 获取表单的name值
						String name = fileItem.getFieldName(); 
						// 额外功能2:文件类型限制------------------------------------------
						List<String> extensionList = Arrays.asList("jpg","png","jpeg");
						// 核心7:获取文件名(如果是普通表单文件项调用返回null)
						String fileName = fileItem.getName(); // 
						/* String extension = ((".")+1); */
						String extension = FilenameUtils.getExtension(fileName); // commons-io里的工具类
						System.out.println("文件扩展名为:"+extension);
						if(extensionList.contains(extension)){
							// 额外功能3:解决文件名重复引起的覆盖问题
							String newFileName = System.currentTimeMillis()+"_header."+extension;
// 最核心:文件上传
File file = new File("d:/"+newFileName); // 指定文件地址
fileItem.write(file);
out.print("文件上传成功!");
}else{
out.print("不支持此类文件格式!支持的文件格式有:jpg,png,jpeg");
						}
					}
				}
			}else{
				out.print("非法文件上传!");
			}
		}catch(FileUploadBase.SizeLimitExceededException e){
			out.print("文件上传超过大小限制!");
		}catch(Exception e){
			out.print("上传失败!请重试!");
		}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

分页查询

illust_76935296_20191015_165259.jpg

分页查询所需数据

1.每页显示多少条数据 pageSize

2.总共有多少条数据 totalCount

3.当前页 pageNo

4.本页查询到的数据 List result

5.总共有多少页 totalPage

6.起始下标 startIndex

代码

  • 分页工具类代码
package cn.kgc.util;

import java.util.List;

/**
 * 分页查询工具类
 */
public class PageBean<T> {
    /**每页显示的条数*/
    private Integer pageSize;
    /**当前页*/
    private Integer pageNo;
    /**总记录数*/
    private Integer totalCount;
    /**起始下标*/
    private Integer startIndex;
    /**总页数*/
    private Integer totalPage;
    /**
     *查询到的结果 T:代表泛型是任意类型 这个类型归当前类来约束
     *当此类的泛型是啥的时候那么返回的列表泛型必须是啥
     */
    private List<T> result;

    public Integer getPageNo() {
        return pageNo;
    }

    public void setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public Integer getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(Integer totalCount) {
        this.totalCount = totalCount;
    }

    public Integer getStartIndex() {
        // 计算出起始下标  (当前页-1)*每页显示的条数
        startIndex = (pageNo-1)*pageSize;
        return startIndex;
    }

    public void setStartIndex(Integer startIndex) {
        this.startIndex = startIndex;
    }

    public Integer getTotalPage() {
        totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
        return totalPage;
    }

    public void setTotalPage(Integer totalPage) {
        this.totalPage = totalPage;
    }

    public List<T> getResult() {
        return result;
    }

    public void setResult(List<T> result) {
        this.result = result;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 页面
    // 查询新闻列表
    NewsDetailService newsDetailService = new NewsDetailServiceImpl();
    // 设置起始页  如果前台没有传递参数  就代表你是第一次进入前台 肯定查询的第一页
    // 将字符串类型转化为integer类型
    Integer pageNo  = ("pageNo") == null ? 1 : (("pageNo"));
    // 设置每页显示的条数
    Integer pageSize = 5;
    // 进行分页查询
    PageBean<NewsDetail> newsPage =(pageNo,pageSize);

    // 设置数据到作用域中
    ("newsPage",newsPage);
    // 跳转
    ("../pages/").forward(request,response);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • newsDetailService类关键代码
/**
     * 分页查询业务
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public PageBean<NewsDetail> getNewsPage(Integer pageNo, Integer pageSize) {
        PageBean<NewsDetail> newsPage = new PageBean<NewsDetail>();
        newsPage.setPageSize(pageSize);
        newsPage.setPageNo(pageNo);
        // 分页业务代码
        // 1.查询总记录数
        int count = newsDao.getCount();
        newsPage.setTotalCount(count);
        // 2.查询分页的结果集
        List<NewsDetail> newsList = newsDao.getNewsList(newsPage.getStartIndex(),newsPage.getPageSize());
        newsPage.setResult(newsList);
        // 最终都存入到pageBean 返回

        return newsPage;
    }/**
     * 分页查询业务
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public PageBean<NewsDetail> getNewsPage(Integer pageNo, Integer pageSize) {
        PageBean<NewsDetail> newsPage = new PageBean<NewsDetail>();
        newsPage.setPageSize(pageSize);
        newsPage.setPageNo(pageNo);
        // 分页业务代码
        // 1.查询总记录数
        int count = newsDao.getCount();
        newsPage.setTotalCount(count);
        // 2.查询分页的结果集
        List<NewsDetail> newsList = newsDao.getNewsList(newsPage.getStartIndex(),newsPage.getPageSize());
        newsPage.setResult(newsList);
        // 最终都存入到pageBean 返回

        return newsPage;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 数据库查询关键代码
 @Override
    public int getCount() {
        int count = 0;
        String sql = " select count(*) from news_detail ";
        try {
            select(sql);

            while (rs.next()){
                count = rs.getInt(1);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                closeAll();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return count;
    }

    @Override
    public List<NewsDetail> getNewsList(Integer startIndex, Integer pageSize) {
        List<NewsDetail> newsList =  new ArrayList<>();
        String sql = " select * from news_detail limit ?,?  ";
        try {
            select(sql,startIndex,pageSize);
            while (rs.next()){
                int id = rs.getInt("id");
                int categoryId = rs.getInt("categoryId");
                String title = rs.getString("title");
                String summary = rs.getString("summary");
                String content = rs.getString("content");
                String picPath = rs.getString("picPath");
                String author = rs.getString("author");
                Date createDate = rs.getDate("createDate");
                Date modifyDate = rs.getDate("modifyDate");
                NewsDetail newsDetail = new NewsDetail(id,categoryId,title,summary,content,picPath,author,createDate,modifyDate);
                newsList.add(newsDetail);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                closeAll();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return newsList;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 接收数据
// 接收分页查询到的数据
	PageBean<NewsDetail> newsPage = (PageBean<NewsDetail>) request.getAttribute("newsPage");
  • 1
  • 2
  • 遍历数据
<%
							for (NewsDetail newsDetail : newsPage.getResult()) {

								%>
									<tr class="admin-list-td-h2">
										<td>
											<a href='?id=2'><%=newsDetail.getTitle()%></a>
										</td>
										<td><%=newsDetail.getAuthor()%></td>
										<td><%=newsDetail.getModifyDate() != null ? format.format(newsDetail.getModifyDate()):""%></td>
										<td>
											<a href='?id=2'>修改</a>
											<%--  get请求 请求携带参数是的衔接符号 ? 多个参数用 & 符号隔离  --%>
											<a href="javascript:=' <%=()%>/controller/?id=<%=()%> '" >删除</a>

										</td>
									</tr>
								<%
							}
						%>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 完成上下页跳转
<ul class="page-num-ul clearfix">
	<li><%=newsPage.getTotalCount()%>条记录&nbsp;&nbsp; <%=newsPage.getPageNo()%>/<%=newsPage.getTotalPage()%></li>
	<a href="javascript:='<%=()%>/controller/?pageNo=1'">首页</a>
		<%
			if (newsPage.getPageNo() > 1){
				%>
					<a href="javascript:='<%=()%>/controller/?pageNo=<%=()-1 %>'">上一页</a>
				<%
			}
			if (newsPage.getTotalPage() > newsPage.getPageNo()){
				%>
					<a href="javascript:='<%=()%>/controller/?pageNo=<%=()+1 %>'">下一页</a>
				<%
			}
		%>
	<a href="javascript:='<%=()%>/controller/?pageNo=<%=() %>'">最后一页</a>&nbsp;&nbsp;
</ul>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 实现页面跳转
<button type="button" class="page-btn" onClick="jump_to([1],('inputPage').value)">GO</button>
  • 1
function jump_to(form,num){
    // 页数不能小于1 不能大于总页数
    var totalPage = $("input[name='totalPage']").val()
    if (num >  totalPage){
        alert("输入的页数不能大于"+totalPage)
    }else if (num < 1){
        alert("输入的页数不能小于于1")
    }else{
        // 设置pageNo的值
        $("input[name='pageNo']").val(num)
        // 提交表单
        form.submit()
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

El与JSTL

由于jsp脚本还有一些不足的地方:

  • 代码结构混乱
  • 脚本与HTML混合,容易出错.
  • 代码不易维护

所以为了解决这些不足,出现了El表达式与JSTL

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5K2XSYDc-1640771308150)(/imgs/2021/12/)]

El功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zi1fb0oD-1640771308151)(/imgs/2021/12/)]

EL表达式的用法

 <%--用el表达式来获取值--%>
  ${name}
 <%-- ${age}--%>

  <%--获取对象的属性  直接写属性名 --%>
  <%-- el表达式获取对象的值  前提条件是通过get方法获取的set设置参数--%>
  ${}
  ${}
  ${}

  <%--获取列表中的值--%>
  ${userList[0].name}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

EL表达式运算符

${empty  }  判空
${ ! && || }  逻辑
${ ()  += - * /  }   运算
  • 1
  • 2
  • 3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVZ5zhsM-1640771308151)(/imgs/2021/12/)]

JSTL基础:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSgEZ5pc-1640771308152)(/imgs/2021/12/)]

标签/导入方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gqm4G4I2-1640771308153)(/imgs/2021/12/)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TsAtIHGQ-1640771308154)(/imgs/2021/12/)]

JSTL用法

<c:if test="${empty name}">
        没有这个名字
    </c:if>

  out标签  向页面输出
        escapeXml
        false : 转义
        true : 不转义
    
  <c:out value="<h1>Hello jstl</h1>" default="hello" escapeXml="true"/>


    <%--设置变量--%>
    <c:set var="name" value="吴昊铭" scope="request"/>


            <%--
    var:遍历出来的每一项
    items: 要遍历的集合
    varStatus:索引下标
        count:从1开始 计数
        index:从0开始 下标
    begin:从什么地方开始遍历
    end:到什么地方结束
    step:步长
    --%>
<c:forEach var="str" items="${list}" varStatus="stat"  >
    ${}
    ${str}
</c:forEach>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 上课代码
<%@ page import="" %>
<%@ page import="" %>
<%@ page import="" %><%--
  Created by IntelliJ IDEA.
  : 10044
  Date: 2021/12/27
  Time: 17:00
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导包--%>
<%@taglib uri="/jstl/core_rt" prefix="c" %>
<%@taglib uri="/jsp/jstl/fmt" prefix="f"%>
<html>
<head>
    <title>Title</title>
</head>
<body>

<c:if test="${empty name}">
  没有这个名字
</c:if>
<%--if判断结构,代表如果name为空...--%>
<%--test:判断的表达式--%>

<%--<c:out value="<h1>Hello jstl</h1>" default="hello" escapeXml="true"/>--%>
<%--false与 true表示 转义与不转义(对前面的语句进不进行转义)--%>

<%--设置变量--%>
<%--<c:set var="name" value="红细胞" scope="request"/>

${name}--%>
<%-- <%
     User user = new User();
     ("user",user);
 %>--%>

<%--<c:set target="${user}" property="name" value="细胞"/>
&lt;%&ndash;获取对象的值&ndash;%&gt;
${}--%>

<%--遍历集合--%>
<%
    List<String> list = new ArrayList<>();
    ("血细胞");
    ("白细胞");
    ("细菌");
    ("抗体");
    ("抗原");
    ("list", list);
%>
<%--
var:遍历出来的每一项
items: 要遍历的集合
varStatus:索引下标
    count:从1开始 计数
    index:从0开始 下标
begin:从什么地方开始遍历
end:到什么地方结束
step:步长
--%>
<c:forEach var="str" items="${list}" varStatus="stat"  >
    ${}
    ${str}
</c:forEach>


<%--<table>
    <c:forEach begin="0" end="10" varStatus="stat">
        <c:if test="${ % 2 == 0}">
            <tr style="color: red">
                <td>Hello </td>
            </tr>
        </c:if>
        <c:if test="${ % 2 != 0}">
            <tr style="color: chartreuse">
                <td>Hello </td>
            </tr>
        </c:if>

    </c:forEach>
</table>--%>

<%--超链接标签--%>
<%--<a href="<c:url value=""/>">跳转</a>--%>

<%--导入标签--%>
<%--<c:import url=""/>--%>
<%--参数标签--%>
<%--<c:param name="name"  value="神经元" />

<c:out value="${}"    />--%>

<%
    Date date = new Date();
    // 创建格式化对象 .format()
    ("date", date);

    ("number", "7758521");
%>

<f:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"/>
<f:formatNumber value="${number}" pattern="0.3"/>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

制作隔行变色效果

<table>
        <c:forEach begin="0" end="10" varStatus="stat">
            <c:if test="${ % 2 == 0}">
                <tr style="color: red">
                    <td>Hello </td>
                </tr>
            </c:if>
            <c:if test="${ % 2 != 0}">
                <tr style="color: chartreuse">
                    <td>Hello </td>
                </tr>
            </c:if>

        </c:forEach>
    </table>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lsVzIeQ7-1640771308155)(/imgs/2021/12/)]

Servlet与过滤器and监听器

servlet

什么是Servlet?

servlet就是一种在服务器端运行的java小程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ypIdYeuu-1640771308156)(/imgs/2021/12/)]

运行原理示意图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPGx5SM1-1640771308157)(/imgs/2021/12/)]

Servlet与Jsp之间的关系(父子关系)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbfOZ0lY-1640771308158)(/imgs/2021/12/)]

servlet的三种实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HK2lbQ0u-1640771308159)(/imgs/2021/12/)]

1.实现servlet接口
public class MyController implements Servlet {
    //  最原始的servlet   包含了Servlet所有方法
    /**
     * 初始化
     * @param servletConfig
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("初始化了");
    }
}    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
2.继承genericServlet补充
/**
 * 第二种写servlet的方式  抽象了  默认实现了servlet接口
 *  为你实现了其他的所有方法 只保留了一个 servlet
 */
public class MyController1 extends GenericServlet {
    /**
     * 只有一个方法了
     * 请求和响应有很多中   我们只做 http请求
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
3.继承HttpServlet
/**
 *  servlet的最终形态
 *      第一形态: 实现servlet接口  里面的所有方法都需要实现
 *      第二形态:  继承GenericServlet  将一些方法默认实现了
 *                只保留了一个service 可以处理servlet的所有请求方式:  http ftp ....
 *                因为我们javaServlet只做http请求
 *       第三形态 : 继承 http Servlet
 *                 http协议的请求 :
 *                  service方法包含很多请求    get post put delete  ....
 *                 我们专门处理的一般都是get 和 post
 *
 *                 最终版: 不去实现service方法
 *                        重写doGet 和 doPost方法
 *                        由于你也不太清除啥时候是get请求 啥时候是post请求
 *                        所以我们要让所有的亲求都经历get和post方法
 */
public class MyServlet extends HttpServlet {

    public MyServlet() {
        System.out.println("构造方法执行了");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 以后所有的代码写在这
        String name = req.getParameter("name");
        System.out.println(name);

        System.out.println("执行了servlet  doGet请求");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        doGet(req,resp);
        System.out.println("执行了servlet doPost请求");
    }

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("servlet 初始化了");
    }

    @Override
    public void destroy() {
        super.destroy();
        System.out.println("servlet 销毁了");
    }
    /**
     * 专门处理http协议的请求
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    /*@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ("service 方法执行了");
    }*/
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
编写请求
<%--请求--%>
  <form action="myServlet" method="post">

    <p>
      用户名: <input type="text" name="name">
    </p>
    <p>
      <input type="submit" value="提交">
    </p>
  </form>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
编写–(参数初始化)
<!--编写一个servlet-->
    <servlet>
        <servlet-name>myServlet</servlet-name>
        <servlet-class></servlet-class>
    </servlet>
    <!--编写一个servlet的映射 将用户的url请求 映射道某个servlet类中 -->
    <servlet-mapping>
        <servlet-name>myServlet</servlet-name><!--被映射的类-->
        <url-pattern>/myServlet</url-pattern> <!--用户的请求url-->
    </servlet-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
Servlet生命周期

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MDuvCASh-1640771308160)(/imgs/2021/12/)]

web请求业务流程

img

总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rgw8M5OP-1640771308161)(/imgs/2021/12/)]

过滤器

概念与实现原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sD6hMkWG-1640771308162)(/imgs/2021/12/)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3GoNYH03-1640771308163)(/imgs/2021/12/)]

实现:
1.编写过滤器类
  • (导包时注意要导这个包)
package cn.kgc.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
        String characterEncoding = null;
        /**
         * 初始化 : 当程序启动时
         * @param filterConfig
         * @throws ServletException
         */
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
              // 当程序初始化的时候
              characterEncoding = filterConfig.getInitParameter("characterEncoding");
        }

        /**
         *  每次有请求和响应都会经过此方法
         * @param servletRequest
         * @param servletResponse
         * @param filterChain
         * @throws IOException
         * @throws ServletException
         */
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                // 请求的时候设置请求的字符编码 响应的时候设置响应的字符编码
                if (servletRequest != null){
                        // 设置post请求的字符编码
                        servletRequest.setCharacterEncoding(characterEncoding);
                }
                if (servletResponse != null){
                        // 设置响应的字符编码
                        servletResponse.setCharacterEncoding(characterEncoding);
                        // 响应一个页面
                        servletResponse.setContentType("text/html;charset="+characterEncoding);
                }


                // 放行
                filterChain.doFilter(servletRequest,servletResponse);
        }

        /**
         * 销毁
         */
        @Override
        public void destroy() {

        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
2.编写
    <!--配置过滤器-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class></filter-class>
        <!--配置初始化参数-->
        <init-param>
            <param-name>characterEncoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!--让所有的请求去找这个过滤器   完全匹配中: /    匹配目录 : /admin/*   匹配某些类型的请求: /*.do  匹配所有的请求: /*-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
过滤器应用场合:

监听器

  • 作用: 在web程序种 一旦servletContext httpSession servletRequest 对象发生状态改变 就会被监听
统计用户实时登录人数监听器实现思路:
1.编写全局上下文监听器 在项目初始化的时候触发
/**
 * 应用程序上下文监听器
 */
public class OnlineUserListListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {

        System.out.println("上下文监听器已经初始化了");
        List<User> userList = new ArrayList<>();
        sce.getServletContext().setAttribute("ONlIST_USER",userList);


    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
2.为要被操作用户类 实现感知型监听器 当对象被添加到session作用域 就会调用valueBound()方法 当用户对象在session作用域中被删除调用valueUnbound()方法
/**
     * 当session 添加数据时会调用
     * @param event
     */
    @Override
    public void valueBound(HttpSessionBindingEvent event) {


        // 获取application 对象
        ServletContext application = event.getSession().getServletContext();
        // 把当前的用户对象存入application作用域列表中
        List<User> userList = (List<User>) application.getAttribute("ONlIST_USER");
        userList.add(this);
        System.out.println("当前登录的用户是:"+this.getUserName()+"已被添加到用户列表中");
        System.out.println("上线一人,当前人数是:"+userList.size()+"人!");
    }

    /**
     * 当session 销毁或者删除数据时会调用
     * @param event
     */
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {

        ServletContext application = event.getSession().getServletContext();

        List<User> userList = (List<User>) application.getAttribute("ONlIST_USER");
        userList.remove(this);
        System.out.println("当前下线的用户是:"+this.getUserName()+"已被删除到用户列表中");

        System.out.println("下线一人,当前人数是:"+userList.size()+"人!");
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
常用的监听器

mvc设计模式

model1

view + controller -> jsp

model -> service+ dao + entity

model2

view -> jsp

controller -> servlet

model -> service + dao + entity

JavaWeb重点补充

illust_75910823_20191015_170658.jpg

jsp脚本

1.编写脚本的位置
<%  %>
2.输出语句
<%=%>
out.print()
3.成员变量 成员方法   在_jspService方法外面
<%! int a = 10; public void show(){}  %>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

request

1.获取表单数据
String request.getParameter()
2.获取多个相同name的表单数据
String[] request.getParameterValues()
3.存取作用域属性  
Object request.getAttribute()
request.setAttribute()
4.设置字符编码
request.setCharacterEncoding()
5.请求转发
request.getRequestDispatcher().forward(request,response)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

response

1.重定向
response.sendRedirect()
  • 1
  • 2

session

1.设置作用域属性
session.setAttribute()
2.获取作用域属性
session.getAttribute()
3.删除属性   
session.removeAttribute()
4.清除session属性
session.invalidate()
5.设置session有效期
session.setMaxInactiveInterval(int interval); 
6.获取sessionid
session.getId()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

cookie

1.获取cookie    request  
Cookie[] getCookies()
2.添加cookie    response
addCookie(Cookie cookie)
3.这只cookie的有效期 s:setMaxAge()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

application

1.存取作用域属性
application.getAttribute()
application.setAttribute()    
  • 1
  • 2
  • 3

四大作用域的区别

request response session application
一次请求 一次请求 一次会话中包含多次请求 整个app应用程序,所有数据都能 共享

JDBC

1.加载驱动
Class.forName("")
2.获取连接对象
String url = "jdbc:mysql://localhost:3306/数据库名?useUnicode=true;&charactorEncoding=utf-8";
Connection conn = DriverManager.getConnection(url,"root","root")
3.获取语句执行者对象
Statement state = conn.createStatement()
state.executeQuery()
state.executeUpdate()
4.有预编译的执行者对象
PreparedStatement prep = conn.prepareStatement(String sql)   
设置参数
prep.setxxx(1,"")
5.执行sql语句获取结果集    
ResultSet rs = prep.executeQuery()
int row = prep.executeUpdate()
6.遍历结果集
rs.next()  判断是否有下一个元素
rs.getxxx()  获取元素
7.关流
xxx.close()
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

dao模式

BaseDao
1. 获取连接封装
public static  Connection getConnection() throws Exception{
        // 1.加载驱动
        Class.forName(driver);
        // 2.获取连接对象   ():连接对象是关闭状态也要创建对象
        if (conn == null || conn.isClosed()){
            conn = DriverManager.getConnection(url,username,password);
        }
        return conn;
        // 通过连接池技术获取连接对象 每次关闭连接对象时并不会关闭掉  而是让连接对象返回到连接池
        /*Context context = new InitialContext();
        DataSource dataSource = (DataSource) ("java:comp/env/jdbc/news");
        conn = ();*/

    }
2. 通用的增删改
public static int update(String sql,Object...obj) throws Exception{
        getConnection();
        ps = conn.prepareStatement(sql);
        if (obj != null){
            for (int i = 0; i < obj.length; i++) {
                ps.setObject((i+1),obj[i]);
            }
        }
        return ps.executeUpdate();
    }
3. 通用的查询
public static void select(String sql,Object...obj) throws Exception{
        getConnection();
        ps = conn.prepareStatement(sql);
        if (obj != null){
            // 设置参数
            for (int i = 0; i < obj.length; i++) {
                ps.setObject((i+1),obj[i]);
            }
        }
        rs = ps.executeQuery();
    }

4. 通用的关流
public static  void closeAll() throws Exception{
        if (rs != null){
            rs.close();
        }
        if (ps != null){
            ps.close();
        }
        if (conn != null){
            conn.close();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

配置文件

# 链接地址
url=jdbc:mysql://localhost:3306/kgcnews?useUnicode=true&characterEncoding=utf-8
# 驱动
driver=
# 用户名
username=root
#密码
password=root
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

读取配置文件

static{
        //部署项目 -> tomcat -> 被编译后的文件
        // 读取配置文件获取io流  通过类加载器加载配置文件成为输入流
        InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("");
        Properties prop = new Properties();
        try {
            prop.load(is);// 通过输入流加载配置文件对象
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 通过key 获取值
        url = prop.getProperty("url");
        driver = prop.getProperty("driver");
        username = prop.getProperty("username");
        password = prop.getProperty("password");

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

单例模式

1.饿汉模式 Single
	私有化构造
    private Single(){}
    私有化静态属性创建对象
    private static Single single = new Single();
    公共的获取实例的方法返回对象 
    public static Single getInstence(){
    	return single;
    }

2.懒汉模式
	私有化构造
    private Single(){}
    私有化静态属性
    private static Single single;
    公共的获取实例的方法 有线程问题加线程同步锁
    public static Single getInstence(){
    	if(single != null){
        	return single;
        }else{
        	return new Single;
        }
    	
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

连接池

1.修改timcat中conf/

<!--
		name:自行设置  唯一
		auth:Container 固定 容器来托管数据源
		type: 当服务器启动的时候 会自动帮你创建一个DataSource数据源的实现类
		maxActive:最大活跃 (最大连接)
		maxIdle:最大闲置(备胎)
		maxWait:最大等待时间 
		username:数据库用户名
		password:数据库密码
		driverClassName:驱动名称
		url:数据库地址
		
		&amp; :与符号&
		useUnicode=true&amp;characterEncoding=utf-8 防止项目编码和数据库编码不一致的情况  统一采用UTF-8
	-->
    <Resource name="jdbc/news" auth="Container" type=""
      maxActive="100" maxIdle="30" maxWait="10000" username="root"
      password="root" driverClassName=""
      url="jdbc:mysql://127.0.0.1:3306/kgcnews?
              useUnicode=true&amp;characterEncoding=utf-8" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.修改获取连接对象的方式

// 通过连接池技术获取连接对象 每次关闭连接对象时并不会关闭掉  而是让连接对象返回到连接池
Context context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/news");
conn = dataSource.getConnection();
  • 1
  • 2
  • 3
  • 4

分层开发

数据访问层 dao 操作数据库
业务逻辑层 service 处理业务代码 事务 …
表示层(视图展示) jsp 展示数据的(请求控制)

JSP 标签

将公共部分的代码放入到一个jsp中
就可以用以下标签引入到其他页面中 实现页面的拼接
<jsp:include page="URL">
  • 1
  • 2
  • 3