狂神说【Javaweb入门到实战】笔记

01.web的基本概念、web服务器讲解
02.Tomcat详解
03.Http讲解
04.Maven
05.Servlet
06.Cookie、Session
07.JSP
08.JavaBean
09.MVC三层架构
10.Filter
11.监听器
12.过滤器、监听器常见应用
13.JDBC

01.web基本概念、web服务器讲解

web基本概念

1.1前言

web开发:

  • web,网页的意思,www.baidu.com
  • 静态web
    • html,css
    • 提供给所有人看的数据始终不会发生变化!
  • 动态web
    • 淘宝,几乎所有网站
    • 提供给所有人看的数据会发生变化!
    • 技术栈:Servlet/JSP,ASP,PHP

在Java中,动态web资源开发的技术统称为Javaweb

1.2web应用程序

**web应用程序:**可以提供浏览器访问的程序;

  • a.html、b.html……多个web资源,这些web资源可以被外界访问,对外界提供服务;
  • URL
  • 这个统一的web资源会被放到同一个文件夹下,web应用程序 ->Tomcat:服务器
  • 一个web应用由多部分组成(静态web,动态web)
    • html,css,js
    • jsp,servlet
    • Java程序
    • jar包
    • 配置文件

web应用程序编写完毕后,若想提供给外界访问:需要一个服务器来统一管理;

1.3静态web

  • .htm,.html这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取。通络;
  • 静态web存在的缺点:
    • Web页面无法动态更新,所有用户看到都是同一个页面
      • 轮播图,点击特效:伪动态
      • JavaScript[实际开发中,它用的最多]
      • VBScript
    • 它无法和数据库交互(数据无法持久化,用户无法交互)

1.4动态web

页面动态展示。
缺点:

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

优点:

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

web服务器

1.5技术讲解

ASP:

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

<hl>
	<hl><hl>
			<hl>
					<hl>
			<hl>
				<%
				system.out.println("hello");
				%>
				<hl>
					<h1>
	<hl><hl>
<hl>

php:

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

JSP/Servlet:

B/S:浏览和服务器
C/S:客户端和服务器

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

1.6web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应消息;

IIS

微软的;ASP…,Windows中自带的
Tomcat

面向百度编程;

  • Tomcat是Apache软件基金会(Apache Software Foundation)的jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和JSP规范总是能在Tomcat中得到体现,Tomcat5支持最新的Servlet2.4和JSP 2.0规范。因为Tomcat技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
  • Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求,实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat时,它实际上作为一个与Apache 独立的进程单独运行的。
  • 诀窍是,当配置正确时,Apache为HTML页面服务,而Tomcat 实际上运行JSP页面和Servlet.另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。目前Tomcat最新版本为9.0。

02.Tomcat详解

可以配置启动的端口号

  • tomcat的默认端口号为:8080
  • mysql:3306
  • http:80
  • https:443
<Connector port="8081" protocol="HTTP/1.1"
					 connectionTimeout="20000"
					 redirectPort="8443"/>

可以配置主机的名称

  • 默认的主机名为:localhost->127.0.0.1
  • 默认网站应用存放的位置为:webapps
<Host name="[www.qinjiang.com](http://ww.qinjiang.com/)" appBase="webapps"
			unpackWARs="true" autoDeploy="true">

高难度面试题:

