完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习
JavaWeb
java Web
前端–>Mysql
IDEA版本2020.1.2
1.基本概念
1.1前言
web开发:
- web:网页的意思
- 静态web
- html、css
- 提供给所有人看的数据始终不会发生变化!
- 动态web
- 提供给所有人看的数据会发生变化!(每个人在不同的时间、不同的地点,看到的信息各不相同!)
- 淘宝,几乎所有的网站;
- 技术栈:Servlet/JSP、ASP、PHP
- 静态web
在java中,动态web资源开发的技术统称为javaweb;
1.2、Web应用程序
web应用程序:可以提供浏览器访问的程序;
- a.html、b.html…多个web资源,这些web资源可以被外界访问,对外界提供服务;
- 能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。
- URL:统一资源定位符
- 这些统一的web资源会被放在同一个文件夹下。web应用程序–>tomcat:服务器
- 一个web应用由多部分组成(静态web,动态web)
- html、css、js
- jsp、servlet
- java程序
- jar包
- 配置文件(properties)
web应用程序编写完成后,如果想提供给外界访问,需要一个服务器来统一管理;
1.3、静态web
*.htm、.html、这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取,通络。
静态Web存在的缺点
- Web页面无法动态更新,所有用户看到的都是同一个页面
- 轮播图、点击特效:伪动态
- JavaScript【实际开发中它用的最多】
- VBScript
- 它无法和数据库交互(数据无法持久化,用户无法交互)
- Web页面无法动态更新,所有用户看到的都是同一个页面
1.4、动态Web
页面会动态展示:“Web的页面展示效果因人而异”;
缺点:
- 假如服务器的动态Web资源出现错误,我们需要重新编写我们的后台程序,重新发布
- 停机维护
优点:
Web页面可以动态更新,所有用户看到的都不是同一个页面
它可以和数据库交互(数据无法持久化:注册,商品信息)
分析原理、看源码
2、Web服务器
2.1、编程软件
ASP:
- 微软:国内最早流行的就是ASP;
- 在HTML中嵌入了VB的脚本,ASP+COM
- 在ASP开发中,基本上一个页面都有几千行的业务逻辑代码,页面及其乱
- 维护成本高!
- C#
- IIS
<h1><h1><h1><h1><h1><%Java代码%><h1><h1><h1><h1>
<h1>
PHP:
- PHP开发速度很快,功能很强大,跨平台,代码简单(70%,WP)
- 无法承载大访问量的情况(有局限);
JSP/Servlet:
B/S:浏览器和服务器
C/S:客户端和服务器
- sun主推的B/S架构
- 基于java语言的(所有的大公司,或者一些开源的组件,都是用java写的)
- 可以承载三高问题(高并发、高可用、高性能)
- 语法想ASP,ASP–>JSP,加强市场强度
…
2.2、Web服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些相应信息;
IIS:
微软的;ASP…,Windows自带的
Tomcat:
面向百度编程
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。
**Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。**对于一个初学者来说,他是最佳选择。
(可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。)
Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。
…
工作3-5年后,可以尝试手写Tomcat服务器;
下载tomcat:
- 安装 or 解压
- 了解配置文件及目录结构
- 这个东西的作用
3、Tomcat
3.1、安装Tomcat
Tomcat官方链接:https://tomcat.apache.org/
下载:
Tomcat安装包
Tomcat压缩包
3.2、Tomcat启动和配置
- 各文件夹的功能与作用:
- 启动,关闭Tomcat
打开下载解压的apache-tomcat-9.0.46
进入bin目录
找到startup.bat开启服务器,找到shutdown.bat关闭服务器
- 网站访问 http://localhost:8080/
可能遇到的问题:
- Java环境变量没有配置
- 闪退问题:需要配置兼容性
- 乱码问题:配置文件中设置
3.3、配置
server.xml文件:服务器的核心配置文件
可以配置启动的端口号:
- tomcat默认端口号:8080
- mysql默认端口号:3306
- http默认端口号:80
- https默认端口号:443
可以配置主机的名称:
- 默认的主机名为:localhost–>127.0.0.1
- 默认网站应用存放的位置为:webapps
高难度面试题:
请你谈谈网站是如何进行访问的!
- 输入一个域名+enter
- 检查本机的:C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名的映射
有:直接返回对应的ip的地址,这个地址中,有我们需要访问的web程序,可以直接访问
没有:去DNS服务器上找(全世界的域名都在这里管理),找到的话就返回,找不到就返回找不到
- 可以配置一下环境变量(可选性)
3.4、发布一个web网站
不会就先模仿
- 将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了
网站应该有的结构:
--webapps:Tomcat服务器的web目录--Root--yangqi:网站的目录名--WEB-INF--classes:java程序--lib:web应用所依赖而jar包--web.xml:网站配置文件--index.html 默认的首页--static--css--style.css--js--img-...
4、HTTP
4.1、什么是Http
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。
- 文本:html,字符串,…
- 超文本:图片、音乐、视频、定位、地图…
- http默认端口号:80
Https:s代表安全的
- 默认端口号:443
4.2、两个时代
- http1.0
- HTTP/1.0:客户端可以与web服务器连接,之后只能获得一个web资源,断开连接
- http2.0
- HTTP/1.1:客户端可以与web服务器连接,可以获得多个web资源
4.3、Http请求
- 客户端 —发请求(Request)—> 服务器
百度:
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 状态码:200
Remote(远程) Address: 36.152.44.95:443
Accept: text/htmlapplication/signed-exchange;v=b3;q=0.9
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,DELEFE,PUT,TRACT…
- get:一次请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但是高效
- post:一次请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但是不高效
2、消息头
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境
Cache-Control: 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST:主机......
4.4、Http响应
- 服务器 —响应(Response)—> 客户端
百度:
Cache-Control: private 缓存控制
Connection: keep-alive 连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型
1、响应体
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境
Cache-Control: 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST:主机......
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位;
2、响应状态码(重点)
200: 请求响应成功
3×:请求重定向
- 重定向:你重新到我给你的新位置去;
4××: 找不到资源
- 资源不存在
5××: 服务器代码错误 500 502:网关错误
面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,都经历了什么?
5、Maven
启动Tomcat,进入网站链接:http://localhost:8080/examples/servlets/,代码案例
为什么要学习这个技术?
- 在javaweb开发中,需要使用大量的jar包,我们需要手动去导入。
- 如何能够让一个东西自动帮我们导入和配置这个jar包。
由此,Maven诞生了!
5.1、Maven项目架构管理工具
我们目前用来就是方便导入jar包的!
Maven的核心思想:约定大于配置
- 有约束,不要去违反。
Maven会规定你如何去编写我们的Java代码,必须要按照这个规范来。
5.2、下载安装Maven
官网:https://maven.apache.org/
下载完成后解压即可
5.3、配置环境变量
在我们的系统环境变量中
配置如下配置:
- M2_HOME maven目录下的bin目录:D:\Maven\apache-maven-3.6.1\bin
- MAVEN_HOME maven目录:D:\Maven\apache-maven-3.6.1
- path目录中新建配置:%MAVEN_HOME%\bin
- 打开命令窗口输入mvn -version测试配置是否完成。
5.4、阿里云镜像
修改镜像:在maven的conf文件夹下的settings.xml中进行配置
- 镜像:mirrors
- 作用:加速我们的下载
- 国内建议使用阿里云镜像
<mirror><id>nexus-aliyun</id><mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url></mirror>
5.5、修改本地仓库
本地的仓库,远程仓库
修改仓库:在maven的conf文件夹下的settings.xml中进行配置
**建立本地仓库:**localRepository
<localRepository>D:\Maven\apache-maven-3.6.1\maven-repo</localRepository>
5.6、在Idea中使用Maven
打开IDEA
创建一个Maven项目
等待项目初始化完毕
出现BUILD SUCCESS 下载成功
观察maven仓库中多了什么
IDEA中的Maven设置
IDEA项目创建成功后,看一眼Maven的配置(防止IDEA默认将本地仓库等换成Idea自己的)
- 到这里,Maven在IDEA中的配置和使用就OK了!
5.7、创建一个普通的Maven项目
新建项目
以下步骤和上次一样。
最终得到的项目结构:
之前的项目结构:
5.8、标记文件夹功能
方法一:
方法二:
5.9、在IDEA中配置Tomcat
第一步:
第二步:
第三步:
解决警告问题:
为什么会有这个问题:我们访问一个网站,需要指定一个文件夹的名字;
必须要有的配置:
不写:默认访问路径为localhost:8080
写了一个/yang:默认访问路径为localhost:8080/yang
这个过程叫做:虚拟路径映射
最后:启动Tomcat
关于Tomcat启动乱码问题:
在tomcat Server中设置 VM options , 值为 -Dfile.encoding=UTF-8 ,(显然没生效)
在setting中的 File encodings 中设置编码格式,发现这是设置页面编码格式的,(显然也没生效)
在java Complier中设置Additional command line parameters的值,-encoding=UTF-8,(显然还没生效)
在bin中设置idea.exe.vmoptions和idea64.exe.vmoptions中的参数,同时增加-Dfile.encoding=UTF-8,据说有些人保存后重启就可以了,(显然我这边还是没生效)
在tomcat \bin目录下的catalina.bat文件中加入 -Dfile.encoding=UTF-8,(显然还不生效)
在 tomcat / conf 目录下,设置 logging.properties ,增加参数 java.util.logging.ConsoleHandler.encoding = GBK,重启后终于可以了
5.10、pom文件
pom.xml文件是maven的核心配置文件
代码
<?xml version="1.0" encoding="UTF-8"?><!--Maven的版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!--这里就是我们刚才配置的GAV--><groupId>com.yang</groupId><artifactId>javaweb-01-maven</artifactId><version>1.0-SNAPSHOT</version><!--package:项目的打包方式jar:java应用war:Javaweb应用--><packaging>war</packaging><!--配置--><properties><!--项目的默认构建编码--><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!--编码版本--><maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target></properties><!--项目依赖--><dependencies><!--具体的jar包配置文件--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version></dependency></dependencies><!--项目构建用的东西--><build><finalName>javaweb-01-maven</finalName><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin></plugins></pluginManagement></build>
</project>
创建一个空项目的Maven,自己配置Maven的pom.xml文件
Maven由于约定大于配置,我们之后可能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:
build中配置resources,来防止我们资源导出失败的问题
<!--在build中配置resources,来防止我们资源导出失败的问题--><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build>
5.11、Idea操作
5.12、解决遇到的问题
Maven:无法导入
- 解决方法:降级maven
Tomcat闪退
- jdk版本/系统环境配置
IDEA每次都要重复配置Maven
- 在IDEA中的全局默认配置中去配置
Maven项目中Tomcat无法配置
maven默认web项目中的web.xml版本问题
替换为webapp4.0版本,和Tomcat的webapps/ROOT/WEB-INF里面的web.xml文件里的一致
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>
5.13、Maven仓库的使用
Maven仓库网站链接:https://mvnrepository.com/
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><!--作用域 ,删掉在所有情况下都可以使用--><scope>provided</scope>
</dependency>
6、Servlet
6.1、Servlet简介
- Servlet就是Sun公司用于开发动态Web的一门技术
- Sun公司在这些API中提供了一个接口叫做:Servlet。如果你想开发一个Servlet程序,只需要完成两个小步骤
- 编写一个类实现Servlet接口
- 把开发好的Java类部署到web服务器中。
把实现了Servlet接口的Java程序叫做:Servlet程序
6.2、HelloServlet
Servlet接口在Sun有两个默认的实现类:HttpServlet,GenericServlet
构建一个空的Maven项目,删掉src目录,以后我们的学习就在这项目里面建立moudle,这个空的工程就是Maven的主工程
在主工程中导入依赖,其他的子工程就会有相应的依赖
关于Maven父子工程的理解:
父项目中会有Moudle
<modules><module>servlet-01</module> </modules>
子项目中会有Parent
<parent><artifactId>javaweb-02-Servlet</artifactId><groupId>com.yang</groupId><version>1.0-SNAPSHOT</version> </parent>
父项目中的jar包子项目可以直接使用
son extends father
Maven环境优化
- 修改web.xml为最新的
- 将Maven结构搭建完整
编写一个Servlet程序
- 编写一个普通类HelloServlet
- 实现Servlet接口,这里我们直接继承HttpServlet实现类
public class HelloServlet extends HttpServlet {//由于get或post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样。@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletOutputStream outputStream = resp.getOutputStream();PrintWriter writer = resp.getWriter();//响应流writer.print("Hello Servlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }
编写Servlet的映射
为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径。
在web.xml中进行web应用的核心编写
<!--注册Servlet--> <servlet><servlet-name>Hello Servlet</servlet-name><servlet-class>com.yang.Servlet.HelloServlet</servlet-class> </servlet> <!--Servlet的请求路径--> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping>
配置Tomcat
注意:配置项目发布的路径。
启动测试
6.3、Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求之后,会:
6.4、Mapping问题
HelloServlet类处理请求,发送响应,代码的编写
public class HelloServlet extends HttpServlet {//由于get或post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样。@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {PrintWriter writer = resp.getWriter();//响应流writer.print("Hello Servlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
一个Servlet请求可以指定一个映射路径
<!--注册Servlet--> <servlet><servlet-name>Hello Servlet</servlet-name><servlet-class>com.yang.Servlet.HelloServlet</servlet-class> </servlet> <!--Servlet的请求路径--> <!--一个Servlet请求指定一个映射路径--> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping>
一个Servlet请求可以指定多个映射路径
<servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello3</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello4</url-pattern> </servlet-mapping> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello5</url-pattern> </servlet-mapping>
一个Servlet请求可以指定通用映射路径
<!--一个Servlet请求指定通用映射路径 ,利用通配符*--> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/hello/*</url-pattern> </servlet-mapping>
默认请求路径
<servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>/*</url-pattern> </servlet-mapping>
指定一些后缀或者前缀等等…
<!--一个Servlet请求指定前缀或后缀,利用通配符*--> <!--后缀 注意:*前面不能加项目映射的路径(/hello/*.yangqi)--> <servlet-mapping><servlet-name>Hello Servlet</servlet-name><url-pattern>*.yangqi</url-pattern> </servlet-mapping>
优先级问题
指定了固有的mapping映射路径优先级最高,如果找不到就会走默认的处理请求;
映射路径404问题
web.xml映射Servlet
<!--404页面--> <servlet><servlet-name>error</servlet-name><servlet-class>com.yang.Servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping><servlet-name>error</servlet-name><url-pattern>/*</url-pattern> </servlet-mapping>
ErrorServlet代码的编写
public class ErrorServlet extends HelloServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");PrintWriter writer = resp.getWriter();writer.print("<h1>你访问的页面不存在,请重新输入!</h1>");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }
6.5、ServletContext
web容器在启动的时候,它会为每一个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用
父项目中创建一个note.md文件,方便之后子工程web.xml编代码用,里面输入代码:
web.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>
```
- 新建一个普通的Moudle命名servlet-02
- Tomcat选择servlet-02
- 创建相应的结构
- 创建类HelloServlet和web.xml映射
6.5.1、共享数据
我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
放置ServletContext内容的类
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/*HelloServlet父类HttpServlet中的各种方法:* this.getInitParameter(); 初始化参数this.getServletConfig(); Servlet配置this.getServletContext(); Servlet上下文* ...*///this.getServletContext()转发ServletContext context = this.getServletContext();String username = "扬启";context.setAttribute("username",username); //将一个数据保存在了ServletContext中 ,名字为:username , 值为:username} }
读取ServletContext内容的类
public class GetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = (String) context.getAttribute("username");resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().print("名字"+username);} }
设置web.xml的映射
<!--ServletContext--> <servlet><servlet-name>ServletContext</servlet-name><servlet-class>com.yang.Servlet.GetServlet</servlet-class> </servlet> <servlet-mapping><servlet-name>ServletContext</servlet-name><url-pattern>/context</url-pattern> </servlet-mapping>
先在浏览器上访问hello,将username内容放到ServletContext中
再访问context,将username内容读取出来
6.5.2、获取初始化参数
配置相关的映射来获取初始化参数
<!--配置一些web应用的初始化参数-->
<context-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/mybatis?</param-value>
</context-param>
<!--进行映射-->
<servlet><servlet-name>getParameter</servlet-name><servlet-class>com.yang.Servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping><servlet-name>getParameter</servlet-name><url-pattern>/getp</url-pattern>
</servlet-mapping>
创建一个新的类ServletDemo03,进行使用初始化参数
public class ServletDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String url = context.getInitParameter("url");resp.getWriter().print(url);}
}
6.5.3、请求转发(RequestDispatcher)
创建一个类ServletDemo04,进行请求转发
public class ServletDemo04 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getp"); //转发的路径requestDispatcher.forward(req,resp); //调用forward()进行请求转发}
}
在web.xml中进行相关的映射
<!--RequestDispatcher请求转发-->
<servlet><servlet-name>requestDispatcher</servlet-name><servlet-class>com.yang.Servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping><servlet-name>requestDispatcher</servlet-name><url-pattern>/getrequestD</url-pattern>
</servlet-mapping>
结果:
在浏览器getrequestD中显示的getp的页面
6.5.4、读取资源文件
Properties:
- 在resources目录下新建一个Properties
- 在java目录下新建一个Properties
发现:都被打包到了同一个路径下–>classes,我们俗称这个路径为类路径classpath;
思路:需要一个文件流
db.properties
username=root
password=123456
代码
public class ServletReadProperties extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//把资源当成一个流 /代表当前路径Properties prop = new Properties();prop.load(stream); //加载流String user = prop.getProperty("username"); //设置属性String pwd = prop.getProperty("password");resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().println("账号:"+user+"密码:"+pwd);}
}
访问测试接口。
6.6、HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象和一个代表响应的HttpServletResponse对象;
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应一些信息:找HttpServletResponse
6.6.1、简单分类
负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);void setContentLength(int var1);void setContentLengthLong(long var1);void setContentType(String var1);void setDateHeader(String var1,long var2);void addDateHeader(String var1,long var2);void setHeader(String var1,String var2);void addHeader(String var1,String var2);void setIntHeader(String var1,int var2);void addIntHeader(String var1,int var2);...
响应的状态码
int SC_CONTINUE = 100;int SC_SWITCHING_PROTOCOLS = 101;int SC_OK = 200;int SC_CREATED = 201;int SC_ACCEPTED = 202;int SC_NON_AUTHORITATIVE_INFORMATION = 203;int SC_NO_CONTENT = 204;int SC_RESET_CONTENT = 205;int SC_PARTIAL_CONTENT = 206;int SC_MULTIPLE_CHOICES = 300;int SC_MOVED_PERMANENTLY = 301;int SC_MOVED_TEMPORARILY = 302;int SC_FOUND = 302;int SC_SEE_OTHER = 303;int SC_NOT_MODIFIED = 304;int SC_USE_PROXY = 305;int SC_TEMPORARY_REDIRECT = 307;int SC_BAD_REQUEST = 400;int SC_UNAUTHORIZED = 401;int SC_PAYMENT_REQUIRED = 402;int SC_FORBIDDEN = 403;int SC_NOT_FOUND = 404;int SC_METHOD_NOT_ALLOWED = 405;int SC_NOT_ACCEPTABLE = 406;int SC_PROXY_AUTHENTICATION_REQUIRED = 407;int SC_REQUEST_TIMEOUT = 408;int SC_CONFLICT = 409;int SC_GONE = 410;int SC_LENGTH_REQUIRED = 411;int SC_PRECONDITION_FAILED = 412;int SC_REQUEST_ENTITY_TOO_LARGE = 413;int SC_REQUEST_URI_TOO_LONG = 414;int SC_UNSUPPORTED_MEDIA_TYPE = 415;int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;int SC_EXPECTATION_FAILED = 417;int SC_INTERNAL_SERVER_ERROR = 500;int SC_NOT_IMPLEMENTED = 501;int SC_BAD_GATEWAY = 502;int SC_SERVICE_UNAVAILABLE = 503;int SC_GATEWAY_TIMEOUT = 504;int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
6.6.2、下载文件
- 向浏览器输出消息 (前面一直在讲,就不说了)
- 下载文件
- 要获取下载文件的路径。
- 下载的文件名是啥?
- 想办法设置让浏览器能够支持下载我们需要的东西。
- 获取下载文件的输入流。
- 创建缓冲区。
- 获取OutputStream对象。
- 将FileOutputStream流写入到buffer缓冲区。
- 使用OutputStream将缓冲区中的数据输出到客户端!
- 创建一个新的Maven项目:response
- 创建结构目录
- 改变web.xml的代码为最新版
- 创建包com.yang.servlet
创建一个类FileServlet
public class FileServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.获取下载文件的路径//String realPath = this.getServletContext().getRealPath("/1.jpg");获取的Tomcat中Servlet下的路径String realPath = "D:\\IDEAStudy\\javaweb-02-Servlet\\response\\src\\main\\resources\\头像.jpg";System.out.println("下载文件的路径"+realPath);//2.下载的文件名是啥?String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);//3.想办法设置让浏览器支持(Content-Disposition)我们下载的东西,attachment:附件,//中文文件名用URLEncoding.encode编码,否则可能会乱码resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));//4.获取下载文件的输入流FileInputStream inputStream = new FileInputStream(realPath);//5.创建缓冲区int len = 10;byte[] buffer = new byte[1024];//6.获取OutputStream对象ServletOutputStream out = resp.getOutputStream();//7.将FileInputStream写入到buffer缓冲区,使用OutputStream将缓冲区内的数据写入到客户端!while ((len=inputStream.read(buffer))>0){out.write(buffer,0,len);}inputStream.close();out.close();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
注册Servlet
6.6.3、验证码功能
验证码怎么来的?
- 前端实现
- 后端实现,需要用到java的图片类,生成一个图片
新建一个类ImageServlet进行测试验证码图片
public class ImageServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//如何让浏览器每3秒自动刷新一次resp.setHeader("refresh","3");//在内存中创建一个图片 宽:80,高:20BufferedImage Image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);//得到图片,创建画笔Graphics2D graphics =(Graphics2D) Image.getGraphics();//设置图片的背景颜色 从(0,0) 到(80,20)graphics.setColor(Color.WHITE);graphics.fillRect(0,0,80,20); //填充颜色//给图片中写入数据graphics.setColor(Color.black);graphics.setFont(new Font(null,Font.BOLD,20));graphics.drawString(makeNum(),0,20); //画一个字符串//告诉浏览器以图片的方式打开resp.setContentType("image/jpeg");//浏览器中有缓存,不让浏览器缓存resp.setDateHeader("expires",-1); //-1:表示不缓存resp.setHeader("Cache-Control","no-cache");resp.setHeader("Pragma","no-cache");//把图片写给浏览器ImageIO.write(Image, "jpg", resp.getOutputStream());}//生成随机数private String makeNum(){Random random = new Random();String num = random.nextInt(9999999)+""; //字符串//创建对象,填充数字不足的位置为0 ,stringBuffer:可变字符串StringBuffer stringBuffer = new StringBuffer();for (int i = 0; i < 7-num.length(); i++) {stringBuffer.append("0");}num = stringBuffer.toString()+num;return num;}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
web.xml中编写注册一个新的Servlet
<servlet><servlet-name>ImageServlet</servlet-name><servlet-class>com.yang.Servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>ImageServlet</servlet-name><url-pattern>/image</url-pattern>
</servlet-mapping>
访问测试。
6.6.4、实现重定向
一个web资源(B)收到客户端(A)请求后,他(B)会通知客户端(A)去访问另外一个web资源©,这个过程叫做重定向
常见场景:
- 用户登录
void sendRedirect(String var1) throws IOException;
测试:
新建一个类RedirectServlet
public class RedirectServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.sendRedirect("/response/image"); //重定向/** resp.sendRedirect("/response/image");可以拆分为:* resp.setHeader("Location","/response/image");* resp.setStatus(302);* */}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
面试题:请你聊聊重定向和转发区别?
相同点:
- 页面都会跳转
不同点:
- 请求转发的时候,url不会发生变化
- 重定向的时候,url变成重定向地址的url
6.6.5、测试登陆用户重定向
- 新建一个类RedirectTest类
- 在web.xml中进行RedirectTest类Servlet的注册
- 在页面index.jsp中进行html代码编写
- 新建一个页面success.jsp
新建一个RedirectTest类
public class RedirectLogin extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//处理请求String username = req.getParameter("username");String password = req.getParameter("password");System.out.println(username+":"+password);//重定向,一定要注意路径问题,否则404resp.sendRedirect("/response/success.jsp");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
在web.xml中进行新的Servlet的注册
<servlet><servlet-name>RedirectLogin</servlet-name><servlet-class>com.yang.servlet.RedirectLogin</servlet-class>
</servlet>
<servlet-mapping><servlet-name>RedirectLogin</servlet-name><url-pattern>/login</url-pattern>
</servlet-mapping>
在index.jsp中进行编写代码
<html><body><h2>Hello World!</h2><%--这里提交的路径,需要寻找到项目的路径--%><%-- ${pageContext.request.contextPath}:代表当前的项目 --%><form action="${pageContext.request.contextPath}/login" method="get">用户名:<input type="text" name="username"> <br>密码:<input type="password" name="password"> <br><input type="submit"></form></body>
</html>
导入jsp的包
<dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.1</version>
</dependency>
新建一个success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>Title</title></head><body><h1>Success</h1></body>
</html>
启动服务器进入login
6.7、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息。
- 创建一个新的Maven项目:request
- 创建结构目录
- 改变web.xml的代码为最新版
- 将index.jsp删掉重新创建index.jsp
- 创建包com.yang.servlet
- 设置Tomcat对应的项目为request ,设置url访问路径为:/request
6.7.1、获取前端传递的参数 请求转发
获取参数方法:
- getParameter(String s)
- getParameterMap() 很少用
- getParameterNames() 很少用
- getParameterValues(String s)
包内新建一个类LoginServlet
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");//接收处理参数String username = req.getParameter("username");String password = req.getParameter("password");String[] hobbies = req.getParameterValues("hobbies");System.out.println("======================");System.out.println(username);System.out.println(password);//输出数组:Arrays.toString(hobbies)System.out.println(Arrays.toString(hobbies));System.out.println("======================");//输出对应项目的路径System.out.println(req.getContextPath());//通过请求转发//这里的 / 代表当前web应用req.getRequestDispatcher("/success.jsp").forward(req,resp);}
}
在web.xml中注册Servlet
<servlet><servlet-name>LoginServlet</servlet-name><servlet-class>com.yang.Servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>LoginServlet</servlet-name><url-pattern>/login</url-pattern>
</servlet-mapping>
在index.jsp中编写代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>index</title>
</head>
<body>
<h1>登陆</h1><div style="text-align: center">
<%-- 这里表单提交的方式:以post方式提交表单,提交到login页面--%><form action="${pageContext.request.contextPath}/login" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br>爱好:<input type="checkbox" name="hobbies" value="学习">学习<input type="checkbox" name="hobbies" value="旅游">旅游<input type="checkbox" name="hobbies" value="听歌">听歌<input type="checkbox" name="hobbies" value="打羽毛球">打羽毛球<input type="checkbox" name="hobbies" value="打网球">打网球<br><input type="submit"></form>
</div>
</body>
</html>
新建一个success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>登陆成功!</title></head><body><h1>登陆成功!</h1></body>
</html>
请求转发与重定向的区别:
相同点:
- 页面都会跳转
不同点:
- 请求转发的时候,url不会发生变化 307
- 重定向的时候,url变成重定向地址的url 302
7、Cookie、Session
Cookie:饼干
Session:会话
- 新建一个maven项目javaweb-session-cookie
- 进行项目结构的创建
- java包中新建包com.yang.servlet
7.1、会话
**会话:**用户打开一个浏览器,点击多个超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话。
**有状态会话:**一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话
你能怎么证明你是大学学生?
你 学校
- 发票 学校给你发票 cookie方法
- 学校登记 学校标记你来过 session方法
一个网站,怎么证明你来过?
客户端 服务器
- 服务器给客户端一个信件,客户端下次访问服务器带上信件就可以了;cookie
- 服务器登记你来过了,下次你来的时候我来匹配你;session
7.2、保存会话的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息?我们可以把信息数据放到session中!
常见场景:网站登录之后,你下次不用再登陆了,第二次访问直接就上去了!
7.3、Cookie
- 从请求中拿到cookie信息
- 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的value
new Cookie("lastLoginTime",System.currentTimeMills()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效日期
resp.addCookie(cookie); //响应给客户端一个cookie
包内新建类CookieDemo01
//保存上一次用户访问的时间
//服务器告诉你上一次你来的时间,把这个时间封装成信件,你下次来的时候带上,服务器就知道你来了
public class CookieDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决中文乱码问题resp.setContentType("text/html;charset=utf-8");req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");PrintWriter out = resp.getWriter();//Cookie(服务器从客户端获取的),可能有多个Cookie[] cookies = req.getCookies();//判断Cookie是否存在if (cookies!=null){//如果存在就输出out.write("您上一次访问本网站的时间:");for (int i = 0; i < cookies.length; i++) {Cookie cookie = cookies[i];//判断cookie的名字是不是lastTime(获得cookie的值)if(cookie.getName().equals("lastTime")){//获取cookie的值,转成长整形,获取时间戳long lastLoginTime = Long.parseLong(cookie.getValue());Date date = new Date(lastLoginTime);//将时间转换成字符串,并输出out.write(date.toLocaleString());}}}else{//如果不存在
// URLEncoder.encode("欢迎第一次登陆本站!","utf-8");
// out.print(URLDecoder.decode("欢迎第一次登陆本站!","utf-8"));out.write("欢迎第一次登陆本站!");}//服务器给客户端响应一个cookie, System.currentTimeMillis() + ""转成字符串Cookie cookie = new Cookie("lastTime", System.currentTimeMillis() + "");//设置cookie的有效时间为1天cookie.setMaxAge(25*60*60);//服务器将cookie响应给客户端resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
在web中进行CookieDemo01的Servlet注册与映射
<servlet><servlet-name>CookieDemo01</servlet-name><servlet-class>com.yang.Servlet.CookieDemo01</servlet-class>
</servlet>
<servlet-mapping><servlet-name>CookieDemo01</servlet-name><url-pattern>/cookie1</url-pattern>
</servlet-mapping>
cookie:一般保存在本地的 用户目录下 appdate;
一个网站cookie是否存在上限!聊聊细节问题
- 一个cookie只能保存一个信息;
- 一个web站点(服务器)可以给浏览器发送多个cookie,最多存放20个cookie;
- Cookie大小有限制,最多4kb;
- 浏览器上限300个cookie
删除cookie:
- 不设置有效期,关闭浏览器,自动失效;
- 设置有效期时间为0
删除cookie,设置时间为0,新建一个类CookieDemo02
public class CookieDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//服务器给客户端响应一个cookie, System.currentTimeMillis() + ""转成字符串Cookie cookie = new Cookie("lastTime", System.currentTimeMillis() + "");//设置cookie的有效时间为1天cookie.setMaxAge(0);//服务器将cookie响应给客户端resp.addCookie(cookie);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
在web.xml中进行CookieDemo02的Servlet注册与映射
<servlet><servlet-name>CookieDemo02</servlet-name><servlet-class>com.yang.Servlet.CookieDemo02</servlet-class>
</servlet>
<servlet-mapping><servlet-name>CookieDemo02</servlet-name><url-pattern>/cookie2</url-pattern>
</servlet-mapping>
启动服务器,先访问cookie1创建cookie,在访问cookie2删除cookie,再访问cookie1确定cookie已经被删除
编码、解码问题
编码:URLEncoder.encode(“扬启”,“utf-8”);
解码:URLDecoder.decode(“值”,“UTF-8”);
7.4、Session(重点)
什么是Session:
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在。
- 用户登录之后,整个网站它都可以访问! -->保存用户的信息,保存购物车的信息…
Session中的一些方法:
- getCreationTime(); 获得创建时间
- getId(); 获得唯一的标识符
- getServletContext(); 获得web服务
- getAttribute(String); 获得结点
- setAttribute(String);
- removeAttribute(String);
- isNew(); 判断是不是新的
- invalidate(); 注销
Session和Cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session是把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象是由服务器创建
Session使用场景:
- 保存一个登陆用户的信息
- 购物车信息
- 在整个网站中经常会使用的数据,我们将它保存在Session中
7.4.1、Session测试
新建一个SessionDemo01类来测试Session,并进行Servlet的注册与映射
SessionDemo01类
public class SessionDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决中文乱码问题resp.setContentType("text/html;charset=utf-8");req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");//获得一个SessionHttpSession session = req.getSession();//给session中存入东西session.setAttribute("name","扬启");/*session创建的时候做了什么事情:* Cookie cookie = new Cookie("key",value);* resp.addCookie(cookie);* *///获取session的idString id = session.getId();//判断session是不是新创建的if (session.isNew()){resp.getWriter().write("session已经新建完成,id为:"+id);}else{resp.getWriter().write("session的id为:"+id);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
web.xml
<servlet><servlet-name>SessionDemo01</servlet-name><servlet-class>com.yang.Servlet.SessionDemo01</servlet-class>
</servlet>
<servlet-mapping><servlet-name>SessionDemo01</servlet-name><url-pattern>/session1</url-pattern>
</servlet-mapping>
启动服务器,进行测试
7.4.2、创建一个Session,在另外一个Servlet中去取
取出一个字符串:
新建一个SessionDemo02类来取Session,并进行Servlet的注册与映射
SessionDemo02类
public class SessionDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决中文乱码问题resp.setContentType("text/html;charset=utf-8");req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");//获取sessionHttpSession session = req.getSession();//得到另一个session的值String name =(String) session.getAttribute("name");System.out.println(name);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
web.xml
<servlet><servlet-name>SessionDemo02</servlet-name><servlet-class>com.yang.Servlet.SessionDemo02</servlet-class>
</servlet>
<servlet-mapping><servlet-name>SessionDemo02</servlet-name><url-pattern>/session2</url-pattern>
</servlet-mapping>
启动服务器,访问session2,输出结果为:null
启动服务器,先访问session1,再访问session2,输出结果为:扬启
取出一个对象:
- 新建一个包pojo
- 包内创建一个类Person
Person类
public class Person{private String name;private int age;public Person(){}public Person(String name,int age){this.name = name;this.age = age;}public String getName(){return name;}public void setName(String name){this.name;}public String getAge(){return age;}public void setAge(int age){this.age = age;}@Overridepublic String toString(){return "Person{"+"name'"+name+'\''+",age="+age+'}';}}
修改SessionDemo01类
public class SessionDemo01 extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOExeption{//解决中文乱码问题resp.setContentType("text/html;charset=utf-8");req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");//获得一个SessionHttpSession session = req.getSession();//给session中存入东西session.setAttribute("name",new Person("扬启",22));/*session创建的时候做了什么事情:* Cookie cookie = new Cookie("key",value);* resp.addCookie(cookie);* *///获取session的idString id = session.getId();//判断session是不是新创建的if (session.isNew()){resp.getWriter().write("session已经新建完成,id为:"+id);}else{resp.getWriter().write("session的id为:"+id);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
将SessionDemo02中的:String person = (String)session.setAttribute(“name”);
改为:Person person = (Person)session.setAttribute(“name”);
System.out.println(person.toString());
启动服务器,先访问session1,再访问session2,输出结果为:Person{name=‘扬启’,age=22}
7.4.3、注销Session【invalidate();】
新建一个类SessionDemo03
SessionDemo03类
public class SessionDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决中文乱码问题resp.setContentType("text/html;charset=utf-8");req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");//获得sessionHttpSession session = req.getSession();//获取另一个session的值session.getAttribute("name");//移除namesession.removeAttribute("name");//手动注销session//注销session,相当于关闭浏览器session.invalidate();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
web.xml
<servlet><servlet-name>SessionDemo03</servlet-name><servlet-class>com.yang.Servlet.SessionDemo03</servlet-class>
</servlet>
<servlet-mapping><servlet-name>SessionDemo03</servlet-name><url-pattern>/session3</url-pattern>
</servlet-mapping>
启动服务器,访问session1,再访问session3,再访问session2,结果报错:状态码500
启动服务器,访问session1,再访问session3,再访问session1,结果:sessionId发生改变
7.4.4、会话自动过期
设置Session默认的失效时间:
<servlet>...</servlet>
<servlet-mapping>...</servlet-mapping><!-- 设置Session默认的失效时间 -->
<session-config> <!--session的配置--><!-- 15分钟后Session失效,以分钟为单位 --><session-timeout>15</session-timeout>
</session-config>
8、JSP
8.1、什么是JSP
JSP(Java Server Pages):Java服务器端页面,也是和Servlet一样,用于动态Web技术!
最大的特点:
- 写JSP就像在写HTML
- 区别:
- HTML只给用户提供静态的数据
- JSP页面中可以嵌入Java代码,为用户提供动态数据。
8.2、JSP原理
思路:JSP到底怎么执行!
代码层面没有任何问题
服务器内部工作
tomcat中有一个work目录(服务器工作的目录)
Idea中使用Tomcat,会在Idea的tomcat中生成一个work目录
我的电脑地址:
C:\Users\suma\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-02-Servlet_2\work\Catalina\localhost\response\org\apache\jsp
发现页面转变成了Java程序:
浏览器向服务器发送请求,不管访问什么资源,都是在访问Servlet!
JSP最终也会被转换成一个Java类!
JSP本质上就是一个Servlet!
//初始化
public void _jspInit(){}//销毁
public void _jspDestroy(){}//JSPService 请求服务
public void _jspService(HttpServletRequest request,HttpServletResponse response){}
判断请求
内置一些对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文 javax.Servlet.HttpSession session = null; //session final javax.servlet.ServletContext application; //applicationContext final javax.servlet.ServletConfig config; //config 配置 final javax.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; HttpServletRequest request //请求 HttpServletResponse response //响应
输出页面前增加的代码
response.setContentType("text/html"); //设置响应的页面类型 pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
以上的这些对象我们可以直接在JSP页面中直接使用!
example:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>登陆成功!</title></head><body><%String name = "yangqi";%>name:<%=name%></body>
</html>
在JSP页面中:
只要是Java代码,就会原封不动的输出,如果是HTML代码,就会被转换成类似于:
out.write("name");
这样的格式,输出到前端。
8.3、JSP基础语法
任何语言都有自己的语法,java有,jsp作为Java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可),java所有语法都支持!
新建一个普通的Maven项目javaweb-jsp
鼠标在项目,右键,选择Add Framework Suupport… 再选择Web Application --> 将普通的项目变成web项目
导包
<dependencies><!--servlet依赖--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><!--jsp依赖--><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version></dependency><!--jstl表达式的依赖--><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version></dependency><!--standard标签库--><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency> </dependencies>
配置tomcat
JSP表达式
<%--JSP表达式作用:用来将程序的输出,输出到客户端<%= 变量或者表达式%>
--%><%= new java.util.Date()%>
jsp脚本片段
<%--jsp脚本片段--%>
<%int sum =0;for(int i=1;i<=100;i++){sum+=i;}out.println("<h1>Sum="+sum+"</h1>");
%>
脚本片段的再实现
<%int x =10;out.println(x);
%>
<p>这是一个JSP文档</p>
<%<%--int x =10;错误,变量名相同,不能重复定义--%>int y =10;out.println(y);
%>
<hr><%--在代码中嵌入HTML元素--%>
<%for(int i=0;i<5;i++){
%>
<h1>Hello World!<%= i%></h1>
<%}
%>
JSP声明(全局):加一个==!==表示代码写进_jspService方法外面(会被编译到该**.jsp文件生成的java的类**中!)
<%--加一个!表示代码写进_jspService方法外面(会被编译到该.jsp文件生成的java的类中!)-%>
<%!static{System.out.println("Loading Servlet!");}private int globalVar = 0;public void yang(){System.out.println("进入了方法yang!");}
%>
EL表达式
${new java.util.Date()}
JSP的注释,不会再客户端显示,HTML就会!
8.4、JSP指令
<%@ page args...%>
<%--定制错误页面--%>
<%--<%@page errorPage="error/404.jsp" %>--%>
<%--显示的声明这是一个错误页面--%>
<%--<%@page isErrorPage="true" %>--%>
<%--<%@page pageEncoding="UTF-8" %>--%><%@ include file=""%>
1、<%@ page …%>
- 进入指定的错误页通过设置<%@ page %>
web目录下新建一个jsp–>index2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--定制错误页面--%> <%@ page errorPage="error/500.jsp" %><html><head><title>登陆成功!</title></head><body><%int x = 1/0;%></body> </html>
在web目录下新建文件夹error 和img
error文件夹下新建500.jsp和404.jsp
500.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>500错误</title> </head> <body><img src="../image/时空交界.jpg" alt="500" style="max-width: 100%;max-height: 100%"> </body> </html>
404.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>404错误</title></head><body><img src="../image/夜中星河.jpg" alt="404" style="max-width: 100%;max-height: 100%"></body></html>
- img文件夹下方一张500.png图片和一张404.png图片
进入指定错误页面通过配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><error-page><error-code>404</error-code><location>/error/404.jsp</location></error-page><error-page><error-code>500</error-code><location>/error/500.jsp</location></error-page></web-app>
2、<%@ include file=""%>
include(包含):可以用来提取公共页
新建一个文件夹common
common中新建header.jsp文件和footer.jsp文件
header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <h1>我是Header! </h1>
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <h1>我是footer! </h1>
web文件夹中新建index3.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><%--@include会将两个页面合二为一--%><%@ include file="common/header.jsp"%><h1>我是网页主体!</h1><%@ include file="common/footer.jsp"%><%--jsp标签jsp:include:拼接页面,本质还是三个--%><jsp:include page="/common/header.jsp"/><h1>我是网页主体!</h1><jsp:include page="/common/footer.jsp"/></body> </html>
web文件夹下的WEB-INF文件夹对用户不可见,客户端无法直接访问!通常放置一些重要的文件!
8.5、9大内置对象
九大内置对象包括:
- PageContext(页面的上下文) 存东西
- Request(请求) 存东西
- Response(响应)
- Session 存东西
- Application 【ServletContext】 存东西
- config【ServletConfig】
- out
- page 几乎不用
- exception
web文件夹下新建一个pageContextDemo01.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>内置对象</title>
</head>
<body><%--内置对象--%><%//存数据pageContext.setAttribute("name1","扬启1");//保存的数据只在一个页面有效request.setAttribute("name2","扬启2");//保存的数据只在一个请求中有效,请求转发会携带该数据session.setAttribute("name3","扬启3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器application.setAttribute("name4","扬启4");//保存的数据服务器中有效,从打开服务器到关闭服务器%><%--脚本片段中的代码,会被原封不动生成到.jsp.java中要求:这里面的代码,必须保证java语法的正确性--%><%//从pageContext中取出数据,我们通过寻找的方式//从底层到高层(作用域):page-->request-->session-->application//JVM:双亲委派机制String name1 =(String) pageContext.findAttribute("name1");String name2 =(String) pageContext.findAttribute("name2");String name3 =(String) pageContext.findAttribute("name3");String name4 =(String) pageContext.findAttribute("name4");String name5 =(String) pageContext.findAttribute("name5"); //不存在为空%><%--使用EL表达式输出:${}等价于<%= %>--%><h1>取出的值为:</h1><br><h3>${name1} <%=name1%></h3><h3>${name2}</h3><h3>${name3}</h3><h3>${name4}</h3><h3><%=name5%></h3> <%--用EL表达式不存在的值自动过滤掉,使用<%=%>不会--%>
</body>
</html>
web文件夹下新建一个PageDemo02.jsp (name1、name2作用域太低,运行结果只能取出name3、name4、name5)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>内置对象</title></head><body><%--脚本片段中的代码,会被原封不动生成到.jsp.java中要求:这里面的代码,必须保证java语法的正确性
--%><%//从pageContext中取出数据,我们通过寻找的方式//从底层到高层(作用域):page-->request-->session-->application//JVM:双亲委派机制String name1 =(String) pageContext.findAttribute("name1");String name2 =(String) pageContext.findAttribute("name2");String name3 =(String) pageContext.findAttribute("name3");String name4 =(String) pageContext.findAttribute("name4");String name5 =(String) pageContext.findAttribute("name5"); //不存在为空
%><%--使用EL表达式输出:${}等价于<%= %>--%>
<h1>取出的值为:</h1><br>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3><%=name5%></h3> <%--用EL表达式不存在的值自动过滤掉,使用<%=%>不会--%></body>
</html>
web文件夹下新建一个pageDemo03.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>内置对象</title></head><body><%--public static final int PAGE_SCOPE = 1;public static final int REQUEST_SCOPE = 2;public static final int SESSION_SCOPE = 3;public static final int APPLICATION_SCOPE = 4;//scope:作用域public void setAttribute(String name,Object attribute, int scope){switch(scope){case 1:this.mPage.put(name,attribute);break;case 2:this.mRequest.put(name,attribute);break;case 3:this.mSession.put(name,attribute);break;case 4:this.mApp.put(name,attribute);break;default:throw new IllegalArgumentException("Bad scope "+scope);}}--%><%pageContext.setAttribute("hello1","hello1",pageContext.SESSION_SCOPE);//等价于session.setAttribute("hello1","hello1");%></body>
</html>
转发:
web文件夹下新建一个pageContextDemo02.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>转发</title></head><body><%pageContext.forward("/index.jsp");request.getRequestDispatcher("index.jsp").forward(request,response);//上面两个代码结果相同:转发//在jsp中通常用pageContext.forward("index.jsp");%></body>
</html>
//存数据
pageContext.setAttribute("name1","扬启1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","扬启2号"); //保存的数据只在一个请求中有效,请求转发会携带这个数据
session.setAttribute("name3","扬启3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","扬启4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完就没用了!
session:客户端向服务器发送请求,产生的数据,用户用完了一会还有用,比如:购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可以用,比如:聊天数据
8.6、JSP标签、JSTL标签、EL表达式
<!--jstl表达式的依赖--><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version></dependency><!--standard标签库--><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency>
EL表达式: ${}
- 获取数据
- 执行运算
- 获取web开发的常用对象
- 调用Java方法(一般不用)
JSP标签
web文件夹下新建jsp, jsptag.jsp和jsptag2.jsp
jsptag.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>标签</title></head><body><h1>1</h1><%--jsp:include--%><%--转发的时候可以携带参数--%><%-- http://localhost:8080/jsptag.jsp?name=yangqi&age=22--%><jsp:forward page="/jsptag2.jsp"><jsp:param name="name" value="yangqi"></jsp:param><jsp:param name="age" value="22"></jsp:param></jsp:forward></body>
</html>
jsptag2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>转发页面</title></head><body><h1>2</h1><%--取出参数--%>名字:<%=request.getParameter("name")%>年龄:<%=request.getParameter("age")%></body>
</html>
JSTL:JSP标准标签库,是一个JSP标签集合,他封装了JSP应用的通用核心功能。
JSTL标签库的使用就是为了弥补HTML标签的不足,它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!
JSTL标签:
格式化标签
SQL标签
XML标签
核心标签(掌握部分)
必须引入JSTL核心标签库,我们才能使用JSTL标签 c代表core。
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%--导入就能使用标签--%>
标签 描述 <c:out> 用于在JSP中显示数据,就像<%=…> <c:set> 用于保存数据 <c:remove> 用于删除数据 <c:if> 与我们在一般程序中用的if一样 <c:choose> 本身只能当做<c:when>和<c:otherwise>的父标签 <c:when> <c:choose>的子标签,本身用来判断条件是否成立 <c:otherwise> <c:choose>的子标签,接在<c:when>之后,当<c:when>判断为false时执行 <c:forEach> 基础迭代标签,接受各种集合类型 <c:url> 使用可选的查询参数来创造一个URL … …
JSTL标签库使用步骤:
- 引用对应的taglib
- 使用其中的方法
- 在Tomcat中也需要引入jstl的包,否则会报错:jstl解析错误
<c:if> <c:out>标签的使用
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入jstl核心标签库,我们才能使用jstl核心标签库:core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>核心标签</title>
</head>
<body><h4>if测试</h4><form action="coreif.jsp" method="get"><%--EL表达式获取表单中的数据${param.参数名}--%><input type="text" name="username" value="${param.username}"><br><input type="password" name="password" value="${param.password}"><br><input type="submit" value="登陆"></form>
<%--判断:如果用户名是管理员就登陆成功--%>
<%--<%--%>
<%-- if(request.getParameter("username").equals("admin")){--%>
<%-- out.write("登陆成功!");--%>
<%-- }--%>
<%--%>--%><%--test一定要带:表示条件--%>
<c:if test="${param.username=='admin'}" var="isAdmin"><c:out value="管理员欢迎你!"/>
</c:if>
<c:out value="${isAdmin}"/></body>
</html>
<c:choose> <c:when> <c:otherwise> <c:set>标签的使用
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>corewhen标签</title>
</head>
<body><form action="corewhen.jsp" method="get"><input type="text" name="score" value="${param.score}"><br><input type="submit" value="查询">
</form><%--定义一个变量是score,值为85--%>
<c:set var="score" value="${param.score}"/><c:choose><c:when test="${score>=90}">你的成绩为优秀!</c:when><c:when test="${score>=60&&score<=90}">你的成绩为良!</c:when><c:when test="${score<60&&score>=0}">你的成绩为差!</c:when><c:otherwise>查询错误!</c:otherwise>
</c:choose></body>
</html>
<c:forEach>标签的使用
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>foreach标签</title>
</head>
<body><%ArrayList<String> people = new ArrayList<>();people.add(0,"张三");people.add(1,"李四");people.add(2,"王五");people.add(3,"赵六");people.add(4,"田七");request.setAttribute("list",people);
%>
<%--var:每一次遍历的变量items:要遍历的对象
--%>
<c:forEach var="people" items="${list}"><c:out value="${people}"/><br>
</c:forEach><hr>
<%--begin:从哪开始end:从哪结束step:步长
--%>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2"><c:out value="${people}"/><br>
</c:forEach>
</body>
</html>
9、JavaBean
Bean:豆子
JavaBean:可以叫做实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM。
ORM:对象关系映射
- 表–>类
- 字段–>属性
- 行–>对象
id | name | age | address |
---|---|---|---|
1 | 扬启1 | 21 | 河南 |
2 | 扬启2 | 22 | 湖北 |
3 | 扬启3 | 23 | 武汉 |
表对应的字段
class Person{private int id;private String name;private int age;private String address;
}
idea连接数据库报错:Server returns invalid timezone. Need to set ‘serverTimezone’ property.
点击Set time zone[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5TkdM9P-1636973029636)(5、JavaWeb.assets/image-20211111161209640.png)]
PS:
GMT(Greenwich Mean Time):格林威治标准时间
UTC:世界标准时间
CST(China Standard Time):中国标准时间
10、MVC三层架构
什么是MVC:Model View Controller (模型、视图、控制器)
10.1、早些年的开发:
用户直接访问控制层,控制层就可以直接操作数据库;
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护 servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码。架构:没有什么是加一层解决不了的。
程序员--->JDBC--->Mysql Oracle SqlServer...
10.2、MVC三层架构
Model:
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
View:
- 展示数据
- 提供链接发起Servlet请求(a,form,img…)
Controller(Servlet):
接收用户的请求:(request:请求参数,Session信息…)
交给业务层处理对应的代码
控制视图跳转
登陆--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数:username,password...)--->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确--->数据库
11、Filter(重点)
Shiro安全框架
Filter:过滤器,用来过滤网站的数据;
- 处理中文乱码
- 登录验证…
Filter开发步骤:
新建一个普通的maven项目javaweb-filter,add Framework Support一个web资源目录
配置Tomcat
新建包filter,filter内新建CharacterEncodingFilter的class文件
新建包servlet,servlet内新建ShowServlet的class文件
导包
编写过滤器
- 导包不要错
- 编写过滤器,实现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 servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {servletRequest.setCharacterEncoding("utf-8");servletResponse.setCharacterEncoding("utf-8");servletResponse.setContentType("text/html;charset=UTF-8");System.out.println("CharacterEncodingFilter执行前...");filterChain.doFilter(servletRequest,servletResponse); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!System.out.println("CharacterEncodingFilter执行后...");}//销毁public void destroy() {System.out.println("CharacterEncodingFilter销毁!");} }
- 实现Servlet,编写对应的功能
public class ShowServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// resp.setContentType("text/html"); // resp.setCharacterEncoding("utf-8");resp.getWriter().write("你好啊,世界!");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }
- web.xml文件的编写
<servlet><servlet-name>ShowServlet</servlet-name><servlet-class>com.yang.servlet.ShowServlet</servlet-class> </servlet> <servlet-mapping><servlet-name>ShowServlet</servlet-name><url-pattern>/servlet/show</url-pattern> </servlet-mapping> <!--未执行过滤器的页面--> <servlet-mapping><servlet-name>ShowServlet</servlet-name><url-pattern>/show</url-pattern> </servlet-mapping><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>com.yang.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping><filter-name>CharacterEncodingFilter</filter-name><!--只要是servlet下的任何请求,都会经过这个过滤器--><url-pattern>/servlet/*</url-pattern> </filter-mapping>
12、监听器
实现一个监听器的接口;(有n种)
新建包listener,listener下新建类OnlineCountListener
编写监听器
实现监听器的接口
//统计网站在线人数:统计session //listener监听:看你的一举一动 public class OnlineCountListener implements HttpSessionListener {//创建session监听//一旦创建session就会触发一次这个事件public void sessionCreated(HttpSessionEvent se) {ServletContext servletContext = se.getSession().getServletContext();System.out.println(se.getSession().getId());Integer onlineCount =(Integer) servletContext.getAttribute("OnlineCount");if (onlineCount==null){//onlineCount为空变为1onlineCount = new Integer(1);}else {//将onlineCount转成intint count = onlineCount.intValue();//onlineCount原数值在加1onlineCount = new Integer(count+1);}servletContext.setAttribute("OnlineCount",onlineCount);}//销毁session监听//一旦销毁session就会触发一次这个事件public void sessionDestroyed(HttpSessionEvent se) {ServletContext servletContext = se.getSession().getServletContext();Integer onlineCount =(Integer) servletContext.getAttribute("OnlineCount");if (onlineCount==null){//onlineCount为空变为0onlineCount = new Integer(0);}else {//将onlineCount转成intint count = onlineCount.intValue();//onlineCount原数值再减1onlineCount = new Integer(count-1);}servletContext.setAttribute("OnlineCount",onlineCount);}/*session销毁:* 1.手动销毁 getSession().invalidate();* 2.自动销毁 在web中配置session自动销毁时间* <session-config><session-timeout>1</session-timeout></session-config>* */ }
在web.xml中注册监听器
<!--、注册监听器--><listener><listener-class>com.yang.listener.OnlineCountListener</listener-class></listener>
看情况是否使用
13、过滤器、监听器的常见应用
包listener内新建类TestPanel
13.1、监听器在GUI(图形用户界面)编程中的运用
public class TestPanel{public static void main(String[] args) {final Frame frame = new Frame("Java监听器"); //新建一个窗体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() {//适配器模式//关闭窗口@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});}
}
监听器在GUI编程中经常运用
用户登陆之后才能进入主页!用户注销就不能进入主页了!
13.2、过滤器的常见应用
13.2.1、不含过滤器的登陆功能
- 在web目录中新建一个sys目录,sys目录中新建jsp–>success.jsp
- web目录下新建jsp–>Login.jsp、error.jsp
- 在包servlet下新建类LoginServlet和类LogoutServlet
- 新建一个包utils,包内新建类Constant
Login.jsp登陆页面的编写
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登陆用户</title>
</head>
<body><form action="/servlet/login" method="post" style="text-align: center"><h1 style="text-align: center">用户登陆</h1><input type="text" name="username"><br><input type="password" name="password"><br><input type="submit" value="登陆"></form></body>
</html>
Constant提取常数类的编写
public class Constant {//将SESSION提取出来,提取成常量public final static String USER_SESSION="USER_SESSION";
}
LoginServlet功能的编写
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取前端请求的参数String username = req.getParameter("username");String password = req.getParameter("password");if(username.equals("admin")){ //登陆成功//在session中存一个常数req.getSession().setAttribute("USER_SESSION",req.getSession().getId());//重定向resp.sendRedirect("/sys/success.jsp");}else{ //登陆失败resp.sendRedirect("/error.jsp");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
success.jsp页面的编写
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>主页</title>
</head>
<body><%Object userSession = request.getSession().getAttribute("USER_SESSION");if (userSession==null){response.sendRedirect("/Login.jsp");}
%>
<h1 style="text-align: center">主页</h1><p style="text-align: center"><a href="/servlet/logout">注销</a></p></body>
</html>
LogoutServlet注销功能的编写
public class LogoutServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Object user_session = req.getSession().getAttribute("USER_SESSION");if (user_session!=null){//如果存在session,就移除sessionreq.getSession().removeAttribute("USER_SESSION");resp.sendRedirect("/Login.jsp");}else {resp.sendRedirect("/Login.jsp");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
error.jsp错误页面的编写
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>错误</title>
</head>
<body><div style="text-align: center"><h1>错误!</h1><h3>用户名或密码错误!</h3><a href="Login.jsp">返回登录页面</a>
</div></body>
</html>
web.xml注册
<servlet><servlet-name>LoginServlet</servlet-name><servlet-class>com.yang.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>LoginServlet</servlet-name><url-pattern>/servlet/login</url-pattern>
</servlet-mapping><servlet><servlet-name>LogoutServlet</servlet-name><servlet-class>com.yang.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>LogoutServlet</servlet-name><url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>
13.2.2、含有过滤器的登录功能
- 包filter内新建一个类SysFilter
用户登录之后,向session中放入用户的数据
进入主页的时候要判断用户是否已经登录,要求:在过滤器中实现!
public class SysFilter implements Filter {public void init(FilterConfig filterConfig) throws ServletException {}public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {//ServletRequest 不同于 HttpServletRequest//强制转换HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) resp;//获取session的值Object user_session = request.getSession().getAttribute(Constant.USER_SESSION);if (user_session==null){response.sendRedirect("/error.jsp");}//链子:继续往下走chain.doFilter(request,response);}public void destroy() {} }
14、JDBC
什么是JDBC(Java DataBase Connection):Java连接数据库!
需要jar包:
- java.sql
- javax.sql
- mysql-connector-java…连接驱动(必须要导入)
实现环境搭建:
- 创建数据库jdbc,数据库内新建表users
CREATE TABLE users (id INT PRIMARY KEY,`name` VARCHAR(50),`password` VARCHAR(30),email VARCHAR(50),birthday DATE
);INSERT INTO users(id,`name`,`password`,email,birthday)
VALUE(1,'张三','123456','yq@qq.com','2020-01-01')
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUE(2,'李四','123123','ls@qq.com','2020-01-02')
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUE(3,'王五','123321','ww@qq.com','2020-01-03')SELECT * from users;
导入数据库依赖
<dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency> </dependencies>
idea连接数据库
新建包com.yang.Test,包内新建类TestJdbc
public class TestJdbc {public static void main(String[] args) throws ClassNotFoundException, SQLException {//配置信息//useUnicode=true&characterEncoding=utf-8:解决中文乱码//useSSL=true:安全连接String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=true";String username = "root";String password = "123456";//1.加载驱动Class.forName("com.mysql.jdbc.Driver");//2.连接数据库,代表数据库 DriverManager:驱动管理Connection connection = DriverManager.getConnection(url, username, password);//3.向数据库发送sql对象:statement,用它来进行CRUD(增、删、改、查)//connection.prepareStatement(sql);预编译:放在后面Statement statement = connection.createStatement();//4.编写sqlString sql = "select * from users;";//5.执行查询sql,返回一个resultsetResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()){System.out.println("id="+resultSet.getObject("id"));System.out.println("name="+resultSet.getObject("name"));System.out.println("password="+resultSet.getObject("password"));System.out.println("email="+resultSet.getObject("email"));System.out.println("birthday="+resultSet.getObject("birthday"));System.out.println("==================================");}//6.关闭连接,释放资源,按照建立的后先顺序(一定要做,先开后关)resultSet.close();statement.close();connection.close();} }
预编译PreparedStatement:
public class TestJdbc2 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//配置信息//useUnicode=true&characterEncoding=utf-8:解决中文乱码//useSSL=true:安全连接String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=true";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(?,?,?,?,?)";String sql = "update users set name=? where id = 4";//4.预编译PreparedStatement preparedStatement = connection.prepareStatement(sql);/*preparedStatement.setInt(1,4);//给第一个占位符? 的值赋值为1preparedStatement.setString(2,"moxi");preparedStatement.setString(3,"123456");preparedStatement.setString(4,"mx@qq.com");preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
*/preparedStatement.setString(1,"沫汐");//5.执行sqlpreparedStatement.executeUpdate();//6.关闭连接,释放资源preparedStatement.close();connection.close();}
}
JDBC固定步骤:
- 加载驱动
- 连接数据库
- 向数据库发送SQL的对象statement:执行CRUD
- 编写sql(根据业务,不同的sql)
- 执行sql
- 关闭连接
事务
事务:
要么都成功,要么都不成功!
ACID原则:保证数据的安全。
开启事务
事务提交 commit();
事务回滚 rollback();
关闭事务转账:A:1000B:1000A(剩900) --100--> B(剩1100)
Junit单元测试:
依赖:
<!--单元测试:@Test注释让方法可以单独执行-->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version>
</dependency>
简单使用:@Test注解只有在方法上有效,加了这个注解的方法就可以单独执行
public class TestJdbc3 {@Testpublic void test(){System.out.println("Hello");}
}
成功:输出结果 失败:报错
数据库新建一个表,account,表内添加数据:
CREATE TABLE account(id INT PRIMARY KEY,`name` VARCHAR(30),money FLOAT
);INSERT INTO account(id,`name`,money) VALUES(1,'A',1000),(2,'B',1000),(3,'C',1000)
数据库添加事务代码:
start transaction ; #开启事务update account set money = money-100 where name = 'A';
update account set money = money+100 where name = 'B';rollback ;commit ;
包Test内新建一个类TestJdbc3
public class TestJdbc3 {@Testpublic void test() {String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8&useSSL=true";String username = "root";String password = "123456";Connection connection = null;PreparedStatement preparedStatement = null;try {//1.加载驱动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'";preparedStatement = connection.prepareStatement(sql);preparedStatement.executeUpdate();//制造错误//int i = 1/0;String sql2 = "update account set money = money+100 where name = 'B'";connection.prepareStatement(sql2).executeUpdate();connection.commit(); //以上两条sql都执行成功了就提交事务} catch (Exception e) {//如果出现异常,就通知数据库回滚事务try {connection.rollback();} catch (SQLException throwables) {throwables.printStackTrace();}}finally {try {preparedStatement.close();connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}
}
完整版JavaWeb环境搭建-maven-servlet...与测试,欢迎大家一起学习相关推荐
- 一天一阔阔儿ZYNQ的linux移植完整版(Linux环境搭建以及内核编译)
虚拟机UBUNTU12.04 64bit 701N 芯片是7020clg400 XILINX的交叉编译器安装 主要就是安装出现的一些问题,方法总结: 主要涉及的问题是,ubuntu12.04 64位系 ...
- linux 内网环境搭建 maven 私库
linux 内网环境搭建 maven 私库 参考资料: https://www.codenong.com/cs106446840/ https://blog.csdn.net/lch_wyl/arti ...
- 基于30系显卡以及Ubuntu18.04系统的YOLOv3环境搭建和训练模型以及测试
基于30系显卡以及Ubuntu18.04系统的YOLOv3环境搭建和训练模型以及测试 安装环境 下面是官网对N卡框架以及驱动和cuda版本的部分对应关系 驱动 (可以跳过这段安装,你可以在安装CUDA ...
- poc测试环境准备_华为桌面云 【环境搭建类】 Poc测试经验总结-环境搭建
Poc测试经验总结-环境搭建 1 内容概要 使用现场服务器.交换机.光存储,搭建Poc测试环境. 2 版本信息 FusionSphereV100R005C10:FusionSphere V100R00 ...
- 深信服连接openldap_完整版的OpenLDAP搭建全过程
总结: 先写总结,再写正文,嘿嘿嘿.这还是第一次认真的写个文档,写个总结,哈哈.大概在一个月前,第一次听说这个东西,完全没有概念,刚开始的时候看理论的知识,看了几次之后就没看了,看不懂啊.太抽象了,真 ...
- 环境搭建--maven
**1.互联网公司特点: *1.1行业特点: 1.1.1分布式 1.1.1.1分布式计算 说明:将一项任务,交给多台计算机共同处理. 例子:一项任务一个人单独完成需要10个小时.如果10个人同时干活, ...
- JavaWeb环境搭建之配置Tomcat
目录 一.配置 Tomcat 步骤 二.配置 Tomcat 可能出现的问题 一.配置 Tomcat 步骤 首先,下载tomcat文件 1. Window -> Preferences ...
- Java访问华为云_华为云操作记录——JavaWeb 环境搭建
华为云操作记录 创建用户 新建用户 sudo adduser weirwei 添加免密 root 权限 sudo vim /etc/sudoers 添加 root 权限 sudo 免密 切换到自己用户 ...
- IOT物联网商业源码完整版下载附搭建教程
简介: 说是值2000多块钱的东西.里面是有教程搭建教程.数据库在里面,点击教程里面数据库的那个图标.精美到桌面或者其他地方就OK了,我测试后台是能进去的,前台进不去去,原因不明....感兴趣的大佬自 ...
- javaweb环境搭建—— 误删mysql服务(sc delete mysql)
Mysql 误删mysql服务(sc delete mysql)(该版本是MySQL8.0) 参考:https://www.jb51.net/article/26505.htm Navicat 连接m ...
最新文章
- Error in plot.new(): figure margins too large
- 逻辑回归Logistic Regression 模型简介
- C 基本语法 | 菜鸟教程
- 移动web端的react.js组件化方案
- Python 游戏辅助基础之 Aircv
- 30 道 MySQL 基础知识
- H5动画实现简单的转盘抽奖。
- C++的引用一,求二次方根
- 技校学计算机当兵,学员(部分)作业选登:《两年计划》读完技校,考上中专,然后去当兵(图)...
- 如何批量调整论文中公式大小--mathtype
- 电脑软件打开出现闪退的问题
- iOS开发备战金三银四·头条三面记录
- 星辰小队针对于软件“星遇”的10天冲刺——第7天
- bark 自建服务器,自建iOS消息推送服务Bark
- stem教育与创客教育
- ANDROID 背光调节
- 广东省新型数据中心发展白皮书
- python切割txt文件_用Python实现大文本文件切割的方法
- Linux系统引导和服务
- SSH客户端中文乱码
热门文章
- [C#]LambdaTest
- access里面的表达式运用_ACCESS条件表达式用法
- 怎样才能让datetime字段去掉最后面的小时、分、秒
- 很好奇这个背景图片,盯着看能感受到裸眼3D有没有
- Android 通知用法
- API文档打开显示'已取消到该网页的导航'的解决方法
- 程序员成功之路 ——The road ahead for programmer(演讲稿)
- 个编得好的拼音输入法C51的
- 宿命论,三年前的演讲稿!,怀念那些力不从心的光景。。
- 记录一次接入Unity IAP Tapjoy 等SDK的过程,坑了一周,快吐血了