JavaWeb入门
JavaWeb入门1 概述1.1 web应用程序1.2 静态web1.3 动态web2 web服务器2.1 概述2.2 web服务器3 Tomcat3.1 Tomcat安装3.2 配置3.3 发布网站3.4 IDEA配置Tomcat4 HTTP4.1 概述4.2 HTTP工作时序5 Maven5.1 概述5.2 Maven项目架构管理工具5.3 安装Maven5.4 配置5.5 本地仓库5.6 IDEA使用Maven5.7 pom.xml配置5.8 web.xml配置5.9 Maven仓库使用6 Servlet6.1 概述6.2 HelloServlet程序6.3 Servlet的运行原理6.4 ServletContext对象6.5 HttpServletResponse类6.6 HttpServletRequest类7 Cookie、Session7.1 会话7.2 保存会话技术7.3 Cookie7.4 Session8 JSP8.1 简介8.2 JSP原理8.3 JSP基本语法8.4 JSP指令8.5 9大内置对象8.6 JSP、JSTL标签 EL表达式9 MVC三层架构
JavaWeb入门
1 概述
web开发:
web,网页
静态web
- HTML,CSS
动态web
- 每个人不同时间看到信息都不同
- Servlet/JSP、ASP、PHP
Java中,动态web资源开发技术统称为JavaWeb
1.1 web应用程序
可以提供浏览器的程序:
- a.html,b.html...这些多个web资源可以被外界访问,对外界提供服务
- 访问的资源都存在某一个计算机
- 统一的web资源通过Tomcat服务器给用户访问
1.2 静态web
服务器上存放HTML文件,通过网络读取文件
静态web:
- Web无法更新,所有用户都是同一个页面
- 数据无法持久化,用户无法交互
1.3 动态web
web页面展示效果
- 可以动态更新,可以与数据库交互
- 需要后台程序支持,停机维护
2 web服务器
2.1 概述
ASP:微软
- 在HTML中嵌入VB的脚本
- 维护成本高
PHP
- 开发效率高,功能强,代码简单
- 无法承载大访问量
JSP/Servlet
- B/S:浏览器与服务器模型
- 基于Java语言
- 可以承载高并发,高可用,高性能
2.2 web服务器
服务器用来处理用户的请求,处理请求,给用户响应
IIS:微软,windows自带
Tomcat:
- 技术先进,性能稳定,免费
3 Tomcat
3.1 Tomcat安装
启动/关闭Tomcat
打开bin目录下startup.bat文件
用浏览器访问localhost:8080
关闭bin目录下shutdown.bat文件
闪退问题:Tomcat需要Java环境,会读取JAVA_HOME或者JRE_HOME没有配置环境变量则会错误
Java环境变量配置:如果需要调整Java目录,如果Path变量存在一个C盘下的java path需要先删除这个地址
3.2 配置
打开conf/server.xml
默认端口配置,协议,超时:
1<Connector port="8080" protocol="HTTP/1.1"
2 connectionTimeout="20000"
3 redirectPort="8443" />
默认主机:
xxxxxxxxxx
21<Host name="localhost" appBase="webapps"
2 unpackWARs="true" autoDeploy="true">
DNS解析简介:
- 1.输入域名
- 2.检查主机Host
- 3.没有则请求DNS服务器,返回IP地址
配置环境变量
3.3 发布网站
将自己写的网站放到服务器(Tomcat)中指定的文件夹下(webapps):
webapps
ROOT
TestStaticWeb:网页目录名
WEB-INF
- classes:java程序
- lib:web应用依赖的Jar包
- web.xml:网站的配置文件
index.html 默认首页
static
- css
- js
- img
......
通过8080端口访问自己发布的网站:
3.4 IDEA配置Tomcat
1.右上角AddConfiguration打开,选择Tomcat
2.配置Tomcat
需要手动配置文件夹
3.启动Tomcat,点击右上角运行
4 HTTP
4.1 概述
HTTP超文本传输协议
- 文本:HTML,JSON...
- 超文本:图片、音乐、视频、定位...
HTTP的版本
HTTP1.0
- HTTP/1.0:客户端与web服务器连接后,只能获得一个web资源
- 每一次请求和应答都会发一次TCP连接的建立和断开
HTTP2.0
- HTTP/1.1:客户端与web服务器连接后,可以获得多个web资源
- 允许在一次TCP连接上发送多次请求和应答
4.2 HTTP工作时序
先建立TCP连接,在TCP连接上进行请求和应答:
访问自己发布的网站,启动抓包
HTTP通信的时序:
HTTP请求
1.请求行
请求方法:GET方法
- GET:请求能携带的参数较少,大小有限制,在URL显示数据,不安全
- POST:请求能携带的参数没有限制,大小没有限制,安全,但不高效
2.消息头
URI:/TestStaticWeb/
- 统一资源标志符 资源位置(这里不带协议和主机)
Version:HTTP/1.1
Host:localhost:8080
- 主机
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
- 支持的数据类型
Accept-Encoding:gzip, deflate
- 支持的编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
- 语言环境
Cache-Control max-age=0
- 缓存控制
Cookie
Connection:keep-alive
- 请求完成是断开还是保持连接(TCP)
HTTP响应
这里进行了重定向304状态码,使用了缓存数据
使用浏览器的网格分析功能抓包:
获取完HTML之后加载图片还会发送HTTP请求到指定URL请求图片
响应头
响应状态码:
1 信息提供
2 肯定应答
- 200 OK
- 204 处理完成请求不返回信息
3 重定向请求
- 304 网页未修改(服务器返回此状态不返回内容,使用缓存内容,节省流量)
4 客户端请求内容出现错误
- 403 服务器拒绝请求
- 404 请求内容不存在
- 408 请求超时
5 服务器错误
- 502 网关错误,上游服务器无效响应
- 504 网关超时,没有收到上游服务器的响应
5 Maven
5.1 概述
在Javaweb开发中,需要用到大量的Jar包,需要手动导入,麻烦
如何自带导入Jar包
- Maven
5.2 Maven项目架构管理工具
目前用来导入Jar包
Maven的核心思想:约定大于配置
Maven会规定好如何去编写Java代码
5.3 安装Maven
5.4 配置
配置环境变量
- M2_HOME maven下的bin目录
- MAVEN_HOME maven目录
- path %MAVEN_HOME%\bin
打开文件conf/settings.xml
xxxxxxxxxx
81<!--配置为国内镜像,方便下载-->
2<mirror>
3 <id>maven-default-http-blocker</id>
4 <mirrorOf>external:http:*</mirrorOf>
5 <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
6 <url>http://0.0.0.0/</url>
7 <blocked>true</blocked>
8</mirror>
改为:
xxxxxxxxxx
61<mirror>
2 <id>alimaven</id>
3 <name>aliyun maven</name>
4 <url>https://maven.aliyun.com/nexus/content/groups/public/</url>
5 <mirrorOf>central</mirrorOf>
6</mirror>
5.5 本地仓库
建立仓库:
xxxxxxxxxx
11<localRepository>E:\environment\Maven\apache-maven-3.8.4\maven-repo</localRepository>
5.6 IDEA使用Maven
使用模板创建Maven项目
1.创建MavenWeb项目
2.等待导入Jar包
3.BUILD SUCCESS 搭建成功
自动导入的Jar包:
4.IDEA中的Maven配置
项目创建之后查看是否配置正确,IDEA可能改变目录
手动创建Maven项目
不使用模板:
这里空模板不能设置Maven,果然IDEA使用了默认的Maven仓库,去设置里面改为自己配置的maven
创建好的文件:
刚刚创建的JavaWeb模板项目:
使用Web项目,在main文件夹下创建java文件夹和resources文件夹
标记文件夹为源码目录,资源目录:
查看Jar包的目录树:
5.7 pom.xml配置
Maven:
pom.xml是Maven的核心配置文件
x1
2
3<!--Maven版本和头文件-->
4<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6 <modelVersion>4.0.0</modelVersion>
7
8 <!--创建项目配置的GAV-->
9 <groupId>com.zou</groupId>
10 <artifactId>JavaWeb-Maven-Test</artifactId>
11 <version>1.0-SNAPSHOT</version>
12 <!--项目的打包方式
13 jar:java应用
14 war:javaWeb应用
15 -->
16 <packaging>war</packaging>
17
18 <name>JavaWeb-Maven-Test Maven Webapp</name>
19 <!-- FIXME change it to the project's website -->
20 <url>http://www.example.com</url>
21
22 <!--配置-->
23 <properties>
24 <!--项目默认构建编码-->
25 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26 <!--编译版本-->
27 <maven.compiler.source>1.7</maven.compiler.source>
28 <maven.compiler.target>1.7</maven.compiler.target>
29 </properties>
30
31 <!--项目依赖-->
32 <dependencies>
33 <dependency>
34 <groupId>junit</groupId>
35 <artifactId>junit</artifactId>
36 <version>4.11</version>
37 <scope>test</scope>
38 </dependency>
39 </dependencies>
40
41 <!--项目构建-->
42 <build>
43 <finalName>JavaWeb-Maven-Test</finalName>
44 <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
45 <plugins>
46 <plugin>
47 <artifactId>maven-clean-plugin</artifactId>
48 <version>3.1.0</version>
49 </plugin>
50 <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
51 <plugin>
52 <artifactId>maven-resources-plugin</artifactId>
53 <version>3.0.2</version>
54 </plugin>
55 <plugin>
56 <artifactId>maven-compiler-plugin</artifactId>
57 <version>3.8.0</version>
58 </plugin>
59 <plugin>
60 <artifactId>maven-surefire-plugin</artifactId>
61 <version>2.22.1</version>
62 </plugin>
63 <plugin>
64 <artifactId>maven-war-plugin</artifactId>
65 <version>3.2.2</version>
66 </plugin>
67 <plugin>
68 <artifactId>maven-install-plugin</artifactId>
69 <version>2.5.2</version>
70 </plugin>
71 <plugin>
72 <artifactId>maven-deploy-plugin</artifactId>
73 <version>2.8.2</version>
74 </plugin>
75 </plugins>
76 </pluginManagement>
77 </build>
78</project>
资源导出失败问题:Java文件夹可以包含配置文件,防止导出失败
xxxxxxxxxx
201<build>
2 <resources>
3 <resource>
4 <directory>src/main/resources</directory>
5 <excludes>
6 <exclude>**/*.properties</exclude>
7 <exclude>**/*.xml</exclude>
8 </excludes>
9 <filtering>false</filtering>
10 </resource>
11 <resource>
12 <directory>src/main/java</directory>
13 <includes>
14 <include>**/*.properties</include>
15 <include>**/*.xml</include>
16 </includes>
17 <filtering>false</filtering>
18 </resource>
19 </resources>
20</build>
5.8 web.xml配置
Tomcat的配置文件,通过IDEA模板生成的配置比较老,直接复制Tomcat自带案例的配置
xxxxxxxxxx
81
2<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
5 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
6 version="4.0"
7 metadata-complete="true">
8</web-app>
5.9 Maven仓库使用
寻找HttpServlet的Jar包,Alt+Enter可以通过IDEA寻找Maven依赖,IDEA生成的依赖版本号很老而且有问题
找到Maven仓库,地址
搜索Servlet:
复制Maven依赖
6 Servlet
6.1 概述
Servlet是sun公司开发动态Web的技术
Sun在这些API中提供一个接口叫:Servlet
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
实现了Servlet接口的Java程序叫做Servlet
6.2 HelloServlet程序
1.新建普通Maven项目删除原来的src目录
2.新建子模块,父项目中pom.xml会多一个module
xxxxxxxxxx
31<modules>
2 <module>Servlet-Hello</module>
3</modules>
子项目:
xxxxxxxxxx
51<parent>
2 <artifactId>JavaWeb-Maven-study</artifactId>
3 <groupId>com.zou</groupId>
4 <version>1.0-SNAPSHOT</version>
5</parent>
子项目如果没有生成parent标签,手动写入,否则无法继承父项目的依赖
3.将web.xml换成Tomcat最新的
4.添加Java和Resources文件夹
5.编写程序
(1)源码分析:
- Servlet接口有两个默认实现类,HttpServlet,GenericServlet
- 这两个类的继承关系:
xxxxxxxxxx
21public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
2public abstract class HttpServlet extends GenericServlet
servlet的方法
xxxxxxxxxx
51void init(ServletConfig var1) throws ServletException;
2ServletConfig getServletConfig();
3void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
4String getServletInfo();
5void destroy();
service在HttpServlet中实现了,service根据GET,POST...方法来调用doGet,doPost方法
xxxxxxxxxx
371protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
2 String method = req.getMethod();
3 long lastModified;
4 if (method.equals("GET")) {
5 lastModified = this.getLastModified(req);
6 if (lastModified == -1L) {
7 this.doGet(req, resp);
8 } else {
9 long ifModifiedSince = req.getDateHeader("If-Modified-Since");
10 if (ifModifiedSince < lastModified) {
11 this.maybeSetLastModified(resp, lastModified);
12 this.doGet(req, resp);
13 } else {
14 resp.setStatus(304);
15 }
16 }
17 } else if (method.equals("HEAD")) {
18 lastModified = this.getLastModified(req);
19 this.maybeSetLastModified(resp, lastModified);
20 this.doHead(req, resp);
21 } else if (method.equals("POST")) {
22 this.doPost(req, resp);
23 } else if (method.equals("PUT")) {
24 this.doPut(req, resp);
25 } else if (method.equals("DELETE")) {
26 this.doDelete(req, resp);
27 } else if (method.equals("OPTIONS")) {
28 this.doOptions(req, resp);
29 } else if (method.equals("TRACE")) {
30 this.doTrace(req, resp);
31 } else {
32 String errMsg = lStrings.getString("http.method_not_implemented");
33 Object[] errArgs = new Object[]{method};
34 errMsg = MessageFormat.format(errMsg, errArgs);
35 resp.sendError(501, errMsg);
36 }
37}
而HttpServlet类中的这些方法只是返回错误码,所以需要我们重写这些方法
xxxxxxxxxx
91protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
2 String protocol = req.getProtocol();
3 String msg = lStrings.getString("http.method_get_not_supported");
4 if (protocol.endsWith("1.1")) {
5 resp.sendError(405, msg);
6 } else {
7 resp.sendError(400, msg);
8 }
9}
(2)编写Servlet类
xxxxxxxxxx
191public class HelloServlet extends HttpServlet {
2 /*get或者Post是请求实现的不同方式 RestFul风格*/
3
4 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
5 System.out.println("Request,Method: GET");
6
7 resp.setStatus(200);
8 resp.setContentType("text/html");
9
10 PrintWriter writer = resp.getWriter();//响应流
11 String HtmlStr = "<html>\n<head></head>\n<body><h1>Hello,Servlet</h1></body>\n</html>";
12 writer.println(HtmlStr);
13 }
14
15
16 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
17 this.doGet(req,resp);
18 }
19}
(3)编写Servlet映射
在Web服务中注册Servlet服务,类似路由表的编写(需要URL)
xxxxxxxxxx
101<!--注册Servlet-->
2<servlet>
3 <servlet-name>hello</servlet-name>
4 <servlet-class>com.helloServlet.HelloServlet</servlet-class>
5</servlet>
6<!--URI:Servlet的请求-->
7<servlet-mapping>
8 <servlet-name>hello</servlet-name>
9 <url-pattern>/hello</url-pattern>
10</servlet-mapping>
(4)启动Tomcat,运行程序
响应头:
ISO-8859-1是Java的默认编码,这里输出中文需要设置编码为UTF-8
补充
<url-pattern > 可以使用统配标识符*来表示任意字符,由于固有路径的优先级高,可以通过这种方式做一个404的页面(没有servlet映射就会进这个页面)
xxxxxxxxxx
81<servlet>
2 <servlet-name>error</servlet-name>
3 <servlet-class>com.helloServlet.ErrorServlet</servlet-class>
4</servlet>
5<servlet-mapping>
6 <servlet-name>error</servlet-name>
7 <url-pattern>/*</url-pattern>
8</servlet-mapping>
xxxxxxxxxx
171public class ErrorServlet extends HttpServlet {
2
3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4
5 resp.setContentType("text/html");
6 resp.setCharacterEncoding("utf-8");
7
8 PrintWriter writer = resp.getWriter();
9 String HtmlStr = "<html>\n<head></head>\n<body><h1>404ERROR \n 页面未找到</h1></body>\n</html>";
10 writer.println(HtmlStr);
11 }
12
13
14 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
15 this.doGet(req,resp);
16 }
17}
6.3 Servlet的运行原理
Tomcat是一个web容器,也叫web服务器,Tomcat只是实现了JSP 和 servlet 开发标准,编译好的servlet类只能运行在tomcat容器中,客户端浏览器不可以直接访问Servlet,需要在web.xml中配置
Servlet,它被设计为多线程的,当一个用户进行访问,就会创建一条线程运行此用户请求的响应,保证了在多用户访问网页的时候不会出现等待访问的情况。而且Servlet机制是有线程池支持的,在初始化阶段,线程就被创建好了
servlet在Tomcat中是以单例模式存在的,在使用实例变量时,会产生线程安全问题,当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类,此时它贮存于内存中。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类(单例模式),也就是有多个线程在使用这个实例。 这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致,所以尽量使用同步来保护被访问的资源
Servlet生命周期
(1)加载和实例化
- 当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Servlet实例。实力化会使Servlet类被类加载器加载,容器通过反射方式创建Servlet实例,默认调用无参构造,所以在编写Servlet类时不应该提供有参构造
(2)初始化
- 在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象。每一个Servlet实例init()方法只被调用一次,在初始化期间可以完成读取配置,建立数据库连接等操作。
- 如果初始化发生错误,Servlet实例可以抛出ServletException异常或者UnavailableException异常来通知容器,ServletException异常用于指明一般的初始化失败,例如没有找到初始化参数;而UnavailableException异常用于通知容器该Servlet实例暂时或永久不可用。
(3)请求处理
- Servlet容器调用Servlet的service()方法对请求进行处理。要注意的是,在service()方法调用之前,init()方法必须成功执行。调用service()方法后判断请求的方法调用doGet(),doPost()等方法处理请求,通过HttpServletRequest读取请求信息,HttpServletResponse返回处理请求结果。
- 如果发生错误,Servlet实例可以抛出ServletException异常或者UnavailableException异常。如果UnavailableException异常指示了该实例永久不可用,Servlet容器将调用实例的destroy()方法,释放该实例。此后对该实例的任何请求,都将收到容器发送的HTTP 404响应。如果指示了该实例暂时不可用,那么在暂时不可用的时间段内,对该实例的任何请求,都将收到容器发送的HTTP 503(服务器暂时忙,不能处理请求)响应。
(4)服务终止
- 当测到一个Servlet实例应该从服务中被移除的时候,容器就会调用实例的destroy()方法,以便让该实例可以释放它所使用的资源,该实例随后会被Java的垃圾收集器所回收。如果再次需要这个Servlet处理请求,Servlet容器会创建一个新的Servlet实例。
6.4 ServletContext对象
web容器启动的时候,会为每个web程序创建对应的ServletContext对象,代表当前web应用
共享数据:在多个Servlet对象共享数据
程序编写:
创建一个Servlet获取Get参数,将参数写入到ServletContext:
xxxxxxxxxx
241public class HelloServlet extends HttpServlet {
2
3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4 System.out.println("method: Get");
5
6 String username = req.getParameter("username");
7 System.out.println(username);
8
9 resp.setCharacterEncoding("utf-8");
10 resp.setContentType("text/html");
11 ServletContext servletContext = this.getServletContext();
12 servletContext.setAttribute("username",username);//将数据保存在ServletContext中
13
14 PrintWriter writer = resp.getWriter();
15 String HtmlStr = "<html>\n<head></head>\n<body><a href=\"http://localhost:8080/S2/getName\">获取用户名</a></body>\n</html>";
16 writer.println("hello");
17 writer.println(HtmlStr);
18 }
19
20
21 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
22 this.doGet(req, resp);
23 }
24}
到ServletContext读取数据并显示:
xxxxxxxxxx
241public class HelloServlet extends HttpServlet {
2
3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4 System.out.println("method: Get");
5
6 String username = req.getParameter("username");
7 System.out.println(username);
8
9 resp.setCharacterEncoding("utf-8");
10 resp.setContentType("text/html");
11 ServletContext servletContext = this.getServletContext();
12 servletContext.setAttribute("username",username);//将数据保存在ServletContext中
13
14 PrintWriter writer = resp.getWriter();
15 String HtmlStr = "<html>\n<head></head>\n<body><a href=\"http://localhost:8080/S2/getName\">获取用户名</a></body>\n</html>";
16 writer.println("hello");
17 writer.println(HtmlStr);
18 }
19
20
21 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
22 this.doGet(req, resp);
23 }
24}
web.xml
xxxxxxxxxx
161<servlet>
2 <servlet-name>hello</servlet-name>
3 <servlet-class>com.context.HelloServlet</servlet-class>
4</servlet>
5<servlet-mapping>
6 <servlet-name>hello</servlet-name>
7 <url-pattern>/hello</url-pattern>
8</servlet-mapping>
9<servlet>
10 <servlet-name>getName</servlet-name>
11 <servlet-class>com.context.GetUsername</servlet-class>
12</servlet>
13<servlet-mapping>
14 <servlet-name>getName</servlet-name>
15 <url-pattern>/getName</url-pattern>
16</servlet-mapping>
运行结果:
跳转页面:
获取初始化参数
web.xml:
xxxxxxxxxx
41<context-param>
2 <param-name>JdbcUrl</param-name>
3 <param-value>jdbc:mysql://localhost:3306</param-value>
4</context-param>
java:
xxxxxxxxxx
51ServletContext servletContext = this.getServletContext();
2String jdbcUrl = servletContext.getInitParameter("JdbcUrl");
3
4PrintWriter writer = resp.getWriter();
5writer.println(jdbcUrl);
结果:
请求转发
java:
xxxxxxxxxx
71ServletContext servletContext = this.getServletContext();
2//转发
3RequestDispatcher request = servletContext.getRequestDispatcher("/getParam");//转发路径
4request.forward(req,resp);
5
6PrintWriter writer = resp.getWriter();
7writer.println("Dispatcher");
结果:
读取资源
properties:
xxxxxxxxxx
31username=root
2password=123456
3url=jdbc:mysql://localhost:3306
maven打包之后的路径:
通过getResourceAsStream获取资源:
xxxxxxxxxx
121ServletContext servletContext = this.getServletContext();
2InputStream stream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
3Properties properties = new Properties();
4properties.load(stream);
5String username = properties.getProperty("username");
6String password = properties.getProperty("password");
7String url = properties.getProperty("url");
8
9PrintWriter writer = resp.getWriter();
10writer.println("username: "+username);
11writer.println("password: "+password);
12writer.println("url: "+url);
结果:
6.5 HttpServletResponse类
应用
- 下载文件
xxxxxxxxxx
321public class ServletFile extends HttpServlet {
2
3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4 //1.获取文件下载路径
5 String realPath = "E:\\java program\\JavaWeb\\JavaWeb-Maven-study\\Response\\target\\classes\\1.jpg";
6 System.out.println("下载路径:"+realPath);
7 //2.下载文件的文件名
8 String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
9 System.out.println("下载文件:"+fileName);
10 //3.设置浏览器支持
11 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
12 //4.获取文件的输入流
13 FileInputStream inputStream = new FileInputStream(realPath);
14 //5.创建缓冲区
15 int len = 0;
16 byte[] buffer = new byte[1024];
17 //6.获取OutputStream对象
18 ServletOutputStream outputStream = resp.getOutputStream();
19 //7.将inputStream写入缓冲区,将缓冲区数据写入outputStream
20 while ((len=inputStream.read(buffer)) != -1){
21 outputStream.write(buffer,0,len);
22 }
23
24 inputStream.close();
25 outputStream.close();
26 }
27
28
29 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
30 this.doGet(req, resp);
31 }
32}
运行效果:
- 验证码
resp.setHeader参数:
xxxxxxxxxx
61//设置浏览器自动刷新
2resp.setHeader("refresh","5");
3//不允许缓存
4resp.setDateHeader("expires",-1);
5resp.setHeader("Cache-Control","no-cache");
6resp.setHeader("Pragma","no-cache");
生成验证码图片的Servlet:
xxxxxxxxxx
371protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
2 //让浏览器自动刷新
3 resp.setHeader("refresh","5");
4
5 //在内存中创建图片
6 BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
7 //得到图片
8 Graphics2D g = (Graphics2D) image.getGraphics();//笔
9 //设置图片背景颜色
10 g.setColor(Color.white);
11 g.fillRect(0,0,80,20);
12 //给图片写数据
13 g.setColor(Color.blue);
14 g.setFont(new Font(null,Font.BOLD,20));
15 g.drawString(RandNum(),20,18);
16
17 //告诉浏览器,请求用图片方式打开
18 resp.setContentType("image/jpeg");
19 //不允许缓存
20 resp.setDateHeader("expires",-1);
21 resp.setHeader("Cache-Control","no-cache");
22 resp.setHeader("Pragma","no-cache");
23
24 //把图片写入
25 ImageIO.write(image,"jpeg",resp.getOutputStream());
26}
27
28private String RandNum(){
29 Random random = new Random();
30 String num = random.nextInt(9999) + "";
31 StringBuffer sb = new StringBuffer();
32 for (int i = 0; i < 4-num.length(); i++) {
33 sb.append("0");
34 }
35 num = sb.toString() + num;
36 return num;
37}
运行结果:
- 重定向
请求重定向到其他页面
xxxxxxxxxx
31protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
2 resp.sendRedirect("/r/image");//重定向
3}
结果:
重定向相当于设置Location位置和状态码302
xxxxxxxxxx
21resp.setHeader("Location","/r/image");
2resp.setStatus(302);
重定向和转发的区别:
相同:
- 页面跳转
不同:
- 转发URL地址不变,相当于把req,resp交给其他的Servlet类处理(或是通过HTTP请求转发到其他进程)
- 重定向URL地址改变,相当于发送请求到目标地址,该地址响应重定向状态,并返回一个地址,然后再次请求重定向返回的地址
6.6 HttpServletRequest类
获取参数
登录首页:
xxxxxxxxxx
241<%page contentType="text/html;charset=UTF-8" language="java" %>
2<html>
3<head>
4 <title>登录</title>
5</head>
6<body>
7
8<div>
9 <h1>登录</h1>
10 <form action="${pageContext.request.contextPath}/login" method="post">
11 <p>用户名:<input type="text" name="username"></p>
12 <p>密码:<input type="password" name="password"></p>
13 <p>
14 登录方式:
15 <input type="checkbox" name="login" value="wei">微信
16 <input type="checkbox" name="login" value="qq">QQ
17 <input type="checkbox" name="login" value="ma">扫码
18 </p>
19 <input type="submit">
20 </form>
21</div>
22
23</body>
24</html>
servlet:
xxxxxxxxxx
231public class ServletLogin extends HttpServlet {
2
3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4 req.setCharacterEncoding("utf-8");
5
6 String username = req.getParameter("username");
7 String password = req.getParameter("password");
8 String[] logins = req.getParameterValues("login");
9
10 System.out.println("==================");
11 System.out.println(username);
12 System.out.println(password);
13 System.out.println(Arrays.toString(logins));
14 System.out.println("==================");
15
16 req.getRequestDispatcher("/success.jsp").forward(req,resp);
17 }
18
19
20 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
21 this.doGet(req, resp);
22 }
23}
运行结果:
登录页面:
获取信息:
7 Cookie、Session
7.1 会话
会话:用户打开浏览器,点击链接等操作,关闭浏览器,这个过程称之为会话
有状态会话:访问网页,下次访问记录曾经访问过
客户端 服务端
服务端给客户端一个Cookie,客户端下次访问带上Cookie
- 服务端登记客户端访问的记录,下次登录进行匹配(Session)
7.2 保存会话技术
cookie:客户端技术
session:服务器技术,保存用户的会话信息
常见场景:网站登录之后,下次打开网页自动登录
7.3 Cookie
1.从客户端请求中获取Cookie
2.服务器响应客户端cookie
xxxxxxxxxx
351protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
2 //服务器给客户端一个信件,下次客户端访问带上信件,就能知道客户端访问过
3 //中文编码
4 req.setCharacterEncoding("utf-8");
5 resp.setCharacterEncoding("utf-8");
6 resp.setContentType("text/html");
7
8 PrintWriter writer = resp.getWriter();
9 //服务端获取客户端Cookie
10 Cookie[] cookies = req.getCookies();//cookie存在多个
11
12 //判断Cookie是否存在
13 if (cookies != null){
14 //存在Cookie
15 writer.write("上次访问过,上次访问的时间是:");
16
17 for (Cookie cookie : cookies) {
18 //获取cookie的名字
19 if (cookie.getName().equals("LastLoginTime")) {
20 long LastLoginTime = Long.parseLong(cookie.getValue());
21 Date date = new Date(LastLoginTime);
22 SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
23 writer.write(ft.format(date));
24 }
25 }
26
27 }else {
28 writer.write("第一次访问,请注册或登录");
29 }
30
31 //服务端给客户端响应cookie
32 Cookie cookie = new Cookie("LastLoginTime", System.currentTimeMillis()+"");
33
34 resp.addCookie(cookie);
35}
服务端响应客户端cookie
服务端获取到客户端cookie
设置cookie有效期:
xxxxxxxxxx
11cookie.setMaxAge(24*60*60);
cookie有效时间与到期时间:
Cookie细节问题
- 一个Cookie只能保存一个信息;
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- cookie大小限制4kb
- 浏览器存储上限300个cookie
删除Cookie
- 不设置有效期,关闭浏览器,自动失效
- 将有效期设为0
xxxxxxxxxx
51//创建一个Cookie,名字与被删除的Cookie名字一致
2Cookie cookie = new Cookie("LastLoginTime","");
3//设置Cookie有效期为0,马上过期
4cookie.setMaxAge(0);
5resp.addCookie(cookie);
编码解码
如果Cookie储存中文出现乱码问题,进行utf-8编码
xxxxxxxxxx
21URLEncoder.encode("张三", "utf-8");
2URLDecoder.decode(cookie.getValue(), "utf-8");
7.4 Session
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没关,Session存在
Session和Cookie的区别
- Cookie把用户数据写给用户,在浏览器客户端保存
- Session把用户数据写到Session(每次访问单独创建Session,通过SessionID保证用户唯一)中,由服务器保存
获取Session,保存对象到Session
xxxxxxxxxx
201req.setCharacterEncoding("utf-8");
2resp.setCharacterEncoding("utf-8");
3resp.setContentType("text/html;charset=utf-8");
4
5//得到Session
6HttpSession session = req.getSession();
7
8//存Session
9session.setAttribute("name",new person("张三",24));
10
11//获取Session的ID
12String id = session.getId();
13
14
15//判断Session是不是新创建
16if (session.isNew()){
17 resp.getWriter().write("session创建成功,ID:"+id);
18}else{
19 resp.getWriter().write("session已经创建,ID:"+id);
20}
可以看到SessionID会保存在cookie中
服务器给用户的是SessionID,用户通过SessionID来识别唯一的session,session信息保存在服务端,用户通过SessionID来获取Session的信息。
session的应用:
- 保存登录信息
- 保存网站常用数据
获取Session的信息
xxxxxxxxxx
111req.setCharacterEncoding("utf-8");
2resp.setCharacterEncoding("utf-8");
3resp.setContentType("text/html;charset=utf-8");
4
5//得到Session
6HttpSession session = req.getSession();
7
8//获取Session的字段
9person name = (person) session.getAttribute("name");
10
11resp.getWriter().write(name.toString());
注销Sesion
手动设置失效:
xxxxxxxxxx
31HttpSession session = req.getSession();
2session.removeAttribute("name");//移除这个属性
3session.invalidate();//无效化Session
自动失效时间:
在web.xml设置:
xxxxxxxxxx
51<!--设置Session的默认失效时间-->
2 <session-config>
3 <!--15分钟Session自动失效-->
4 <session-timeout>15</session-timeout>
5 </session-config>
8 JSP
8.1 简介
Java Server Page: Java服务器页面
JSP与HTML区别:
- HTML只给用户提供静态的数据(无法与服务端交互)
- JSP页面可以嵌入JAVA代码,提供动态页面
8.2 JSP原理
Jsp会转换为Servlet类
在Tomcat文件夹下可以找到Jsp源码(在访问JSP页面才会生成)
可以找到JSP继承Servlet类
JSP源码分析:
xxxxxxxxxx
61//初始化
2public void _jspInit()
3//销毁
4public void _jspDestroy()
5//服务
6public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
内置对象:
xxxxxxxxxx
111final javax.servlet.jsp.PageContext pageContext; //页面上下文
2javax.servlet.http.HttpSession session = null; //Session
3final javax.servlet.ServletContext application; //ApplicationContext应用上下文作用域所有Servllet
4final javax.servlet.ServletConfig config; //config
5javax.servlet.jsp.JspWriter out = null; //out
6final java.lang.Object page = this; //page = 当前页面
7javax.servlet.jsp.JspWriter _jspx_out = null;
8javax.servlet.jsp.PageContext _jspx_page_context = null;
9
10HttpServletRequest request //请求
11HttpServletResponse response //响应
配置:
xxxxxxxxxx
91response.setContentType("text/html;charset=UTF-8"); //设置页面响应类型
2pageContext = _jspxFactory.getPageContext(this, request, response,
3 null, true, 8192, true);
4_jspx_page_context = pageContext;
5application = pageContext.getServletContext();
6config = pageContext.getServletConfig();
7session = pageContext.getSession();
8out = pageContext.getOut();
9_jspx_out = out;
这些对象在JSP可以直接使用
输出页面:
JSP:
xxxxxxxxxx
81<html>
2<head>
3 <title>Title</title>
4</head>
5<body>
6hello
7</body>
8</html>
Servlet:
xxxxxxxxxx
91out.write("\r\n");
2out.write("<html>\r\n");
3out.write("<head>\r\n");
4out.write(" <title>Title</title>\r\n");
5out.write("</head>\r\n");
6out.write("<body>\r\n");
7out.write("hello\r\n");
8out.write("</body>\r\n");
9out.write("</html>\r\n");
8.3 JSP基本语法
JSP中Java代码规范与Java语法相同,会扩充一些语法
JSP表达式:
xxxxxxxxxx
51<%--JSP表达式
2作用:将程序的结果输出到页面
3<%= 变量或表达式 %>
4--%>
5<%= new java.util.Date()%>
JSP脚本片段:
xxxxxxxxxx
81<%--JSP脚本片段--%>
2<%
3int sum = 0;
4for (int i = 0; i < 100; i++) {
5 sum += i;
6}
7out.println("<h3>sum = "+sum+"</h3>");
8%>
xxxxxxxxxx
71<%
2for (int i = 0; i < 5; i++) {
3 %>
4<h3>循环第<%= i %>次</h3>
5<%
6}
7%>
JSP声明:
提高作用域,将代码放在类中,可以声明全局变量或定义方法
xxxxxxxxxx
171<%--JSP声明--%>
2<%!
3private String Name;
4public String getName(){
5 return this.Name;
6}
7
8public void setName(String name){
9 this.Name = name;
10}
11%>
12
13<%
14setName("张三");
15%>
16
17<h3>name:<%= getName()%></h3>
注释:JSP注释在页面源代码看不到,HTML可以看到
8.4 JSP指令
1.设置页面信息
xxxxxxxxxx
81<%--设置页面响应为HTML,编码为UTF-8--%>
2<%page contentType="text/html;charset=UTF-8" language="java" %>
3<%--设置错误转跳页面--%>
4<%page errorPage="error/500.jsp" %>
5<%--设置是否错误页面--%>
6<%page isErrorPage="true" %>
7<%--设置页面编码--%>
8<%page pageEncoding="UTF-8" %>
设值页面错误:
xxxxxxxxxx
31<%
2 int i = 1/0;
3%>
遇到500错误会直接转跳到500.jsp页面
也可以在web.xml设置错误转跳的页面:
xxxxxxxxxx
81<error-page>
2 <error-code>404</error-code>
3 <location>/error/404.jsp</location>
4</error-page>
5<error-page>
6 <error-code>500</error-code>
7 <location>/error/500.jsp</location>
8</error-page>
2.include包含
header.jsp,footer.jsp中写入网站通用的头部和尾部,include指令就会把头部尾部拼接到网页中
xxxxxxxxxx
31<%include file="common/header.jsp"%>
2<h1>网页主体</h1>
3<%include file="common/footer.jsp"%>
使用JSP标签也能实现一样的效果,但是不会拼接jsp而是调用
xxxxxxxxxx
31<jsp:include page="/common/header.jsp"></jsp:include>
2<h1>网页主体</h1>
3<jsp:include page="/common/header.jsp"></jsp:include>
注意:一般使用JSP标签,使用上面的方式会拼接代码,如果在include的jsp文件与外面的jsp文件声明同名变量会导致栈错误,而下面的方式不会。
8.5 9大内置对象
- PageContext
- Request
- Response
- Session
- Application
- ServletConfig
- out
- page
- exception
对象及作用域
xxxxxxxxxx
291<%--内置对象--%>
2
3<%
4 pageContext.setAttribute("name1","张三1"); //保存的数据只在一个页面中有效
5 request.setAttribute("name2","张三2"); //保存在一次请求中有效,转发会携带这个数据
6 session.setAttribute("name3","张三3"); //保存的数据在一次会话中有效,从打开浏览器到关闭浏览器
7 application.setAttribute("name4","张三4"); //保存的数据在服务器中,从打开服务器到关闭服务器
8%>
9
10<%
11 /*通过pageContext取出 寻找方式*/
12 /*寻找:从底层到高层(作用域)
13 * page->request->session->application*/
14 String name1 = (String) pageContext.findAttribute("name1");
15 String name2 = (String) pageContext.findAttribute("name2");
16 String name3 = (String) pageContext.findAttribute("name3");
17 String name4 = (String) pageContext.findAttribute("name4");
18 String name5 = (String) pageContext.findAttribute("name5");
19%>
20
21<%--使用EL表达式进行输出--%>
22
23<h3>${name1}</h3>
24<h3>${name2}</h3>
25<h3>${name3}</h3>
26<h3>${name4}</h3>
27<h3>${name5}</h3>
28
29<h3><%=name5%></h3>
注:使用EL表达式不会在网站上显示null的结果 使用JSP表达式会显示null
在另一个页面中取出
xxxxxxxxxx
171<%
2 /*通过pageContext取出 寻找方式*/
3 /*寻找:从底层到高层(作用域)*/
4 String name1 = (String) pageContext.findAttribute("name1");
5 String name2 = (String) pageContext.findAttribute("name2");
6 String name3 = (String) pageContext.findAttribute("name3");//能取到
7 String name4 = (String) pageContext.findAttribute("name4");//能取到
8 String name5 = (String) pageContext.findAttribute("name5");
9%>
10
11<%--使用EL表达式进行输出--%>
12
13<h3>${name1}</h3>
14<h3>${name2}</h3>
15<h3>${name3}</h3>
16<h3>${name4}</h3>
17<h3>${name5}</h3>
对象及作用域:
- pageContext:保存的数据只在一个页面中有效
- request:保存在一次请求中有效,转发会携带这个数据,用户用完就没用的数据
- session:保存的数据在一次会话中有效,从打开浏览器到关闭浏览器,用户用完还有用的数据
- application:保存的数据在服务器中,从打开服务器到关闭服务器,一个用户使用完其他用户还会使用的数据
8.6 JSP、JSTL标签 EL表达式
maven依赖:
xxxxxxxxxx
121<!--jstl表达式-->
2<dependency>
3 <groupId>javax.servlet.jsp.jstl</groupId>
4 <artifactId>jstl-api</artifactId>
5 <version>1.2</version>
6</dependency>
7<!--taglib-->
8<dependency>
9 <groupId>taglibs</groupId>
10 <artifactId>standard</artifactId>
11 <version>1.1.2</version>
12</dependency>
JSP标签
包含
xxxxxxxxxx
11<jsp:include page="JSP1.jsp"></jsp:include>
设置转发与请求参数
xxxxxxxxxx
41<jsp:forward page="JspTag02.jsp">
2 <jsp:param name="name" value="zhangsan"/>
3 <jsp:param name="age" value="1"/>
4</jsp:forward>
取出参数,处理转发
xxxxxxxxxx
31<%--取出参数--%>
2名字:<%=request.getParameter("name")%> <br>
3年龄:<%=request.getParameter("age")%>
JSTL表达式
JSTL标签库的使用弥补HTML标签的不足,标签的功能与Java代码相同
- 核心标签
- 格式化标签
- SQL标签
- XML标签
JSTL标签的使用
导入taglib:
xxxxxxxxxx
11<%taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
form表单:
xxxxxxxxxx
41<form action="JSTLCore.jsp" method="get">
2 <input type="text" name="username" value="${param.username}"><br>
3 <input type="submit" value="登录">
4</form>
JSTL标签:
xxxxxxxxxx
81<%--判断提交的用户名是否为管理员--%>
2<c:if test="${param.username=='admin'}" var="checked">
3 <c:out value="管理员"></c:out>
4</c:if>
5
6<br>
7
8<c:out value="${checked}"></c:out>
判断的使用
xxxxxxxxxx
161<c:set var="score" value="82"></c:set>
2
3<c:choose>
4 <c:when test="${score>=90}">
5 成绩大于90
6 </c:when>
7 <c:when test="${score>=80}">
8 成绩大于80
9 </c:when>
10 <c:when test="${score>=70}">
11 成绩大于70
12 </c:when>
13 <c:when test="${score<=60}">
14 成绩不及格
15 </c:when>
16</c:choose>
for遍历
xxxxxxxxxx
131<%
2 ArrayList<String> name = new ArrayList<String>();
3 name.add("张三");
4 name.add("李四");
5 name.add("王五");
6 name.add("田六");
7 request.setAttribute("list",name);
8%>
9
10<%--遍历--%>
11<c:forEach var="name" items="${list}">
12 <c:out value="${name}"></c:out> <br>
13</c:forEach>
9 MVC三层架构
MVC: Model View Controller 模型、视图、控制器
View
- 展示数据
- 提供发起Servlet请求的操作(a,form...)
Controller
- 接收用户请求(req:请求参数,session)
- 调用业务层处理请求
- 控制视图跳转
Model
- 处理业务 (Service)
- 数据持久化: CRUD
posted on 2022-03-03 16:14 Egoistic_Flowers 阅读(98) 评论(0) 编辑 收藏 举报