Servlet 的开发步骤:
开发一个类,继承 HttpServlet, 重写 doGet 方法
在 web.xml中,去配置这个 Servlet
部署到 Tomcat 容器中
启动 Tomcat
打开浏览器,发送请求,查看响应
整个工程结构如下:
web-servlet-01-hello
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── guyu
│ │ └── servlet01
│ │ └── servlet
│ │ └── HelloServlet.java
│ ├── resources
│ └── webapp
│ ├── WEB-INF
│ │ └── web.xml
│ └── index.jsp
└── test
└── java
-
项目工程模板 【mavenWebProject】链接:
链接:https://pan.baidu.com/s/12YVZQr0pH-gi-mVI35c9Dg
提取码:58b1
各目录的作用:
pom.xml:用于管理源代码、配置文件、项目授权、项目的依赖关系等等
src:主要用来存放我们的 Java 代码
webapp:主要用来存放需要发布的应用文件,包括页面,配置文件等
WEB-INF:存放一些管理类,配置文件等
web.xml: 项目的配置文件
index.jsp: 默认的首页面
test: 测试类代码
利用 tomcat7-maven-plugin 插件运行如下图所示:
在浏览器输入 http://localhost:10086/hs 如下图所示:
浏览器输入 http://localhost:10086/hs/hello 如下图所示:
就这样,Web 开发和部署一个 Servlet 实例是不是很简单呀,源代码如下:
pom.xml 代码如下:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.guyu</groupId>
<artifactId>Servlet-01</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven Web Project and Servlet-01</name>
<url>https://www.cnblogs.com/guyu-</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--provided-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!--runtime-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<!--test-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 内置Tomcat插件端口,只适合开发环境,不适合产品环境 -->
<port>10086</port>
<!-- 应用名 -->
<path>/hs</path>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
</plugin>
</plugins>
</build>
</project>
注:内置 tomcat 端口号 10086 和 应用名 /hs 可自行更改配置.本实例都以此配置
webapp/index.jsp 代码如下:
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" %>
<html>
<body>
<h2 align="center">你好 maven web 项目!</h2>
</body>
</html>
webapp/WEB-INF/web.xml 代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<!-- listener -->
<!-- filter -->
<!-- servlet -->
<!-- 基于xml配置,八行代码-->
<servlet>
<!--自定义,一般为类名-->
<servlet-name>helloservlet</servlet-name>
<!--一定是package + .类名-->
<servlet-class>com.guyu.servlet01.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--给Servlet提供(映射)一个可供客户端访问的URL-->
<servlet-name>helloservlet</servlet-name>
<!-- servlet的映射路径 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
servlet01\servlet\HelloServlet.javal 代码如下:
package com.guyu.servlet01.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;
import java.util.Date;
/**
* @Author: Fred
* @Date: 2020/10/13 11:23
* @description 第一个 Servlet 实例
*/
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//0. 设置响应头
resp.setContentType("text/html;charset=utf-8");
//1. 通过response对象来获取对浏览器端的输出流
PrintWriter pw = resp.getWriter();
//2. 调用方法输出
pw.println("<html>");
pw.println("<head>");
pw.println("<title>hello,servlet</title>");
pw.println("</head>");
pw.println("<body>");
pw.println("<h2 align=\"center\">你好,故屿!</h2>");
pw.println("<p align=\"center\">当前系统时间:"+new Date()+"</p>");
pw.println("</body>");
//3.释放资源
pw.close();
}
}
注:
此实例只对初学者,上述代码可通过在 HelloServlet.java 类中加 @WebServlet(urlPatterns = “/hello”) 注解代替 web.xml 八行代码。
另外可使用 JSP 指令、标签和 HTML 的综合体开发更简便。
针对 Servlet 配置的初始化参数,支持xml和注解两种配置。
以下加强实例 [8]
Servlet 从创建到销毁的过程
- init()
Servlet 通过调用 init () 方法进行初始化 - service()
Servlet 调用 service() 方法来处理客户端的请求 - destroy()
Servlet 通过调用 destroy() 方法终止(结束)
最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
如下代码:
package com.guyu.servlet01.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: Fred
* @Date: 2020/10/13 16:03
*/
//若使用了 load-on-startup 则根据 load-on-startup=1 的值来先后创建这些 Servlet,并直接调用它们的init方法,发送请求后才会调用service()方法
@WebServlet(urlPatterns = "/life")
//@WebServlet(urlPatterns = "/life",loadOnStartup = 1)
public class LifeCycleServlet extends HttpServlet {
private int count = 0;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
//
count++;
//
pw.println("<h2 align=\"center\">每次请求都会调用1次service方法,共计:"+count+"次</h2>");
System.out.println("--- LifeCycleServlet的service()方法被调用了 --> "+count+"次");
//
pw.close();
}
/*********************
* 此方法也只会执行1次,它的执行时机:
* 当此Servlet被摧毁卸载时或应用被容器给停掉[undeploy] 或 容器 shutdown 时
* 需 startup 启动 Tomcat,发送localhost:9090 登录容器选择 undeploy 即可响应
*/
@Override
public void destroy() {
System.out.println("-- LifeCycleServlet的destroy()方法被调用了...");
}
/*********************
* 此方法是在容器创建完Servlet实例后,就被调用,只调用1次。
* @throws ServletException
*/
@Override
public void init() throws ServletException {
System.out.println("--- LifeCycleServlet的init()方法被调用了....");
System.out.println("--- 请等待五秒....");
//模拟这个过程需5秒....
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
此实例演示初始化参数: 向浏览器端发送请求,响应信息实时地写入到创建本地文件中
- servlet02\servlet\InitParamServlet .javal 代码如下:
package com.guyu.servlet02.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* @Author: Fred
* * @Date: 2020/10/14 15:12
*/
@WebServlet(urlPatterns = {"/init/param"},
initParams = {
@WebInitParam(name="flag",value = "true"),
@WebInitParam(name="dir", value = "D:\\temp\\count.txt")
})
public class InitParamServlet extends HttpServlet {
private int count = 0;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//获取当前servlet初始化参数
ServletConfig servletConfig = getServletConfig();
String flag = servletConfig.getInitParameter("flag");
String dir = servletConfig.getInitParameter("dir");
//获取全局初始化参数
String global = getServletContext().getInitParameter("global");
//
count++;
//
if(Boolean.parseBoolean(flag)) {
//把这个计数器中的值实时地写入到文件中
File file = new File(dir);
if(!file.exists()) {
file.createNewFile();
}
//输入
PrintWriter out = new PrintWriter(new FileWriter(file,true), true);
out.println("当前访问的次数:"+count+"\n"+new Date());
//关闭
out.close();
//再往浏览器端写信息
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.println("<h2 align=\"center\">访问次数:"+count+"</h2>");
pw.println("<h3 align=\"center\">"+global+"</h3>");
pw.close();
}
}
}
- webapp/WEB-INF/web.xml 代码中 全局初始化参数配置 如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<!-- listener -->
<!-- filter -->
<!-- servlet -->
<!-- 全局初始化参数-->
<context-param>
<param-name>global</param-name>
<param-value>hello,context param and guyu</param-value>
</context-param>
<!-- 第一个 servlet 实例-->
<servlet>
<!--自定义,一般为类名-->
<servlet-name>helloservlet</servlet-name>
<!--一定是package + .类名-->
<servlet-class>com.guyu.servlet01.servlet.HelloServlet</servlet-class>
<!-- <load-on-startup>1</load-on-startup>-->
<!-- 基于xml配置,为了简单快捷推荐使用基于注解的配置-->
<!-- <init-param>-->
<!-- <param-name>path</param-name>-->
<!-- <param-value>d:/temp</param-value>-->
<!-- </init-param>-->
<!-- <init-param>-->
<!-- <param-name>name</param-name>-->
<!-- <param-value>故屿</param-value>-->
<!-- </init-param>-->
</servlet>
<servlet-mapping>
<!--给Servlet提供(映射)一个可供客户端访问的URL-->
<servlet-name>helloservlet</servlet-name>
<!-- servlet的映射路径 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!-- 第二个 servlet 实例-->
<servlet>
<servlet-name>showservlet</servlet-name>
<servlet-class>com.guyu.servlet01.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>showservlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
</web-app>
- 运行后在浏览器输入 http://localhost:10086/hs/init/param 刷新三次如下图所示:
- 在本地 D:\temp\count.txt 文件中看查看响应信息
此实例演示有关Servlet 的 url-pattern 的模糊匹配模式
- servlet02\servlet\UrlPatternServlet.javal 代码如下:
package com.guyu.servlet02.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: Fred
* @Date: 2020/10/14 16:12
*
* 此案例演示 url-pattern的模糊匹配
*/
//@WebServlet(urlPatterns = "/demo/*")
@WebServlet(urlPatterns = "*.haha")
public class UrlPatternServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//通过以下几个方法,让大家理解url的涵义
//http://host:port/appName/resource?queryString
//http://192.168.0.34:9090/crm/user/query?id=1
String host = req.getRemoteHost();
int port = req.getServerPort();
//获取应用名
String appName = req.getContextPath();
//获取servlet的url-pattern
String servletPath = req.getServletPath();
//获取除 servlet path以外的其它路径中的信息
String pathInfo = req.getPathInfo();
//获取queryString
String queryString = req.getQueryString();
//输出以上信息
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
//
pw.print("<p align=\"center\">主机名:"+host+"</p>");
pw.print("<p align=\"center\">服务端口:"+port+"</p>");
pw.print("<p align=\"center\">应用名:"+appName+"</p>");
pw.print("<p align=\"center\">servlet-path:"+servletPath+"</p>");
pw.print("<p align=\"center\">pathInfo:"+pathInfo+"</p>");
pw.print("<p align=\"center\">queryString:"+queryString+"</p>");
pw.close();
}
}
- 运行后在浏览器输入 http://127.0.0.1:10086/hs/demo/update?guyu 如下图所示:
注意:以上使用注解@WebServlet(urlPatterns = "/demo/*")
以下使用注解@WebServlet(urlPatterns = "*.haha")
- 运行后在浏览器输入http://127.0.0.1:10086/hs/demo/update.haha?guyu 如下图所示:
以上关于模糊匹配 这个*号对应的路径,可以通过 getPathInfo 来获取,从而判断具本的请求操作
此实例演示表单如何获取请求参数
- servlet02\servlet\FormParameterServlet.javal 代码如下:
package com.guyu.servlet02.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.Arrays;
/**
* @Author: Fred
* @Date: 2020-10-15 10:19:00
*
* 此案例演示如何获取请求参数
*/
@WebServlet(urlPatterns = "/param/form", name = "formServlet")
public class FormParameterServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求体部和响应体部的编码,需为 post 请求【不是头部】
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//获取请求参数,通过 getParameter 和 getParameterValues 方法
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
String pwd2 = req.getParameter("pwd2");
String age = req.getParameter("age");
String sex = req.getParameter("sex");
String email = req.getParameter("email");
String birth = req.getParameter("birth");
//针对复选框,调用多个值的方法
String[] hobbies = req.getParameterValues("hobby");
//获取文件
String icon = req.getParameter("icon");
//获取隐藏域
String special = req.getParameter("special");
//获取多行文本框
String intro = req.getParameter("intro");
//获取单选下拉框的值
String degree = req.getParameter("degree");
//输出以上信息
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.print("<h2 align=\"center\">请求的数据已全部收到,请查看后台控制台</h2>");
pw.close();
//下面,在控制台中输出以上的变量
System.out.printf("UserName: %s\n",username);
System.out.printf("Pwd: %s \n", pwd);
System.out.printf("Pwd2: %s \n", pwd2);
System.out.printf("Age: %s \n", age);
System.out.printf("Sex: %s \n", sex);
System.out.printf("Email: %s \n", email);
System.out.printf("Birth: %s \n", birth);
//复选框:
if(hobbies != null) {
System.out.printf("爱好:%s\n", Arrays.toString(hobbies));
}
//
System.out.printf("Icon: %s \n", icon);
System.out.printf("Special: %s \n", special);
System.out.printf("Intro: %s \n", intro);
System.out.printf("Degree: %s \n", degree);
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ctrl+o 重写doPost方法,返回doGet
doGet(req, resp);
}
}
- webapp/html/form.html 代码中 表单元素 如下:
<!DOCTYPE html>
<html>
<head>
<title>表单案例</title>
<meta charset="utf-8">
</head>
<body>
<h2 align="center">表单元素</h2>
<hr size="10" noshade="noshade">
<h3 align="center">以下是一个多种不同类型的表单域</h3>
<!-- post请求,提交表单数据响应控制台返回值全为 null -->
<form action="/hs/param/form" name="xxForm" method="post"
enctype="multipart/form-data">
<!-- 提交表单数据响应控制台返回数据值,该 enctype 为默认值可不写,这种情况下,method 可以是 get或post,注未配置get编码 -->
<!--<form action="/hs/param/form" name="xxForm" method="post">-->
<!-- enctype="application/x-www-form-urlencoded">-->
<br>
<p align="center"><input type="text" name="username" placeholder="用户名"></p>
<p align="center"><input type="password" name="pwd" placeholder="密码"></p>
<p align="center"><input type="password" name="pwd2" placeholder="请确认密码"></p>
<p align="center"><input type="number" name="age" placeholder="你的年龄">
<p align="center">
<input type="radio" name="sex" value="1" checked>男
<input type="radio" name="sex" value="0">女
</p>
<p align="center"><input type="email" name="email" placeholder="你的邮箱"></p>
<p align="center"><input type="date" name="birth" placeholder="你的生日"></p>
<p align="center">
<input type="checkbox" name="hobby" value="编程">编程
<input type="checkbox" name="hobby" value="电影">电影
<input type="checkbox" name="hobby" value="小说">小说
<input type="checkbox" name="hobby" value="游戏">游戏
</p>
<p align="center">请选择头像:<input type="file" name="icon" accept="image/png"></p>
<!-- 表单的隐藏域,在页面上是不显示的 -->
<input type="hidden" name="special" value="100">
<!-- 多行文本框 -->
<p align="center">
<textarea cols="13" cols="37" name="intro" placeholder="自我介绍"></textarea>
</p>
<!-- 下拉选择框 -->
<p align="center">
<select name="degree">
<option value="novalue" selected>=请选择=</option>
<option value="本科">本科</option>
<option value="专科">专科</option>
<option value="硕士">硕士</option>
<option value="博士">博士</option>
<option value="高中">高中</option>
<option value="中专">中专</option>
<option value="其它">其它</option>
</select>
</p>
<p align="center">
<input type="button" value="普通按钮">
<input type="submit" value="提交表单">
<input type="reset" value="重置表单">
</p>
</form>
<!-- 待上面的HTML文档加载完成后,再来导入js -->
<script type="text/javascript" src="js/form_demo.js"></script>
</body>
</html>
- 以 enctype 属性是 “multipart/form-data”
运行后在浏览器先输入 http://localhost:10086/hs/html/form.html 如下图所示:
- 输入填写表单数据后 提交表单 此时已自动跳转 http://localhost:10086/hs/param/form 如下图所示:
- 在控制台中输出的数据变量 如下图所示:
-
以 enctype 属性是 “application/x-www-form-urlencoded”
运行后在浏览器先输入 http://localhost:10086/hs/html/form.html 输入填写表单数据后 提交表单 此时已自动跳转 http://localhost:10086/hs/param/form
- 在控制台中输出的数据变量 如下图所示:
获取请求参数时需要注意的事项:
不同的表单类型,在后台需要使用不同的方法来获取表单数据
其中,如果<form> 的enctype属性是:
enctype="multipart/form-data" 时,method必需是 post, 则后台需要通过
request.getPart() 或 request.getParts() 来获取表单数据。
enctype="application/x-www-form-urlencoded" 这个值是默认值,这种情况下,method可以是 get或post, 后台则通过
request.getParameter() 或 request.getParameterValues() 来获取表单数据。
注:只要不做文件上传,则enctype就使用默认值。
此实例演示 Servlet 每隔 1 秒显示当前系统时间
- servlet02\servlet\RefreshServlet .javal 代码如下:
package com.guyu.servlet02.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: Fred
* @Date: 2020/10/15 17:24
*
* 扩展 HttpServlet 类,刷新自动加载时间设置显示
*/
@WebServlet(urlPatterns = "/Refresh")
public class RefreshServlet extends HttpServlet {
// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置刷新自动加载时间为 1 秒
response.setIntHeader("Refresh", 1);
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
//使用默认时区和语言环境获得一个日历
Calendar cale = Calendar.getInstance();
//将Calendar类型转换成Date类型
Date tasktime=cale.getTime();
//设置日期输出的格式
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E a");
//格式化输出
String nowTime = df.format(tasktime);
PrintWriter out = response.getWriter();
String title = "自动刷新 Header 设置 - 1秒一次";
String docType =
"<!DOCTYPE html>\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n"+
"<body bgcolor=\"#BFEFFF\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" + "<br>" +
"<font color=\"#FF0000\">\n" +
"<h4 align=\"center\" >当前时间是:" + nowTime + "</p>\n");
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- 运行后在浏览器输入 http://localhost:10086/hs/Refresh 如下图所示:
本案例演示请求的跳转
- servlet02\servlet\JumpServlet.javal 代码如下:
package com.guyu.servlet02.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: Fred
* @Date: 2020/10/16 10:19
*
* 本案例演示请求的跳转
*/
@WebServlet(urlPatterns = "/jump/*",name = "jumpServlet")
public class JumpServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String pathinfo = req.getPathInfo();
if(pathinfo != null) {
//进一步判断这个值
if(pathinfo.equals("/one")) {
//执行 one 操作
System.out.println("即将跳转到 /init/param中...");
//浏览器请求跳转到 /init/param 后,控制台响应显示输出信息
jump("/init/param",req, resp);
//可写可不写
return ;
} else if(pathinfo.equals("/two")) {
//执行 two 操作时 请求http://localhost:10086/hs/jump/two
// 直接把 one 修改 two 时为出现后台无响应信息,需路径整串重新请求
System.out.println("即将跳转到 /html/form.html中...");
// System.out.println("即将跳转到 /WEB-INF/jsp/hello.jsp...");
//跳转静态资源
jump("/html/form.html",req, resp);
//跳转 webapp/WEB-INF 被容器给保护的资源
//jump("/WEB-INF/jsp/hello.jsp", req, resp);
//可写可不写
return ;
} else {
//说明用户写的资源,我们没有 此访问 http://localhost:10086/hs/jump/*
resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "406... 不接受此请求,请重新输入指定 /* 的值!");
//执行 /* 操作
//System.out.println("请重新输入指定 /* 的值!");
//return ;
}
}
}
/*****
* 跳转方法
* @param target
* @param req
* @param resp
*/
private void jump(String target, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取 RequestDispatcher对象
// RequestDispatcher dispatcher = req.getRequestDispatcher(target);
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(target);
//2. 直接转发
dispatcher.forward(req, resp);
}
}
- webapp/WEB-INF/jsp/hello.jsp 此目录下代码必需要通过 Servlet 跳转如下:
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/10/16
Time: 10:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp</title>
</head>
<body>
<h1 align="center">恭喜你,跳进来了 故屿!</h1>
</body>
</html>
- 运行后在浏览器请求输入 http://localhost:10086/hs/jump/one 如下图所示:
- 在浏览器请求输入 http://localhost:10086/hs/jump/two 如下图所示
- 在浏览器请求输入 http://localhost:10086/hs/jump/* 如下图所示
- 在控制台中响应输出的数据 如下图所示:
注意在 web 开发中,服务端资源分成两大类时:
这些资源如果是放在项目的webapp目录下,我们通过浏览器是可以直接访问的。
如果这些资源是放在项目的webapp/WEB-INF 目录下,则这些资源就被容器给保护起来了,通过
浏览器是不能直接访问,必需要通过Servlet跳转。
- 此时 servlet02\servlet\JumpServlet.javal 代码如下注释修改:
- 在浏览器请求输入 http://localhost:10086/hs/jump/two 如下图(注意通过Servlet跳转后的页面路径不会改变)
就这样通过浏览器请求访问服务端动、静态资源的跳转就完成啦~
本案例演示转发和重定向
- servlet03\servlet\ForwardOrRedirectServlet.javal 代码如下:
package com.guyu.servlet03.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/********
* 此案例演示 转发和重定向
*/
@WebServlet(urlPatterns = "/frdemo/*",name = "frServlet")
public class ForwardOrRedirectServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// HttpSession session = req.getSession();
// ServletContext application = getServletContext();
//
String pathinfo = req.getPathInfo();
if(pathinfo != null) {
if (pathinfo.equals("/forward")) {
//绑定数据
req.setAttribute("DEMO_KEY", "这是放在 request 范围中的数据");
// session.setAttribute("SES_DEMO_KEY","这是放在 session 范围中的数据");
// application.setAttribute("APP_DEMO_KEY", "这是放在 application 范围中的数据");
//转发
req.getRequestDispatcher("/show_result").forward(req, resp);
} else if (pathinfo.equals("/redirect")) {
//绑定数据
req.setAttribute("DEMO_KEY", "这是放在 request 范围中的数据");
// session.setAttribute("SES_DEMO_KEY","这是放在 session 范围中的数据");
// application.setAttribute("APP_DEMO_KEY", "这是放在 application 范围中的数据");
//重定向: 注 location 前面要带上应用名 /hs
String appName = req.getContextPath();
resp.sendRedirect(appName+"/show_result");
// resp.sendRedirect("/show_result");
} else {
//不支持
resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "不支持此请求");
}
} else {
resp.sendError(404, "页面不存在");
}
}
}
- servlet03\servlet\ShowResultServlet .javal 代码如下:
package com.guyu.servlet03.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = "/show_result")
public class ShowResultServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
//直接从请求范围取出之前绑定的值
String demo_key = (String) req.getAttribute("DEMO_KEY");
// String ses_demo_key = (String) req.getSession().getAttribute("SES_DEMO_KEY");
// String app_demo_key = (String) getServletContext().getAttribute("APP_DEMO_KEY");
//
if(demo_key != null) {
// pw.println("<h2 align=\"center\">DEMO_KEY: "+demo_key+"</h2>");
pw.println("<h2 align=\"center\">"+demo_key+"</h2>");
} else {
pw.println("<h2 align=\"center\">从request范围取不到DEMO_KEY</h2>");
}
// pw.println("<h2>SES_DEMO_KEY: "+ses_demo_key+"</h2>");
// pw.println("<h2>APP_DEMO_KEY: "+app_demo_key+"</h2>");
//
pw.close();
}
}
- 运行后在浏览器请求输入 http://localhost:10086/hs/frdemo/forward 如下图所示:
- 此时如上图 需注意 请求转发【forward】 时,地址栏中的地址是不变化的,因为请求是同一个;
- 在浏览器请求输入 http://localhost:10086/hs/frdemo/redirect 时地址变化 如下图所示:
- 重定向【redirect】 时,地址栏中的地址是变化的,因为请求是新的请求!
-
而在浏览器请求输入 http://localhost:10086/hs/frdemo 时,如下图所示:
frdemo 末尾不带 / ,则为 404 页面不存在! frdemo 末尾带 / ,则为 406 不支持此请求!
转发和重定向的区别:
请求转发时,地址栏中的地址是不变化的,因为请求是同一个;
重定向时,地址栏中的地址是变化的,因为请求是新的请求。
请求转发时,可以从 request 中取出之前绑定的 key 值;
重定向时,不能从 request 中取出之前绑定的 key 值。
本案例演示 请求头和响应头的头信息
- servlet03\servlet\HeaderServlet .javal 代码如下:
package com.guyu.servlet03.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.Enumeration;
/**
* 本案例演示 请求头和响应头的信息
*/
@WebServlet(urlPatterns = "/header")
public class HeaderServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//演示浏览器请求后在控制台响应一些头信息
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = req.getHeader(name);
System.out.printf("%s: %s\n", name, value);
}
//响应头类型编码
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
//输出一个页面,可使用Sublime 快速替换编辑
pw.println("<!DOCTYPE html>");
pw.println("<html>");
pw.println("<head>");
pw.println(" <title>header demo</title>");
pw.println(" <meta charset='utf-8'>");
pw.println("</head>");
pw.println("<body>");
pw.println("<div id='container'>");
pw.println(" <h2 align=\"center\">用户登录</h2>");
pw.println(" <form name='loginForm' action='"+req.getContextPath()+"/header' method='post'>");
pw.println(" <p align=\"center\"><input type='text' name='user' placeholder='用户名'></p>");
pw.println(" <p align=\"center\"><input type='password' name='pwd' placeholder='密 码'></p>");
pw.println(" <p align=\"center\">");
pw.println(" <input type='submit' value='登录'>");
pw.println(" <input type='reset' value='重置'>");
pw.println(" </p>");
pw.println(" </form>");
pw.println("</div>");
pw.println("</body>");
pw.println("</html>");
//关闭
pw.close();
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(request, response);
}
}
- 运行后在浏览器请求输入 http://127.0.0.1:10086/hs/header 如下图所示:
- 在控制台中响应输出的数据 如下图所示 请求头信息:
- 继续填写登录
package com.guyu.servlet03.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.Enumeration;
/**
* 本案例演示 请求头和响应头的信息
*/
@WebServlet(urlPatterns = "/header")
public class HeaderServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//演示浏览器请求后在控制台响应一些头信息
// Enumeration<String> headerNames = req.getHeaderNames();
// while (headerNames.hasMoreElements()) {
// String name = headerNames.nextElement();
// String value = req.getHeader(name);
// System.out.printf("%s: %s\n", name, value);
// }
//把上面封装起来
printRequestHeader(req);
//响应头类型编码
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
//输出一个页面,可使用Sublime 快速替换编辑
pw.println("<!DOCTYPE html>");
pw.println("<html>");
pw.println("<head>");
pw.println(" <title>header demo</title>");
pw.println(" <meta charset='utf-8'>");
pw.println("</head>");
pw.println("<body>");
pw.println("<div id='container'>");
pw.println(" <h2 align=\"center\">用户登录</h2>");
pw.println(" <form name='loginForm' action='"+req.getContextPath()+"/header' method='post'>");
pw.println(" <p align=\"center\"><input type='text' name='user' placeholder='用户名'></p>");
pw.println(" <p align=\"center\"><input type='password' name='pwd' placeholder='密 码'></p>");
pw.println(" <p align=\"center\">");
pw.println(" <input type='submit' value='登录'>");
pw.println(" <input type='reset' value='重置'>");
pw.println(" </p>");
pw.println(" </form>");
pw.println("</div>");
pw.println("</body>");
pw.println("</html>");
//关闭
pw.close();
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//获取请求参数
String user = req.getParameter("user");
String pwd = req.getParameter("pwd");
//输出 这两个量变 以及请求头
resp.setContentType("text/html;charset=utf-8");
PrintWriter pw = resp.getWriter();
pw.println("<h2 align=\"center\">你的登录名:"+user+"</h2>");
pw.println("<h2 align=\"center\">登录密码:"+pwd+"</h2>");
//在后台输出请求头
printRequestHeader(req);
}
private void printRequestHeader(HttpServletRequest req) {
System.out.println("--- 华丽丽地分割线 ---");
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = req.getHeader(name);
System.out.printf("%s: %s\n", name, value);
}
}
}
- 运行后在浏览器请求输入 http://127.0.0.1:10086/hs/header 后与填写登录提交 如下图所示:
- 此时在控制台中响应输出的数据,两次分割线信息 如下图所示 :
对上述在浏览器中按 F12 也可查看相关信息:
本案例演示 Cookie 的添加和获取
- servlet03\servlet\CookieServlet.javal 代码如下:
package com.guyu.servlet03.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;
/**
* 本案例演示 cookie的添加和获取
*/
@WebServlet(urlPatterns = "/cookie")
public class CookieServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter pw = resp.getWriter();
//0. 先判断是否有cookie
Cookie[] cookies = req.getCookies();
if(cookies != null && cookies.length > 0) {
//说明已经存在 cookie, 迭代
for(Cookie c : cookies) {
pw.println("<h2 align=\"center\">以下是cookie的值</h2>");
pw.println("<div style='border:1px solid red;margin-left:750px;margin-right:750px'>");
pw.println(" <p align=\"center\">Cookie名: "+c.getName()+"</p>");
pw.println(" <p align=\"center\">Cookie值: "+c.getValue()+"</p>");
pw.println(" <p align=\"center\">Cookie Domain: "+c.getDomain()+"</p>");
pw.println(" <p align=\"center\">Cookie Path: "+c.getPath()+"</p>");
pw.println(" <p align=\"center\">Cookie Max-Age: "+c.getMaxAge()+"</p>");
pw.println("</div>");
}
} else {
//说明没有cookie 需要清除浏览数据 ctrl+shift+delete
//1.负责向客户端写 cookie
//创建两个Cookie
Cookie c1 = new Cookie("_user","guyu");
//c1.setDomain("127.0.0.1");
//c1.setPath("/cookie");
//设置 Cookie 有效期其时长为 一分钟
//当第一次访问 http://127.0.0.1:10086/hs/cookie 时,等待60s后再点击查看 cookie 时
//此时 cookie 过期,request 会请求不到,反之60s内请求可查看其 cookie
c1.setMaxAge(60);
Cookie c2 = new Cookie("_pwd", "root");
//psd 密码有效期时长 30s
c2.setMaxAge(30);
//2.把这两个cookie写到客户端,添加到响应
resp.addCookie(c1);
resp.addCookie(c2);
//3.输出一个超链接,让用户查看cookie
pw.println("<h2 align=\"center\"><a href='"+
req.getContextPath()+"/cookie'>查看cookie</a></h2>");
}
//关闭
pw.close();
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
- 运行后在浏览器输入 http://127.0.0.1:10086/hs/cookie 时,响应头内会显示设置其 cookie 的所有数据如下图所示:
- 在其 30s 内点击查看 cookie 时 ,请求头内会显示其 cookie 的所有数据:
- 重运行后若在其 30s 后点击查看 cookie 时 ,请求头内只会显示其 第一个 cookie 的数据值,因为第二个 cookie 的数据值有效期为 30s:
重运行后反之若在其 60s 后点击查看 cookie 时 ,此时数据值都已失效。
注:
当客户端第一次请求来到服务端时,服务端会通过响应头把一小段信息写给客户端,
客户端以cookie的方式来存储这段信息。
Note:
欢迎点赞,留言,转载请在文章页面明显位置给出原文链接
知者,感谢您在茫茫人海中阅读了我的文章
没有个性 哪来的签名!
详情请关注点我
持续更新中
© 2020 10 - Guyu.com | 【版权所有 侵权必究】 |