请你谈一谈网站是如何访问的

  1. 输入一个域名;回车

  2. 检查本机的C:\windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;
    a. 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问

    127.0.0.1	[www.qinjiang.com](http://www.qinjiang.com/)
    

    b. 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到

  3. 可以配置一下环境变量(可选性)

03.Http讲解

3.1什么是HTTP

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

  • 文本:html,字符串,~……
  • 超文本:图片,音乐,视频,定位,地图……
  • 80
  • Https:安全的
  • 443

3.2两个时代

  • http1.0
    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
  • http2.0
    • HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源

3.3Http请求

客户端 – 发请求(Request) – 服务器
百度:

Request URL:[https://www.baidu.com/](https://www.baidu.com/) 请求地址
Request Method:GET     get方法/post方法
Status Code:200 oK     状态码:200
Remote(远程)    Address:14.215.177.39:443
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9  语言
Cache-Control:max-age=0
Connection:keep-alive

1.请求行

  • 请求行中的请求方式:GET
  • 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…
    • get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高
    • post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。

2.消息头

Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持部种询码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉湖览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连续
HOST:主机..../.

3.4Http响应

  • 服务器 — 响应—客户端

百度:


Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip
Content-Type:text/htm1

1.响应体

Accept:告诉测览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISo8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机../.
Refresh:告诉容户端,多久刷新一次
Location:址网页重新定位

2.响应状态码
200:请求响应成功 200
3**:请求重定向

  • 重定向:你重新到我给你新位置去;
    4**:找不到资源(资源不存在) 404
    5**:服务器代码错误 500 502:网关错误
    常见面试题:
    当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?

04.Maven

  1. 在Javaweb开发中,需要使用大量的jar包,我们手动去导入;
  2. 如何能够让一个东西自动帮我导入和配置这个jar包。由此,Maven诞生了!

4.1Maven项目架构管理工具

我们目前用来就是方便导入jar包的!
Maven的核心思想:约定大于配置

  • 有约束,不要去违反。

Maven会规定好你该如何去编写我们的Java代码,必须要按照这个规范来

4.2下载安装Maven

4.3配置环境变量

4.4阿里云镜像

  • 镜像:mirrors
    • 作用:加速我们的下载
  • 国内建议使用阿里云的镜像
<mirror>
		<id>alimavenid>
		<mirrorof>centralmirrorof>
		<name>aliyun mavenname>
		<url>[http://maven.aliyun.com/nexus/content/groups/public/](http://maven.aliyun.com/nexus/content/groups/public/)url>
mirror>

4.5本地仓库

在本地的仓库,远程仓库;
建立一个本地仓库:localRepository

<localRepository>D:\Environment\apache-maven-3.6.2\maven-repolocalRepository>

05.Servlet

5.1、Servlet简介

  • Servlet就是sun公司开发动态web的一门技术
  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
    • 编写一个类,实现Servlet接口
    • 把开发好的java部署到web服务器中

把实现了Servlet接口的java程序叫做,Servlet

5.2、HelloServlet

Servlet接口Sun公司有两个默认的实现类:HttpServletGenericServlet

1.构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel,这个空的工程就是Maven主工程;
2.关于Maven父子工程的理解:

父项目中会有

<modules>
		<module>servlet-01module>
modules>

子项目中会有

<parent>
		<artifactId>javaweb-02-servletartifactId>
		<version>1.0-SNAPSHOTveresin>
parent>

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

son extends father

3.Maven环境优化

  1. 修改web.xml为最新的
  2. 将maven的结构搭建完整

4.编写一个Servlet程序

  1. 编写一个普通类
  2. 实现Servlet接口,这里我们直接继承HttpServlet
public class HelloServlet extends HttpServlet{

    //由于get或post只是请求实现的不同的方式,可以互相调用,业务逻辑都一样;
    @Override
    protected  void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        //ServletOutputStream OutputStream=res.getOutputStream();
        PrintWriter writer=resp.getWriter();//响应流
        writer.print("Hello,Servlet");
    }
    @Override
    protected  void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
				doGet(req,resp);
		}
}

5.编写Servlet的映射

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


    <servlet>
        <servlet-name>helloservlet-name>
        <servlet-class>com.kuang.servlet.HelloServletservlet-class>
    servlet>
    
    <servlet-mapping>
        <servlet-name>helloservlet-name>
        <url-pattern>/hellourl-pattern>
    servlet-mapping>

6.配置Tomcat

注意:配置项目发布的路径就可以了

7.启动测试

5.3、Servlet原理

狂神说【Javaweb入门到实战】笔记_第1张图片

5.4、Mapping问题

  1. 一个Servlet可以指定一个映射路径
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hellourl-pattern>
servlet-mapping>
  1. 一个Servlet可以指定多个映射路径
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hello2url-pattern>
servlet-mapping>
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hello3url-pattern>
servlet-mapping>
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hello4url-pattern>
servlet-mapping>
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hello5url-pattern>
servlet-mapping>
  1. 一个Servlet可以指定通用映射路径
<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/hello/*url-pattern>
servlet-mapping>
  1. 默认请求路径

<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>/*url-pattern>
servlet-mapping>
  1. 指定一些后缀或者前缀等等……

<servlet-mapping>
		<servlet-name>helloservlet-name>
		<url-pattern>*.qinjiangurl-pattern>
servlet-mapping>
  1. 优先级问题

指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;


<servlet>
		<servlet-name>errorservlet-name>
		<servlet-class>com.kuang.servlet.ErrorServletservlet-class>
servlet>
<servlet-mapping>
		<servlet-name>errorservlet-name>
		<url-pattern>/*url-pattern>
servlet-mapping>

5.5、ServletContext对象

狂神说【Javaweb入门到实战】笔记_第2张图片

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

  • 共享数据
    我在这个Servlet中保存的数据,可以在另一个Servlet中拿到;
  • 获取初始化参数

5.6、Servlet应用

  • 共享数据
    我在这个Servlet中保存的数据,可以在另一个Servlet中拿到;
  • 获取初始化参数
  • 请求转发
  • 读取资源文件

5.7、HttpServletResponse

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

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

简单分类

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

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

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

Response下载文件
Response验证码实现
Response重定向
Request应用

06.Cookie、Session

6.1、会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称为会话。
有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话。

6.2、保存会话的两种技术

cookie

  • 客户端技术(响应,请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息?我们可以把信息或者数据放在Session中!

常见案例:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!

6.3、Cookie

Cookies 是某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。
简单来说: Cookie 存放在客户端,一般用来保存用户信息。

1.从请求中拿到cookie信息
2.服务器响应给客户端cookie

Cookie[] cookies=req.getCookies();//获得Cookie
cookie.getName();//获得cookie中的key
cookie.getValue();//获得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMillis()+"")://新建一个cookie
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie

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

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

如何在项目中使用 Cookie 呢?

我这里以 Spring Boot 项目为例。

  1. 设置 Cookie 返回给客户端
@GetMapping("/change-username")
public String setCookie(HttpServletResponse response) {
		// 创建一个 cookie
		Cookie cookie = new Cookie("username", "Jovan");
		//设置 cookie过期时间
		cookie.setMaxAge(7 * 24 * 60 * 60); // expires in 7 days
		//添加到 response 中
		response.addCookie(cookie);
		return "Username is changed!";
}
  1. 使用 Spring 框架提供的 @CookieValue 注解获取特定的 cookie 的值
@GetMapping("/")
public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) {
    return "Hey! My username is " + username;
}
  1. 读取所有的 Cookie 值
@GetMapping("/all-cookies")
public String readAllCookies(HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
		    return Arrays.stream(cookies)
		            .map(c -> c.getName() + "=" + c.getValue()).collect(Collectors.joining(", "));
		}
		
		return "No cookies";
}

6.4Session(重点)

什么是Session?

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

Session和Cookie的区别

CookieSession都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。

Cookie 一般用来保存用户信息 比如①我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了;②一般的网站都会有保持登录也就是说下次你再访问网站的时候就不需要重新登录了,这是因为用户登录的时候我们可以存放了一个 Token 在 Cookie 中,下次登录的时候只需要根据 Token 值来查找用户即可(为了安全考虑,重新登录一般要将 Token 重写);③登录一次网站后访问网站其他页面不需要重新登录。

Session 的主要作用就是通过服务端记录用户的状态。 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。

Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。

Cookie 存储在客户端中,而Session存储在服务器上,相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。

如何使用Session-Cookie方案进行十分验证?

很多时候我们都是通过 SessionID 来实现特定的用户,SessionID 一般会选择存放在 Redis 中。举个例子:

  1. 用户成功登陆系统,然后返回给客户端具有 SessionIDCookie
  2. 当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。

关于这种认证方式更详细的过程如下:
狂神说【Javaweb入门到实战】笔记_第3张图片

  1. 服务器验证通过后,服务器为用户创建一个 Session,并将 Session 信息存储起来。
  2. 用户向服务器发送用户名、密码、验证码用于登陆系统。
  3. 服务器向用户返回一个 SessionID,写入用户的 Cookie
  4. 当用户保持登录状态时,Cookie 将与每个后续请求一起被发送出去。
  5. 服务器可以将存储在 Cookie 上的 SessionID 与存储在内存中或者数据库中的 Session 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。

使用 Session 的时候需要注意下面几个点:

  1. 依赖 Session 的关键业务一定要确保客户端开启了 Cookie
  2. 注意 Session 的过期时间。

多服务器节点下 Session-Cookie 方案如何做?

Session-Cookie 方案在单体环境是一个非常好的身份认证方案。但是,当服务器水平拓展成多节点时,Session-Cookie 方案就要面临挑战了。

举个例子:假如我们部署了两份相同的服务 A,B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。

我们应该如何避免上面这种情况的出现呢?

有几个方案可供大家参考:

某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。
每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的 Session 信息。每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。
单独使用一个所有服务器都能访问到的数据节点(比如缓存)来存放 Session 信息。为了保证高可用,数据节点尽量要避免是单点。

如果没有 Cookie 的话 Session 还能用吗?

这是一道经典的面试题!

一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID 的方案的话, 如果客户端禁用了 Cookie,那么 Session 就无法正常工作。

但是,并不是没有 Cookie 之后就不能用 Session 了,比如你可以将 SessionID 放在请求的 url 里面https://javaguide.cn/?Session_id=xxx 。这种方案的话可行,但是安全性和用户体验感降低。当然,为了你也可以对 SessionID 进行一次加密之后再传入后端。

07.JSP

7.1、什么是JSP?

Java Server Pages:Java服务器端页面,也和Servlet一样,用于动态web技术!
最大的特点:

  • 写JSP就像在写HTML
  • 区别:
    • HTML只会给用户提供静态的数据;
    • JSP页面中可以嵌入JAVA代码,为用户提供动态数据;

7.2、JSP原理

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

  • 代码层面没有任何问题
  • 服务器内部工作

Tomcat中有一个work目录;
IDEA中使用Tomcat的会在IDEA的Tomcat中生产一个work目录;
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP最终也会被转换为一个Java类!
JSP本质上就是一个Servlet.

//初始化
public void _jspInit(){

}
//销毁
public void _jspDestory(){

}
//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response)
  1. 判断请求
  2. 内置一些对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文
javax.servlet.http.HttpSession session = null;   //session
final javax.servlet.ServletContext application;  //applicationContext
final javax.servlet.ServletConfig config;        //config
javax.servlet.jsp.JspWriter out = null;          //out
final java.lang.Object page = this;              //page:当前
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;

【补充】:

JSP工作原理

JSP是一种Servlet,但是与HttpServlet的工作方式不太一样。HttpServlet是先由源代码编译为class文件后部署到服务器下,为先编译后部署。而JSP则是先部署后编译。JSP会在客户端第一次请求JSP文件时被编译为HttpJspPage类(接口Servlet的一个子类)。该类会被服务器临时存放在服务器工作目录里面。下面通过实例给大家介绍。 工程JspLoginDemo下有一个名为login.jspJsp文件,把工程第一次部署到服务器上后访问这个Jsp文件,我们发现这个目录下多了下图这两个东东。 .class文件便是JSP对应的Servlet。编译完毕后再运行class文件来响应客户端请求。以后客户端访问login.jsp的时候,Tomcat将不再重新编译JSP文件,而是直接调用class文件来响应客户端请求。
狂神说【Javaweb入门到实战】笔记_第4张图片

只会在客户端第一次请求的时候被编译 ,因此第一次请求JSP时会感觉比较慢,之后就会感觉快很多。如果把服务器保存的class文件删除,服务器也会重新编译JSP

开发Web程序时经常需要修改JSP。Tomcat能够自动检测到JSP程序的改动。如果检测到JSP源代码发生了改动。Tomcat会在下次客户端请求JSP时重新编译JSP,而不需要重启Tomcat。这种自动检测功能是默认开启的,检测改动会消耗少量的时间,在部署Web应用的时候可以在web.xml中将它关掉。

7.3、JSP基础语法和指令

任何语言都有自己的语法,Java中有。JSP作为Java技术的一种应用,它拥有一些自己的扩充语法(了解,知道即可),Java所有语法都支持!

JSP表达式

<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%=变量或者表达式%>
--%>
<%= new java.util.Date()%>

jsp脚本片段

<%--jsp脚本片段--%>
<%
	int sum=0;
	for (int i=1;i<100;i++){
		sum+=i;
	}
	out.println("

Sum="+sum+"

"
); %>

JSP声明

<%!
	static{
		System.out.println("Loading Servlet!");
	}
	private int globalvar=0;
	public void kuang(){
		System.out.println("进入了方法kuang!");
	}
%>

JSP声明:会被编译到JSP生成Java的类中!其他的,都会被生成到_jspService方法中!
在JSP,嵌入Java代码即可!

<%%>
<%=%>
<%!%>

<%--注释--%>

JSP的注释不会在客户端显示,HTML就会!

JSP指令

<%@page args....%>
<%@include file=""%>

		<%--@include会将两个页面合二为一--%>
		<%@include file="common/header.jsp"%>
		<h1>网页主体</h1>
		<%@include file="common/footer.jsp"%>
		
		<hr>
		
		<%--JSP标签
		jsp:include:拼接页面,本质还是三个
		--%>
		<jsp:include page="/common/header.jsp"/>
		<h1>网页主体</h1>
		<jsp:include page="/common/footer.jsp"/>

7.4、JSP内置对象及作用域

9大内置对象

  • request:封装客户端的请求,其中包含来自GET或POST请求的参数;
  • response:封装服务器对客户端的响应;
  • pageContext:通过该对象可以获取其他对象;
  • session:封装用户会话的对象;
  • application:封装服务器运行环境的对象,【ServletContext】存东西;
  • out:输出服务器响应的输出流对象;
  • config:Web应用的配置对象,【ServletConfig】;
  • page:JSP页面本身(相当于Java程序中的this);
  • exception:封装页面抛出异常的对象。

四种作用域

JSP中的四种作用域包括page、request、session和application,具体来说:

  • page代表与一个页面相关的对象和属性。
  • request代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web组件;需要在页面显示的临时数据可以置于此作用域。
  • session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中。
  • application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。

如何实现JSP或Servlet的单线程模式

对于JSP页面,可以通过page指令进行设置。 <%@page isThreadSafe="false"%>

对于Servlet,可以让自定义的Servlet实现SingleThreadModel标识接口。

说明:如果将JSP或Servlet设置成单线程工作模式,会导致每个请求创建一个Servlet实例,这种实践将导致严重的性能问题(服务器的内存压力很大,还会导致频繁的垃圾回收),所以通常情况下并不会这么做。

JSP标签

<%--jsp:include--%>
<%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
 --%>      
<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="kuangshen"></jsp:param>
    <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

JST表达式

JSTL标签库的使用就是为了弥补HTML的不足;它自定义许多标签,可以供我们使用,标签的功能和java代码一样!

JSTL核心标签

核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

狂神说【Javaweb入门到实战】笔记_第5张图片

JSTL标签库使用步骤:

  • 引入对应的taglib
  • 使用其中的方法
  • 在Tomcat中也需要引入jstl的包,否则会报错:JSTL解析错误

08.JavaBean

实体类
JavaBean有特定的写法

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用来和数据库的字段做映射 ORM;
ORM:对象关系映射

  • 表—>类
  • 字段—>属性
  • 行记录—>对象
class people{
		private int id;
		private String name;
		private int id;
		private String address;
}

class A{
		new People(1,"安娜1号",3,"西安");
		new People(2,"安娜2号",3,"西安");
		new People(3,"安娜3号",3,"西安");
}
  • 过滤器
  • 文件上传
  • 邮件发送

09.MVC三层结构

MVC三层架构

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

早些年
狂神说【Javaweb入门到实战】笔记_第6张图片

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

servlet--CRUD-->数据库
弊端;程序十分臃肿,不利于维护    
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的!
程序员调用
|
JDBC
|
Mysql Oracle SqlServer...

MVC三层架构
狂神说【Javaweb入门到实战】笔记_第7张图片

Model:

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

View:

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

Controller:

  • 接收用户的请求:(req:请求参数、Session信息…)
  • 交给业务层处理对应的代码
  • 控制视图的跳转
登录--->接收用户的登录请求--->处理用户请求(获取用户登录的参数,username,password)---->
交给业务层处理登录业务(判断用户名密码是否正确)--->Dao层查询用户名和密码是否正确

10.Filter

Filter

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

  • 处理中文代码
  • 登录验证……
    狂神说【Javaweb入门到实战】笔记_第8张图片
    Filter开发步骤:
  1. 导包
  2. 编写过滤器

Filter过滤

过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作。

// 测试 Filter(过滤)
        stringList
                .stream()
                .filter((s) -> s.startsWith("a"))
                .forEach(System.out::println);//aaa2 aaa1

forEach 是为 Lambda 而设计的,保持了最紧凑的风格。而且 Lambda 表达式本身是可以重用的,非常方便。

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

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

在web.xml中配置Filter

<filter>
       <filter-name>CharacterEncodingFilterfilter-name>
       <filter-class>com.kuang.filter.CharacterEncodingFilterfilter-class>
   filter>
   <filter-mapping>
       <filter-name>CharacterEncodingFilterfilter-name>
       
       <url-pattern>/servlet/*url-pattern>
       
       
   filter-mapping>

11.监听器

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

  1. 编写一个监听器
    实现监听器的接口…
package com.kuang.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

依赖的jar包

//统计网站在线人数 : 统计session
public class OnlineCountListener implements HttpSessionListener {

    //创建session监听: 看你的一举一动
    //一旦创建Session就会触发一次这个事件!
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }

    //销毁session监听
    //一旦销毁Session就会触发一次这个事件!
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");

        if (onlineCount==null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        ctx.setAttribute("OnlineCount",onlineCount);

    }

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

12.过滤器、监听器常见应用

监听器:GUI编程中经常使用;

public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("中秋节快乐");  //新建一个窗体
        Panel panel = new Panel(null); //面板
        frame.setLayout(null); //设置窗体的布局

        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,255)); //设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,0)); //设置背景颜色

        frame.add(panel);

        frame.setVisible(true);

        //监听事件,监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
            }
        });

    }
}

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

  1. 用户登录之后,向Sesison中放入用户的数据
  2. 进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;

if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
    response.sendRedirect("/error.jsp");
}

chain.doFilter(request,response);

13.JDBC

JDBC

什么是JDBC:Java理解数据库!
狂神说【Javaweb入门到实战】笔记_第9张图片

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java… 连接驱动(必须要导入)

实验环境搭建

**CREATE TABLE users(
    id INT PRIMARY KEY,
    `name` VARCHAR(40),
    `password` VARCHAR(40),
    email VARCHAR(60),
    birthday DATE
);

INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');

SELECT	* FROM users;**

导入数据库依赖


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <version>5.1.47version>
dependency>

JDBC固定步骤

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement : CRUD
  4. 编写SQL (根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接(先开的后关)
public class TestJdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
        Statement statement = connection.createStatement();

        //4.编写SQL
        String sql = "select * from users";

        //5.执行查询SQL,返回一个 ResultSet  : 结果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        rs.close();
        statement.close();
        connection.close();
    }
}

预编译SQL

public class TestJDBC2 {
    public static void main(String[] args) throws Exception {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        String sql = "insert into  users(id, name, password, email, birthday) values (?,?,?,?,?);";

        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,2);//给第一个占位符? 的值赋值为1;
        preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
        preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
        preparedStatement.setString(4,"[email protected]");//给第四个占位符? 的值赋值为1;
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());

        //5.执行SQL
        int i = preparedStatement.executeUpdate();

        if (i>0){
            System.out.println("插入成功@");
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        preparedStatement.close();
        connection.close();
    }
}

事务

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务

转账:
A:1000
B:1000
    
A(900)   --100-->   B(1100)

Junit单元测试

依赖


<dependency>
    <groupId>junitgroupId>
    <artifactId>junitartifactId>
    <version>4.12version>
dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!

@Test
public void test(){
    System.out.println("Hello");
}

狂神说【Javaweb入门到实战】笔记_第10张图片
失败的时候是红色:
狂神说【Javaweb入门到实战】笔记_第11张图片

搭建一个环境

CREATE TABLE account(
   id INT PRIMARY KEY AUTO_INCREMENT,
   `name` VARCHAR(40),
   money FLOAT
);

INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
@Test
    public void test() {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        Connection connection = null;

        //1.加载驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库,代表数据库
             connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
            //int i = 1/0;

            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

你可能感兴趣的:(JavaWeb入门到实战,前端,tomcat,maven,后端)