web 开发:
web,网页,例如 : www.baidu.com
静态web
动态web
在Java中动态web资源开发的技术都称为javaweb;
web应用程序:可以提供浏览器访问的程序;
html文件,a.html、b.html等多个资源,这些web资源可以被外界访问,对外界提供服务;
我们能访问到的任何一个页面或者资源都存在于世界上的某一个计算机中
URL:统一资源定位符
这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat服务器
一个web应用由多部分组成(静态web,动态web)
web应用程序编写完毕后,如果想要提供给外界访问,需要一个服务器来统一管理
页面会动态:“web的页面展示的效果每个人都不同";
缺点
优点:
web页面可以动态更新,所有的用户看到的界面都不是同一个页面
它可以与数据库交互
基于ASP,JSP,php
JSP/Servlet:
B/S:浏览器和服务器
C/S:客户端和服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
微软的:ASP,windows中自带
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。
tomcat的默认端口号:8080
mysql的默认端口:3306
http 的默认端口:80
https默认端口:443
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- 默认网站应用存放的位置为:wabapps
name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
请你谈谈网站时如何进行访问的?
1、输入一个域名:回车
2、检查本机的C:\Windows\System32\drivers\hosts配置文件下有没有这个域名映射:
1.有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
2.没有去DNS服务器找,找到的话就返回,找不到就返回找不到
4.可以配置环境变量(可选项)
将自己写的网站,放到服务器(Tomcat)中指定的web应用文件夹下(webapps)下,就可以访问了,网站的基本结构:
-- webapps: Tomcat服务器web目录
-ROOT
-ruasibstudy:网站目录名
-WEB-INF
-classes : java程序
-lib:web应用所依赖的jar包
-web.xml
-index.html 默认的首页
-static
-css
-style.css
-js
-img
- .....
HTTP协议:面试
Maven :构建工具
Servlet入门
Helloword
Servlet配置
原理
超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。
https: 安全的超文本传输协议
http1.0
http2.0
百度:
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET 请求方法:get方法、post方法
Status Code: 200 OK 状态码:200
Remote Address: 14.215.177.38:443 百度的地址 + 端口
Cache-Control: private 缓存控制
Connection: keep-alive 连接方式:保持连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 文件类型:html,以及文件编码:utf-8
Date: Mon, 28 Jun 2021 01:43:29 GMT
Expires: Mon, 28 Jun 2021 01:43:28 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=386; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=33801_33966_31254_34113_33607_34134_34119; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1624844609018818305012084217433091881680
Transfer-Encoding: chunked
X-Ua-Compatible: IE=Edge,chrome=1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 告诉浏览器它所支持的数据类型
Accept-Encoding: gzip, deflate, br 支持哪种编码格式 :GBK、utf-8、GB2312、iso8859-1
Accept-Language: zh-CN,zh;q=0.9 告诉六拉起。他的语言环境
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉浏览器,请求完成的是断开连接和保持连接
HOST : 主机ip地址以及端口
服务器–响应—客户端
百度:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 0
Content-Type: image/gif
Date: Mon, 28 Jun 2021 01:43:31 GMT
Pragma: no-cache
Server: nginx/1.8.0
Set-Cookie: BAIDUID_BFESS=C23FC53DC981E34B8842BF60593436D4:FG=1; Path=/; Domain=baidu.com; Expires=Tue, 28 Jun 2022 01:43:31 GMT; Max-Age=31536000; Secure; SameSite=None
Set-Cookie: BDUSS_BFESS=k5GNVdXeXBCSjl3NUE0Z3hvSTVCT3NEUk5TakhjYXhLS3dQc2dNQWIyOTIwTTVnSVFBQUFBJCQAAAAAAAAAAAEAAABpXVFFXzEydgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZDp2B2Q6dgY; Path=/; Domain=baidu.com; Expires=Thu, 26 Jun 2031 01:43:31 GMT; Max-Age=315360000; HttpOnly; Secure; SameSite=None
Tracecode: 26119272462803688714062809
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 告诉浏览器它所支持的数据类型
Accept-Encoding: gzip, deflate, br 支持哪种编码格式 :GBK、utf-8、GB2312、iso8859-1
Accept-Language: zh-CN,zh;q=0.9 告诉六拉起。他的语言环境
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉浏览器,请求完成的是断开连接和保持连接
HOST : 主机ip地址以及端口
Refresh: 告诉客户端,多久刷新一次;
Location:让网页重新定位;
200 : 请求响应成功
3xx :请求重定向
4xx :找不 到资源 404
5xx : 服务器代码错误 500, 502 : 网关错误
当你的浏览器中地址输入地址并回车的一瞬间到页面能够显示回来,经历了什么?
1、再javaweb开发中,需要使用大量的jar包,我们手动去导入;
2、如何能够让一个东西自动帮我导入和配置这个jar包
下载解压即可;
提示:电脑上的所有环境都放在一个文件夹下,方便管理
再我们的系统环境变量下,配置如下:
测试maven是否安装成功,保证必须配置完毕!
镜像:mirrors
<mirror>
<id>nexus-aliyunid>
<mirrorOf>*,!jeecg,!jeecg-snapshotsmirrorOf>
<name>Nexus aliyunname> <url>http://maven.aliyun.com/nexus/content/groups/publicurl>
mirror>
在本地的仓库,远程仓库:
建立本地仓库:
<localRepository>E:\Dev_Language\JAVA\maven\apache-maven-3.6.2\maven-repolocalRepository>
1、启动IDEA
2、创建一个MavenWeb项目
3 然后等待项目初始化完成
4 查看仓库文件
5 idea中的maven设置
在这里maven在idea中配置的maven就ok了
一个带模板的maven
解决警告信息:
必须要解决这个问题:为什么会有这个问题?因为我们访问一个网站需要指定一个文件夹名字
pom.xml 是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.0modelVersion>
<groupId>com.ruasibgroupId>
<artifactId>javaweb-01-mavenartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<name>javaweb-01-maven Maven Webappname>
<url>http://www.example.comurl>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.7maven.compiler.source>
<maven.compiler.target>1.7maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.11version>
<scope>testscope>
dependency>
dependencies>
<build>
<finalName>javaweb-01-mavenfinalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-pluginartifactId>
<version>3.1.0version>
plugin>
<plugin>
<artifactId>maven-resources-pluginartifactId>
<version>3.0.2version>
plugin>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.0version>
plugin>
<plugin>
<artifactId>maven-surefire-pluginartifactId>
<version>2.22.1version>
plugin>
<plugin>
<artifactId>maven-war-pluginartifactId>
<version>3.2.2version>
plugin>
<plugin>
<artifactId>maven-install-pluginartifactId>
<version>2.5.2version>
plugin>
<plugin>
<artifactId>maven-deploy-pluginartifactId>
<version>2.8.2version>
plugin>
plugins>
pluginManagement>
build>
project>
由于maven他的约定大于配置,我们可能遇到我们写的配置文件,无法被导出或者生效的问题
解决办法:
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
https://mvnrepository.com/
Java Servlet API
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
常见的HTTP状态码:
Content-Type(内容类型),一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。
Content-Type 标头告诉客户端实际返回的内容的内容类型。
语法格式:
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
另外一种常见的媒体格式是上传文件之时使用的:
Servlet就是sun公司开发动态web的一门技术
Sun在这些API中提供一个接口叫做Servlet,如果你想开发Servlet程序,只需要完成两个步骤:
实现了Servlet接口的java程序叫做,Servlet
Servlet在sun公司有两个默认的实现类:HttpServelt,GenericServlet
构建一个普通的maven项目,删掉除了配置文件外的所有东西,即删除src目录下的所有文件,以后学习就在这个项目中建立Moudel;这个空的项目就是maven的主工程;
关于maven父子工程的理解:
父工程的pom.xml文件中,有以下代码,而其中的,servlet-01就是其子工程
<modules>
<module>servlet-01module>
modules>
其中父项目的java子项目可以直接使用
Maven环境优化
编写一个Servlet程序
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("hello,servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
为什么需要映射:我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能访问的路径;
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>com.ruasib.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>\hellourl-pattern>
servlet-mapping>
web-app>
配置Tomcat
注意:配置项目发布的路径就可以了
Servlet是由web服务器调用,web服务器在收到浏览器请求后会:
一个Servlet可以指定一个映射路径:
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>servlet-01servlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/hahaurl-pattern>
servlet-mapping>
web-app>
一个Servlet可以指定多个映射路径
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>servlet-01servlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/hahaurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/haha1url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/haha2url-pattern>
servlet-mapping>
web-app>
一个Servlet可以指定通用映射路径
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>servlet-01servlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/haha/*url-pattern>
servlet-mapping>
web-app>
默认请求路径
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>servlet-01servlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
web-app>
指定以下后缀或者前缀等等…
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>servlet-01servlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/haha/*.ruasiburl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/haha/*.ruasiburl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>*.ruasiburl-pattern>
servlet-mapping>
web-app>
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<servlet>
<servlet-name>servlet-01servlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servlet-01servlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
web容器在启动的时候,他会为每个web程序创建一个对应的ServletContext,它代表了当前的web应用;
在这个Servlet中保存的数据,可以在另外一个servlet中拿到
// 将数据写入ServletContext
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter(String name); 初始化参数
// this.getServletConfig() Servlet配置
// this.getServletContext(); Servlet上下文对象
ServletContext servletContext = this.getServletContext();
String username = "ruasib"; // 数据
// 将一个数据保存在ServletContext中,键为username,值为username(变量)
servletContext.setAttribute("username",username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
// 从ServletContext中获取数据
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
// 将数据从contetx中按照键“username”来获取到对应的值(数据)
String username = (String)context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字="+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>com.ruasib.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
<servlet>
<servlet-name>getcservlet-name>
<servlet-class>com.ruasib.servlet.GetServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>getcservlet-name>
<url-pattern>/getcurl-pattern>
servlet-mapping>
web-app>
运行结果:
// 获取在web.xml文件中的标签的名为url的参数的数据
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 读取在web.xml文件中得到的xml参数
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
context-param>
<servlet>
<servlet-name>gpservlet-name>
<servlet-class>com.ruasib.servlet.ServletDemo3servlet-class>
servlet>
<servlet-mapping>
<servlet-name>gpservlet-name>
<url-pattern>/gpurl-pattern>
servlet-mapping>
web-app>
// 转发类
package com.ruasib.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求转发
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
// 获取转发的请求路径
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
// 调用forward实现请求转发
requestDispatcher.forward(req,resp);
// 第二种方式:实现请求转发
// context.getRequestDispatcher("/gp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
// 转发目的地
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("进入了ServletDemo03");
System.out.println("进入了ServletDemo03");
// 读取在web.xml文件中得到的xml参数
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
context-param>
<servlet>
<servlet-name>gpservlet-name>
<servlet-class>com.ruasib.servlet.ServletDemo3servlet-class>
servlet>
<servlet-mapping>
<servlet-name>gpservlet-name>
<url-pattern>/gpurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>sd4servlet-name>
<servlet-class>com.ruasib.servlet.ServletDemo4servlet-class>
servlet>
<servlet-mapping>
<servlet-name>sd4servlet-name>
<url-pattern>/sd4url-pattern>
servlet-mapping>
web-app>
运行结果:
Properties文件
发现:在没有解决Maven存在的资源导出问题时后,会将java目录下的文件无法被导出到target目录下,Maven存在的资源导出问题解决方案5.11章节中
当解决了Maven存在的资源导出问题后,重新生成文件,发现:两个目录下的properties文件都被打包到了同一个路径下:classes,我们俗称这个路径为classpath;
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class propertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// `/`代表当前web应用
// 读取目录 target/servlet-02-1.0-SNAPSHOT//WEB-INF/classes/db.properties 的文件
// InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
// 读取目录 target/servlet-02-1.0-SNAPSHOT//WEB-INF/classes/WEB-INF/classes/com/ruasib/servlet/aa.properties 的文件
InputStream inputStream = this.getServletContext().getResourceAsStream(
"/WEB-INF/classes/com/ruasib/servlet/aa.properties");
Properties prop = new Properties();
prop.load(inputStream);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().print(username+":"+password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>sd5servlet-name>
<servlet-class>com.ruasib.servlet.propertiesServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>sd5servlet-name>
<url-pattern>/sd5url-pattern>
servlet-mapping>
web-app>
# db.properties
username=ruasib
password=123456
# aa.properties
username=hasib
password=xcvbnm
文件结构:
运行结果:
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表HttpServletRequest对象,代表响应的一个HttpServletResponse;
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentType(String var1);
void sendRedirect(String var1) throws IOException;
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);
void setStatus(int var1);
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;
向浏览器输出消息
下载文件
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
public class FileDownServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 获取要下载文件的路径
String realPath = "D:\\java_workplace\\javaweb\\javaweb-servlet\\response\\" +
"target\\response-1.0-SNAPSHOT\\WEB-INF\\classes\\莉雅.jpg";
System.out.println("要下载的文件路径:"+realPath);
//2. 下载的文件名是什么?
// 最后一个 // 后的
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
//3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,使用URLEncoder.encode对中文文件名进行编码,
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
//4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
//5. 创建缓冲区
int len = 0;
byte[] buf = new byte[1024];
//6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
//7. 将FileOutputStream流写入到buffer缓冲区
// 使用OutputStream将缓冲区中的数据输出到客户端
while((len=in.read(buf))!=-1){
out.write(buf,0,len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>downservlet-name>
<servlet-class>com.ruasib.servlet.FileDownServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>downservlet-name>
<url-pattern>/downurl-pattern>
servlet-mapping>
web-app>
生成验证码
package com.ruasib.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置客户端每隔3秒自动刷新页面
resp.setHeader("refresh","3");
// 创建带缓冲区的图片对象,就相当于创建一个画板
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
// 使用笔画出图片
Graphics2D graphics2D = (Graphics2D) image.getGraphics(); // 笔
// 设置笔的颜色
graphics2D.setColor(Color.white);
graphics2D.fillRect(0,0,80,20);
// 给图片写数据
graphics2D.setColor(Color.BLUE);
graphics2D.setFont(new Font(null,Font.BOLD,20));
graphics2D.drawString(makeNum(),0,20);
// 将图片返回到客户端
resp.setContentType("image/jpg");
// 网站存在缓存 ,不让网站缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
// 将图片写给浏览器
boolean write = ImageIO.write(image,"jpg",resp.getOutputStream());
}
private String makeNum() {
Random random = new Random();
String num = random.nextInt(9999)+"";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4 - num.length(); i++) {
sb.append(0);
}
return sb.toString()+ num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>imgservlet-name>
<servlet-class>com.ruasib.servlet.ImageServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>imgservlet-name>
<url-pattern>/imgurl-pattern>
servlet-mapping>
web-app>
运行结果:
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// // 实现重定向
// resp.setHeader("Location","/res/img");
// // 重定向状态码:302
// resp.setStatus(302);// HttpServletResponse.SC_FOUND
resp.sendRedirect("/res/img"); // 重定向
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>imgservlet-name>
<servlet-class>com.ruasib.servlet.ImageServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>imgservlet-name>
<url-pattern>/imgurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>rsservlet-name>
<servlet-class>com.ruasib.servlet.ImageServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>rsservlet-name>
<url-pattern>/rsurl-pattern>
servlet-mapping>
web-app>
面试题:请你聊聊重定向和转发的区别?
相同点:
不同点:
转发和重定向
转发特点:
1.一次请求
2.地址不变
3.一个请求只有一个request,A和B可以通过他共享数据
4.只能转发到项目内部的资源
重定向的特点
1.二次请求
2.地址不变
3.二个请求有两个request,A和B无法通过他共享数据
4.可以重定向到项目外部的资源
小测试
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
// 重定向 ,一定要主要路径,否则404
resp.sendRedirect("/res/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>requestservlet-name>
<servlet-class>com.ruasib.servlet.RequestTestservlet-class>
servlet>
<servlet-mapping>
<servlet-name>requestservlet-name>
<url-pattern>/loginurl-pattern>
servlet-mapping>
web-app>
<%--index.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Hello World!
<%--这里提交的路径,需要寻找到项目的路径
${pageContext.request.contextPath}代表当前项目
--%>
<%-- success.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
success
运行结果:
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(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("hobby");
System.out.println("=========================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("=========================");
// / 表示当前web项目
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Applicationdisplay-name>
<servlet>
<servlet-name>LoginServletservlet-name>
<servlet-class>com.ruasib.servlet.LoginServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>LoginServletservlet-name>
<url-pattern>/loginurl-pattern>
servlet-mapping>
web-app>
<%--index.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登录
登录
<%--success.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登录成功
登录成功
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称为会话。
有状态会话:一个客户端来访问过服务器,下次再访问,服务器会知道这个客户端城景来过,称为有状态会话
一个网站,服务器怎么知道客户端访问过?
1、服务端给客户端一个信件,客户端下次访问带上信件就可以了(cookie)
2、服务器登记你来过了,下次来的时候服务器来匹配客户端;(session)
常见案例:网站登录后,就不需要再登录了。第二次访问直接上去了。
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
// 保存用户上一次访问的时间
public class CookieDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 服务器,告诉你,你来的时间,把这个时间封装成一个信件,你下次带来,我就知道你来了
// 解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
// 获取输出流
PrintWriter out = resp.getWriter();
//Cookie, 服务器从客户端获取到
Cookie[] cookies = req.getCookies();// 这里返回数组,说明Cookie可能存在多个
// 判断Cookie是否存在
if (cookies!=null){
// 如果存在,则取出数组中的Cookie
out.write("你上一次访问的时间是:");
for (Cookie cookie:cookies
) {
if(cookie.getName().equals("lastLoginTime")){
// 获取Cookie的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toString());
}
}
}else {
out.write("这是你第一次访问本站");
}
// 服务端给客户端响应Cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
// 设置 cookie最长的存活时间 ,即有效期为以 1 天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo1servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo1servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo1servlet-name>
<url-pattern>/c1url-pattern>
servlet-mapping>
web-app>
cookie:一般会保存再本地用户目录下appdata;
一个网站cookie是否存在上限?
删除Cookie:
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CookieDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建一个cookie,名字要和要删除的cookie一样
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 设置cookie的有效期为0
cookie.setMaxAge(0);
// 响应cookie给客户端
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo2servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo2servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo2servlet-name>
<url-pattern>/c2url-pattern>
servlet-mapping>
web-app>
运行结果:
先通过/c1
路径生成cookie,后通过\c2
路径删除cookie,由下列两图片看出cookie已经被删除
解决中文编码问题:
// 通过使用URLEncoder.encode("阿迪", "utf-8")函数,进行编码,
// 使用 URLDecoder.decode("阿迪","utf-8")函数,进行解码
// 上述两个方法,传入的参数都是字符串,第一个参数为要进行编码/解码的数据,第二个参数是需要转换成的编码类型
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class CookieDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
System.out.println("123");
// 获取 输出流
PrintWriter out = resp.getWriter();
// 获取cookie
Cookie[] cookies = req.getCookies();
// 判断是否有cookie
if (cookies != null){
out.write("上一次访问时间是:");
// 遍历查找cookie
for (Cookie cookie :cookies
) {
System.out.println(cookie.getName());
if(cookie.getName().equals("name")){
String value = URLDecoder.decode(cookie.getValue(),"utf-8");
out.write(value);
System.out.println(value);
}
}
}else{
out.write("第一次访问");
}
// 新建一个cookie
Cookie cookie = new Cookie("name", URLEncoder.encode("阿达","utf-8"));
cookie.setMaxAge(24*60*60);
// 给客户端响应cookie
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo3servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo3servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo3servlet-name>
<url-pattern>/c3url-pattern>
servlet-mapping>
web-app>
运行结果:
获取到了浏览器的所有cookie
<session-config>
<session-timeout>15session-timeout>
session-config>
什么是Session:
Session与Cookie的区别:
使用场景:
往session中存数据
package com.ruasib.session;
import com.ruasib.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class SessionDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 往sessoion中存对象
// 解决乱码问题
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
// 获取session对象
HttpSession session = req.getSession();
// 往session中存数据
session.setAttribute("person",new Person());
// 获取session的id
String sessionId = session.getId();
if (session.isNew()){
resp.getWriter().write("session创建,Id="+sessionId);
}else {
resp.getWriter().write("session已经在服务器中存在,Id="+sessionId);
}
// Session 创建的时候做了什么事情:
// Cookie cookie = new Cookie("JSESSIONID",sessionId);
// resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
往session中存和取对象
通过setAttribute(key,value)方法存对象,getAttribute(key)方法取对象,其中key-value为键值对,简单来说,就是一个key只能对应一个value, 比如 ”person“ 就是key ,value 就是 Person 对象
package com.ruasib.session;
import com.ruasib.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 获取session
HttpSession session = req.getSession();
// 获取session中的数据
Person person = (Person) session.getAttribute("person");
//
System.out.println(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
删除session中的数据,注销session
注销session后,服务器会自动销毁当前的sessionID,然后生成一个新的sessionID
package com.ruasib.session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 获取session对象
HttpSession session = req.getSession();
// 将person从session中删除
session.removeAttribute("person");
// 手动注销session,将session注销后,会自动生成一个新的sessionId
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
以上3个Servlet类的配置文件
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo1servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo1servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo1servlet-name>
<url-pattern>/c1url-pattern>
servlet-mapping>
<servlet>
<servlet-name>CookieDemo2servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo2servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo2servlet-name>
<url-pattern>/c2url-pattern>
servlet-mapping>
<servlet>
<servlet-name>CookieDemo3servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo3servlet-class>
servlet>
<servlet-mapping>
<servlet-name>CookieDemo3servlet-name>
<url-pattern>/c3url-pattern>
servlet-mapping>
<servlet>
<servlet-name>SessionDemo1servlet-name>
<servlet-class>com.ruasib.session.SessionDemo1servlet-class>
servlet>
<servlet-mapping>
<servlet-name>SessionDemo1servlet-name>
<url-pattern>/s1url-pattern>
servlet-mapping>
<servlet>
<servlet-name>SessionDemo2servlet-name>
<servlet-class>com.ruasib.session.SessionDemo2servlet-class>
servlet>
<servlet-mapping>
<servlet-name>SessionDemo2servlet-name>
<url-pattern>/s2url-pattern>
servlet-mapping>
<servlet>
<servlet-name>SessionDemo3servlet-name>
<servlet-class>com.ruasib.session.SessionDemo3servlet-class>
servlet>
<servlet-mapping>
<servlet-name>SessionDemo3servlet-name>
<url-pattern>/s3url-pattern>
servlet-mapping>
<session-config>
<session-timeout>15session-timeout>
session-config>
web-app>
Java Server Pages: java 服务端端页面,也和Servlet 一样,用于动态Web 技术!
最大的特点:
思路:JSP到底怎么执行的
在代码层面没有任何问题
服务器内部工作
Tomcat中有一个work目录;
在IDEA中使用Tomcat的话会在IDEA的Tomcat中生成一个work目录
一般位于C盘下的用户文件夹下的Admin下的.Intellijidea下存在一个index_jsp.class,
注意:
jsp
文件,那么你的项目是无法找到编译后的xxx_jsp.class
文件的没有发布项目的时候该目录下的状态
发布项目并访问相应路径后的状态
C:\Users\asd\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-session-cookie_2\work\Catalina\localhost\ROOT\org\apache\jsp
C:\Users\asd\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-session-cookie_2\work
// asd 为电脑的管理员名
// 其中,Unnamed_javaweb-session-cookie_2 是我当前运行的项目
// 当打开该路径下的文件夹,会发现页面打开文件到最后一个文件时jsp页面转变成了java类
在你安装的tomcat中work目录下,会存放将默认的jsp文件编译成class的文件:
E:\Dev_Language\Tomcat\apache-tomcat-8.0.20\work\Catalina\localhost\ROOT\org\apache\jsp
浏览器向服务器发送请求,不过访问什么资源,其实都是在访问Servlet
JSP最终也会被转换成一个java类,其本质就是一个Servlet
// 初始化
public void _jspInit() {}
// 销毁
protected void _jspDestroy() {}
public abstract void _jspService(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException;
1.判断请求
2.内置一些对象
final javax.servlet.jsp.PageContext pageContext;// 页面上下文
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.http.HttpSession session = null // session
HttpServletRequest req // 请求
HttpServletResponse resp // 响应
3、输出页面增加的代码
response.setContentType("text/html; charset=UTF-8"); // 设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, false, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
4.以上的这些对象可以直接在jsp页面中直接使用
在JSP页面中:
只要是java代码就会原封不动的输出;
如果是HTML代码,就会转化为:
out.write("\n");
out.write(" \n");
out.write(" $Title$ \n");
out.write(" \n");
out.write(" \n");
out.write(" $END$\n");
将上面类似的代码输出到前端。
任何语言都有自己的语法,java有。jsp作为java技术的一种应用也有,它用于一些自己扩充的语法,java所有所有语法都支持!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
标题
<%-- 代码 --%>
<%--
JSP 表达式
作用:用来输出数据 输出到客户端
语法:<%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
<%--
JSP 脚本片段
--%>
<%
int sum = 0;
for (int i = 0; i<=100;i++){
sum += i;
}
out.print("sum="+sum+"
");
%>
<%--在java代码直接嵌入HTML--%>
<%
int x = 10;
out.print(x);
%>
这是一个JSP文档
<%
int y = 5;
out.print(y);
%>
<%--在Java代码中嵌入HTML元素,并且将java代码分割--%>
<%
for (int i = 0; i < 3; i++) {
%>
Hello,world <%= i %>
<%
}
%>
会被编译到JSP生成java的类中!其他的jsp
脚本片段会被生成到_jspService
方法中。在jsp
中嵌入java代码即可
<%--
JSP声明 将变量,方法定义到类中
--%>
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void ruasib(){
System.out.println("进入了方法ruasib");
}
%>
执行代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%--
JSP 表达式
作用:用来输出数据 输出到客户端
语法:<%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
<%--
JSP 脚本片段
--%>
<%
int sum = 0;
for (int i = 0; i<=100;i++){
sum += i;
}
out.print("sum="+sum+"
");
%>
<%--在java代码直接嵌入HTML--%>
<%
int x = 10;
out.print(x);
%>
这是一个JSP文档
<%
int y = 5;
out.print(y);
%>
<%--在Java代码中嵌入HTML元素,将java代码分割--%>
<%
for (int i = 0; i < 3; i++) {
%>
Hello,world <%= i %>
<%
}
%>
<%--
JSP声明 将变量,方法定义到类中 使用 <%! 要定义到类中的方法或者变量 %>
--%>
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void ruasib(){
System.out.println("进入了方法ruasib");
}
%>
查看生成的xxx_jsp.class
结果如下:
控制台输出:
<%-- jsp2.jsp : 发生错误的页面--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--定义发生错误页面后的跳转目标--%>
<%@page errorPage="error/err.jsp" %>
Title
<%
int i = 1/0;
%>
<%--500.jsp :发生错误后跳转进来的页面--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
自定义错误页面
文件结构:
运行结果:
web.xml
文件来配置错误页面
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<%--404页面错误--%>
<error-page>
<error-code>404error-code>
<location>/error/404.jsplocation>
error-page>
<%--500页面错误--%>
<error-page>
<error-code>500error-code>
<location>/error/500.jsplocation>
error-page>
web-app>
对应的jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
运行结果:
原因:
在web项目发布以后,idea会在target
目录下导出你的文件,然后在浏览器访问你的数据时,访问的是你target
目录下的文件。比如我的上面说的无法加载出来的404.jpg
图片,就是因为maven
存在资源导出问题,资源导出问题解决方案,在我发布的5.11
章节中。
或者直接将target目录下没有的文件全部复制到相应的位置就能解决了
当target
目录下存在404.jpg
后,就能看到图片了
指令 | 描述 |
---|---|
<%@ page … %> | 定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include … %> | 包含其他文件 |
<%@ taglib … %> | 引入标签库的定义,可以是自定义标签 |
标签 | 描述 |
---|---|
jsp:include | 用于在当前页面中包含静态或动态资源 |
jsp:useBean | 寻找和初始化一个JavaBean组件 |
jsp:setProperty | 设置 JavaBean组件的值 |
jsp:getProperty | 将 JavaBean组件的值插入到 output中 |
jsp:forward | 从一个JSP文件向另一个文件传递一个包含用户请求的request对象 |
jsp:plugin | 用于在生成的HTML页面中包含Applet和JavaBean对象 |
jsp:element | 动态创建一个XML元素 |
jsp:attribute | 定义动态创建的XML元素的属性 |
jsp:body | 定义动态创建的XML元素的主体 |
jsp:text | 用于封装模板数据 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%-- @include 会将 两个页面合二为一--%>
<%-- 网页的头--%>
<%@include file="common/header.jsp"%>
网页主体
<%-- 网页的尾--%>
<%@include file="common/footer.jsp"%>
<%--jsp标签
jsp:include : 拼接页面,本质还是3个页面
--%>
<%-- 网页的头--%>
网页主体
<%-- 网页的尾--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
i am header
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
i am footer
文件结构:
运行结果:
对象 | 描述 |
---|---|
request | HttpServletRequest类的实例 |
response | HttpServletResponse类的实例 |
out | PrintWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
exception | exception 类的对象,代表发生错误的 JSP 页面中对应的异常对象 |
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%-- 内置对象--%>
<%
// 保存的数据中只在一个页面中有效
pageContext.setAttribute("name1","阿迪1");
// 保存的数据只在一次请求中有效,请求转发会携带这个数据
request.setAttribute("name2","阿迪2");
// 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器,
session.setAttribute("name3","阿迪3");
// 保存的数据在服务器中有效,从打开服务器到关闭服务器
application.setAttribute("name4","阿迪4");
%>
<%--
脚本片段中的代码,会被原封不动的生成到 xxx_jsp.java中
要求:这里的代码必须要跟Java的语法一致
--%>
<%
//从 pageContext取出,我们通过寻找的方式来找出其中的数据
// 从底层到高层(作用域):page -> request -> session -> application
// 双亲委派机制:
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表达式 ` ${ 变量或者表达式} ` 等价于 ` <%= 变量或者表达式 %> `
--%>
页面一,存数据的页面
EL 表达式取出的值:
${name1}
${name2}
${name3}
${name4}
${name5}
<%= name5%>
<%
// 对setAttribut方法进行扩展,四个作用域
pageContext.setAttribute("age1","1",PageContext.PAGE_SCOPE);
// 等价于 pageContext.setAttribute("age1","1");
pageContext.setAttribute("age2","2",PageContext.REQUEST_SCOPE);
// 等价于 request.setAttribute("age2","2");
pageContext.setAttribute("age3","3",PageContext.SESSION_SCOPE);
// 等价于 session.setAttribute("age3","3");
pageContext.setAttribute("age4","4",PageContext.APPLICATION_SCOPE);
// 等价于 application.setAttribute("age4","4");
%>
request: 客户端向服务器发送请求,产生数据,用户看完就没用了,比如新闻,用户看完就没用的;
session: 客户端向服务端发送请求,产生的数据,用户用完以后还要用,比如购物车
application: 客户端向服务端发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如聊天数据;
一般这些作用域可以跟页面跳转方法配合使用pageContext.forward(s);
s就是你要跳转的页面,在跳转之前可以往这些容器中存数据,然后再别的页面取出数据。
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.0modelVersion>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstl-apiartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
dependencies>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.7maven.compiler.source>
<maven.compiler.target>1.7maven.compiler.target>
properties>
project>
${ }
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
JspTag1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
jspTag2.jsp
名字:<%= (String) request.getParameter("name")%>
年龄:<%= (String) request.getParameter("age")%>
<%
User user = (User) request.getSession().getAttribute("userSession");
%>
<%= user.getUserName()%>
${userSession.userName}
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和java代码一样
核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
标签 | 描述 |
---|---|
|
用于在JSP中显示数据,就像<%= … > |
|
用于保存数据 |
|
用于删除数据 |
|
用来处理产生错误的异常状况,并且将错误信息储存起来 |
|
与我们在一般程序中用的if一样 |
|
本身只当做 和 的父标签 |
|
的子标签,用来判断条件是否成立 |
|
的子标签,接在 标签后,当 标签判断为false 时被执行 |
|
检索一个绝对或相对 URL,然后将其内容暴露给页面 |
|
基础迭代标签,接受多种集合类型 |
|
根据指定的分隔符来分隔内容并迭代输出 |
|
用来给包含或重定向的页面传递参数 |
|
重定向至一个新的URL. |
|
使用可选的查询参数来创造一个URL |
如需详细了解请移步菜鸟教程
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。引用SQL标签库的语法如下:
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
JSTL XML标签库提供了创建和操作XML文档的标签。引用XML标签库的语法如下:
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
taglib
<%-- jstl 标签 的使用 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Title
if 测试
<%--判断如果用户名是管理员,则登录成功--%>
<%-- 登录java代码实现
<%
if (request.getParameter("username").equals("admin")){
out.print("登录成功");
}
%>
--%>
<%--判断如果提交的用户是管理员,则登录成功--%>
<%--
jstl 标签 、、的使用
其中 、 配合使用与switch有些类似
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%-- 定义一个变量叫 socre ,设置值为 85--%>
你的成绩优秀
你的成绩良好
你的成绩一般
你的成绩不及格
<%-- jstl 标签 的使用 --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: asd
Date: 2021/7/3
Time: 21:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%
// 定义集合,将数据存入集合
ArrayList people = new ArrayList();
people.add("张三");
people.add("李四");
people.add("王五");
people.add("赵六");
people.add("前七");
request.setAttribute("list",people);
%>
<%--
var = "people" 定义一个变量, people
items = "${list}}" 要遍历的对象 list
等价于java代码:
for (String people:list) {
out.print(people);
}
--%>
名字:
<%--
var="people" 定义一个变量,people
items="${list}" ,要遍历的对象,list
begin="1" , 开始遍历的位置
end="3" , 结束遍历的位置
step="2" , 步长
等价于java代码:
ArrayList people = new ArrayList();
people.add("张三");
people.add("李四");
people.add("王五");
people.add("赵六");
people.add("前七");
request.setAttribute("list",people);
people = (ArrayList) request.getAttribute("list");
for (int i = 1; i <= 3; i+=2) {
String temp = people.get(i);
out.println(temp);
}
--%>
名字:
实体类
JAVABean有特定的写法:
一般用来和数据库的字段做映射:ORM
ORM:对象关系映射
id | name | age | address |
---|---|---|---|
1 | 阿笛 | 10 | asd |
2 | 阿笛1 | 11 | asd |
3 | 阿笛2 | 20 | asd |
javabean的用法
<%
// People people = new People();
%>
<%
// people.setId(1);
// people.setName("阿笛");
// people.setAge(10);
// people.setAddress("asd");
%>
<%
// out.print("id:"+people.getId());
// out.print("name:"+people.getName());
// out.print("age:"+people.getAge());
// out.print("address:"+people.getAddress());
%>
id:
name:
age:
address:
什么是MVC: Model、View、Controller 模型、视图、控制器
用户直接访问控制层,控制层就可以直接操作数据库
servlet --- curd--->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理jdbc、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的,否则就加多层
Model:
View:
Controller (Servlet)
登录-->接收用户的登录请求-->处理用户的请求(获取用户登录的参数,username,password)-->交给业务层处理登录业务(判断用户名密码是否正确:数据库事务)-->Dao层查询数据库中的用户名和密码是否正确-->数据库
Filter:过滤器,用来过滤网站的数据;或者是通过不同的vip等级进入不同的页面
Filter开发步骤:
class 类名 implements javax.servlet.Filter
并重写方法servlet:
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("你好");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
字符编码过滤器
将字符编码转化成utf-8
public class CharacterEncodingFilter implements Filter {
// 初始化:在服务器启动时调用此方法
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter 初始化");
}
// Chain:链,可以有很多个过滤器
/*
* 1,过滤器中的所以代码,在过滤特定请求的时候都会执行
* 2,必须要让过滤器继续通行: filterChain.doFilter(servletRequest,servletResponse);
* */
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("过滤前");
// 让我们的请求继续通行,如果不写,程序就在这里就被拦截了
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("过滤后");
}
// 销毁:在服务器停止的时候调用此方法
public void destroy() {
System.out.println("CharacterEncodingFilter 销毁");
}
}
3.在web.xml配置Filter
ShowServlet
com.nguyen.servlet.ShowServlet
ShowServlet
/servlet/show
ShowServlet
/show
CharacterEncodingFilter
com.nguyen.filter.CharacterEncodingFilter
CharacterEncodingFilter
/servlet/*
实现一个监听器的接口,统计当前在线人数
// 统计网站在线人数,统计session
public class OnlineCountListener implements HttpSessionListener {
// 创建session监听:
// 一旦创建一个Session就会触发一次该方法
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer)servletContext.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
// 获取当前在线人数,一旦有新的用户上线就对在线人数+1
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
// 销毁session监听
// 一旦销毁Session就会触发一次此方法
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer)servletContext.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$Title$
当前有 <%= request.getServletContext().getAttribute("OnlineCount")%> 人在线
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>com.nguyen.listener.OnlineCountListenerlistener-class>
listener>
web-app>
监听器在GUI编程中经常使用
此功能使用到第11节的字符编码过滤器
定义session常量,存放用户信息
package com.nguyen.util;
public class Constant {
public final static String USER_SESSION = "USER_SESSION";
}
错误页面:输入地址错误,或者登录失败都会进入此页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
错误
没有权限或者密码错误
登录界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登录成功后才能进入该页面
<%@ page import="com.nguyen.util.Constant" %><%--
Created by IntelliJ IDEA.
User: nguyen
Date: 2021/7/18
Time: 12:44
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
<%
// 检查是否存在user_session,如果没有登录,则不允许进入该页面,并且自动跳转到登录界面
Object o = request.getSession().getAttribute(Constant.USER_SESSION);
if (o==null){
response.sendRedirect("/login.jsp");
}
%>
主页
服务器响应登录请求
package com.nguyen.servlet;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println(username);
if ("admin".equals(username)){//登录成功
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
// 重定向
resp.sendRedirect("/sys/success.jsp");
}else {// 登录失败
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
服务器响应注销请求
package com.nguyen.servlet;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object o = req.getSession().getAttribute(Constant.USER_SESSION);
//客户端发起注销请求时,从session中删除User_session
if(o!=null){
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect("/login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
当且仅当用户通过登录界面,并且输入正确的账号信息时才能正常登录到主页面,否则会自动跳转到登录界面
注销后,无法进入主页
由于jsp在理论上只需要实现展示页面的功能,所以不应该在jsp文件中添加主页访问权限(即只有登录了才能进入主页的权限),所以应该新增一层过滤器,以解决这一方面的问题
在无过滤器代码文件的基础上,仅更改success.jsp
文件,并新增一个过滤器
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
主页
过滤器:用于处理主页访问权限问题
package com.nguyen.filter;
import com.nguyen.util.Constant;
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 获取session
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 获取user_session,如果登录了,则可以访问主页,否则跳转到错误页面
Object o = request.getSession().getAttribute(Constant.USER_SESSION);
if(o==null){
response.sendRedirect("/error.jsp");
}
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
}
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>LoginServletservlet-name>
<servlet-class>com.nguyen.servlet.LoginServletservlet-class>
servlet>
<servlet>
<servlet-name>LogoutServletservlet-name>
<servlet-class>com.nguyen.servlet.LogoutServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>ShowServletservlet-name>
<url-pattern>/servlet/showurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServletservlet-name>
<url-pattern>/servlet/loginurl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>LogoutServletservlet-name>
<url-pattern>/servlet/logouturl-pattern>
servlet-mapping>
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>com.nguyen.filter.CharacterEncodingFilterfilter-class>
filter>
<filter>
<filter-name>SysFilterfilter-name>
<filter-class>com.nguyen.filter.SysFilterfilter-class>
filter>
<filter-mapping>
<filter-name>SysFilterfilter-name>
<url-pattern>/sys/*url-pattern>
filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/servlet/*url-pattern>
filter-mapping>
web-app>
正常登录时,可以进入主页,当直接通过地址进入主页时,会对该请求进行过滤,自动跳转到错误页面,以下图片为未登录的请求的请求。
需要jar包的支持:
查询users表中的数据
package com.nguyen.text;
import java.sql.*;
public class test {
public static void main(String[] args) {
// 解决字符编码问题
String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=true&useUnicode=true&" +
"characterEncoding=utf-8";
String user = "root";
String password = "root";
try {
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库
Connection conn = DriverManager.getConnection(url,user,password);
// 3.向数据库发生SQL的对象,PrepareStatement :CURD
String sql = "select * from users";
PreparedStatement statement = conn.prepareStatement(sql);
// 5.执行查询语句
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String password1 = resultSet.getString("password");
String email = resultSet.getString("email");
Date birthday = resultSet.getDate("birthday");
System.out.println("id="+id);
System.out.println("name="+name);
System.out.println("password="+password1);
System.out.println("email="+email);
System.out.println("birthday="+birthday);
}
resultSet.close();
statement.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
基本概念:事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
简单来说,就是事务提交的时候要么成功,要么失败。
ACID原则就是保证数据安全
开始事务
事务提交 commit()
事务回滚 rollback()
关闭事务
依赖
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
package com.nguyen.text;
import org.junit.jupiter.api.Test;
public class TestJDBC {
@Test
public void hello(){
System.out.println("hello");
}
}
直接运行hello()
方法得到如下结果:
转账操作,无异常则可以更新数据库状态,有异常会自动回滚事务
package com.nguyen.text;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
@Test
public void hello(){
String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=true&useUnicode=true&" +
"characterEncoding=utf-8";
String user = "root";
String password = "root";
String Driver = "com.mysql.jdbc.Driver";
Connection conn = null;
try {
Class.forName(Driver);
conn = DriverManager.getConnection(url, user, password);
// 关闭自动提交事务
conn.setAutoCommit(false);
String sql = "UPDATE account set money = money - 100 WHERE name = 'A'";
conn.prepareStatement(sql).executeUpdate();
String sql1 = "UPDATE account set money = money + 100 WHERE name = 'B'";
conn.prepareStatement(sql1).executeUpdate();
// 制造异常
int i =1/0;
// 提交事务
conn.commit();
System.out.println("提交成功");
} catch (Exception e) {
// 如果出现异常则回滚事务
try {
assert conn != null;
conn.rollback();
System.out.println("提交失败");
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
conn.close();
} catch (SQLException e2) {
e2.printStackTrace();
}
e.printStackTrace();
}
}
}
由于该代码中存在异常(0不能是分母),所以该更新操作会自动回滚,数据库的状态不会发生变化。
conn = DriverManager.getConnection(url,user,password);
// 3.向数据库发生SQL的对象,PrepareStatement :CURD
String sql = “select * from users”;
PreparedStatement statement = conn.prepareStatement(sql);
// 5.执行查询语句
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()){
int id = resultSet.getInt(“id”);
String name = resultSet.getString(“name”);
String password1 = resultSet.getString(“password”);
String email = resultSet.getString(“email”);
Date birthday = resultSet.getDate(“birthday”);
System.out.println(“id=”+id);
System.out.println(“name=”+name);
System.out.println(“password=”+password1);
System.out.println(“email=”+email);
System.out.println(“birthday=”+birthday);
}
resultSet.close();
statement.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
#### 事务
- 基本概念:事务是恢复和[并发控制](https://baike.baidu.com/item/并发控制)的基本单位。
- 事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为**ACID特性**。
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
简单来说,就是事务提交的时候要么成功,要么失败。
ACID原则就是保证数据安全
```java
开始事务
事务提交 commit()
事务回滚 rollback()
关闭事务
依赖
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
package com.nguyen.text;
import org.junit.jupiter.api.Test;
public class TestJDBC {
@Test
public void hello(){
System.out.println("hello");
}
}
转账操作,无异常则可以更新数据库状态,有异常会自动回滚事务
package com.nguyen.text;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
@Test
public void hello(){
String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=true&useUnicode=true&" +
"characterEncoding=utf-8";
String user = "root";
String password = "root";
String Driver = "com.mysql.jdbc.Driver";
Connection conn = null;
try {
Class.forName(Driver);
conn = DriverManager.getConnection(url, user, password);
// 关闭自动提交事务
conn.setAutoCommit(false);
String sql = "UPDATE account set money = money - 100 WHERE name = 'A'";
conn.prepareStatement(sql).executeUpdate();
String sql1 = "UPDATE account set money = money + 100 WHERE name = 'B'";
conn.prepareStatement(sql1).executeUpdate();
// 制造异常
int i =1/0;
// 提交事务
conn.commit();
System.out.println("提交成功");
} catch (Exception e) {
// 如果出现异常则回滚事务
try {
assert conn != null;
conn.rollback();
System.out.println("提交失败");
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
conn.close();
} catch (SQLException e2) {
e2.printStackTrace();
}
e.printStackTrace();
}
}
}
由于该代码中存在异常(0不能是分母),所以该更新操作会自动回滚,数据库的状态不会发生变化。