技术标签: Java 学习笔记 学习 java javaweb 后端 java-ee
文章目录
- 视频及资料地址
- XML
- Tomcat
- Servlet
- JSP
- Listener 监听器
- EL 表达式
视频:【尚硅谷2020版JavaWeb全套教程,java web零基础入门完整版】
资料:【https://share.mowangblog.top/Courseware/JavaWeb】
xml 是可扩展的标记性语言。
1、用来保存数据,而且这些数据具有自我描述性
2、作为项目或者模块的配置文件
3、作为网络传输数据的格式(现在 JSON 为主)。
<?xml version="1.0" encoding="utf-8" ?>
<!-- xml文档声明 -->
version="1.0"
:version表示xml的版本号encoding="utf-8"
:encoding表示xml文件的编码格式xml的注释和html一样。
<!-- 这里的内容为注释内容 -->
xml元素指的是从开始标签(包括)到结束标签(包括)的部分。元素可以包含其他元素、文本或者两者混合,元素也可以拥有属性。
名称可以含字母、数字以及其他的字符
名称不能以数字或者标点符号开始
名称不能包含空格
双标签:
<books></books>
单标签:
<books />
xml 的标签属性和 html 的标签属性是非常类似的,属性可以提供元素的额外信息,一个标签上可以书写多个属性,每个属性的值必须使用引号引起来。
<books name="Java" price="9.9"></books>
所有 XML 元素都须有关闭标签(也就是闭合)
<root>
<book1></book1>
<book2 />
<!-- <book3>为闭合标签 -->
</root>
XML 标签对大小写敏感
XML 元素之间必须正确地嵌套
XML 文档必须有根元素。根元素就是顶级元素,没有父标签的元素,叫顶级元素。根元素是没有父标签的顶级元素,而且必须唯一。
XML 的属性值须加引号
XML 中需要显示特殊字符与html一样,如需要显示大于号,则使用>
CDATA 语法可以告诉 xml 解析器,CDATA 里的文本内容,只是纯文本,不需要 xml 语法解析,可以实现将输入的字符原样输出。
CDATA格式:
<root>
<![CDATA[
该区域可以将输入的字符原样输出,不会进行解析 <><><><><>
]]>
</root>
不管是 html 文件还是 xml 文件它们都是标记型文档,都可以使用 w3c 组织制定的 dom 技术来解析。使用 dom 技术进行解析,那么就会有 document 对象,document 对象表示的是整个文档(可以是 html 文档,也可以是 xml 文档)。
早期 JDK 提供了两种 xml 解析技术(已经过时):DOM 和 Sax。
第三方的解析:
1、jdom 在 dom 基础上进行了封装 。
2、dom4j 又对 jdom 进行了封装。
3、pull 主要用在 Android 手机开发,跟 sax 非常类似,都是使用事件机制解析 xml 文件。
这个 Dom4j 是第三方的解析技术。我们需要使用第三方给我们提供好的类库才可以解析 xml 文件。
Dom4j jar包加载为库:
需要进行解析的XML文件:
<?xml version="1.0" encoding="utf-8" ?>
<books>
<book sn="SN12341234">
<name>Java</name>
<price>9.9</price>
</book>
<book sn="SN12312312">
<name>Python</name>
<price>9.9</price>
</book>
</books>
相应的类对象:
package xmls;
public class Book {
private String sn;
private String name;
private double price;
public Book() {
}
public Book(String sn, String name, double price) {
this.sn = sn;
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Book{" + "sn='" + sn + '\'' + ", name='" + name + '\'' + ", price=" + price + '}';
}
public void setSn(String sn) {
this.sn = sn;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
public String getSn() {
return sn;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
解析XML文件:
package xmls;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;
public class Dom4jTest {
@Test
public void test1() throws Exception {
// 创建一个SaxReader输入流对象,读取xml文件
SAXReader saxReader = new SAXReader();
// 读取xml文件,生成Document对象
// Junit测试中,相对路径从模块名开始
Document document = saxReader.read("src\\xmls\\books.xml");
// System.out.println(document);
// 通过Document对象获取根元素
Element rootElement = document.getRootElement();
// 通过根元素获取book标签对象
// element() elements() 都是通过标签名查找子元素
List<Element> books = rootElement.elements("book");
for (Element book : books) {
// asXML() 将标签对象转换为标签字符串
// System.out.println(book.asXML());
// 获取子标签
Element name = book.element("name");
// getText() 获取标签中的文本内容
String nameText = name.getText();
// elementText() 直接获取指定标签名的文本内容
String priceText = book.elementText("price");
// attributeValue() 获取标签对象指定属性的属性值
String sn = book.attributeValue("sn");
Book book1 = new Book(sn, nameText, Double.parseDouble(priceText));
System.out.println(book1);
}
}
}
可以根据jdk的版本进行选择下载,我的jdk为1.8,tomcat8.0支持jdk1.7及以后,这边选择了tomcat8.5.84
下载完成后将下载的压缩包进行解压即可。
找到 Tomcat 目录下的 bin 目录下的 startup.bat 文件,双击,就可以启动 Tomcat 服务器。
打开浏览器,在浏览器地址栏中输入以下其中一个地址进行测试:
1、http://localhost:8080
2、http://127.0.0.1:8080
3、http://本机真实ip:8080
当出现如下界面,说明 Tomcat 服务器启动成功:
原因(一般情况):没有配置好 JAVA_HOME 环境变量
解决:配置 JAVA_HOME 环境变量
使用该方式启动tomcat服务器可以看到启动失败的错误信息。
在tomcat的bin目录下打开命令行,运行如下命令:
catalina run
Tomcat 默认的端口号是:8080
找到 Tomcat 目录下的 conf 目录,找到 server.xml 配置文件,在 server.xml 配置文件中找到 Connector 标签修改该标签的 port 属性值。
端口号的范围:1-65535,一般不要使用1000以内的端口号(一般已经被一些系统服务占用),注意,修改完端口号,需要重启Tomcat服务器才会生效。
只需要把 web 工程的目录拷贝到 Tomcat 的 webapps 目录下即可。
1、在 webapps 目录下创建一个工程目录:
2、网页内容拷贝到工程目录下:
<h1>HELLO WORLD</h1>
3、访问 Tomcat 下的 web 工程
http://ip:port
http://127.0.0.1:8080 表示访问到Tomcat目录下webapps目录
访问格式如下:
http://ip:port/工程名/目录下/文件名
访问刚刚部署的web工程:
http://127.0.0.1:8080/test/test.html
找到 Tomcat 下的 conf 目录\Catalina\localhost\ 下,创建如下的配置文件,一个配置文件对应一个web工程:
配置文件内容如下:
<!--
Context 表示一个工程上下文
path 表示工程的访问路径:/testabc (与配置文件名一致)
docBase 表示你的工程目录在哪里
-->
<Context path="/testabc" docBase="E:\testabc" />
注意配置文件的编码格式要为utf-8
重启Tomcat访问工程目录下的test.html文件:
http://127.0.0.1:8080/testabc/test.html
当我们在浏览器地址栏中输入访问地址如下:
http://ip:port/
没有工程名的时候,默认访问的是 ROOT 工程。
当我们在浏览器地址栏中输入的访问地址如下:
http://ip:port/工程名/
没有资源名,默认访问 index.html 页面
index.html
<h1>hello world</h1>
创建一个自己的类库:
index.jsp
1、编写一个类实现 Servlet 接口
2、实现 service 方法,处理请求,并响应数据
3、到 web.xml 中去配置 servlet 程序的访问地址
找不到Servlet类:
解决博客链接
HelloServlet.java
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
......
/**
* service方法用于处理请求和相应的方法
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("HelloServlet");
}
}
到 web.xml 中配置 servlet 程序的访问地址
<!-- servlet标签给Tomcat配置servlet程序 -->
<servlet>
<!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全类名-->
<servlet-class>HelloServlet</servlet-class>
</servlet>
<!--servlet-mapping 标签给 servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用-->
<servlet-name>HelloServlet</servlet-name>
<!--
url-pattern 标签配置访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
/hello 表示地址为:http://ip:port/工程路径/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
import javax.servlet.*;
import java.io.IOException;
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1.构造器被调用");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.初始化方法被调用");
}
@Override
public void destroy() {
System.out.println("4.destroy方法被调用");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3.service方法被调用");
}
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 类型转换(因为HttpServletRequest有 getMethod()方法)
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// 获取请求的方式
String method = httpServletRequest.getMethod();
if ("GET".equals(method)) {
System.out.println("GET");
} else if ("POST".equals(method)){
System.out.println("POST");
}
}
一般在实际项目开发中,都是使用继承 HttpServlet 类的方式实现 Servlet 程序。
1、编写一个类继承 HttpServlet 类
2、根据业务需要重写 doGet 或 doPost 方法
3、到 web.xml 中的配置 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 HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet2 doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HelloServlet2 doPost");
}
}
<servlet>
<servlet-name>HelloServlet2</servlet-name>
<servlet-class>HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class HelloServlet3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet3 doGet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet3 doPost");
}
}
<servlet>
<servlet-name>HelloServlet3</servlet-name>
<servlet-class>HelloServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet3</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
ServletConfig 类从类名上来看,是 Servlet 程序的配置信息类。ServletConfig 类对象中封装了Servlet 程序的配置信息,ServletConfig 类对象可以在 Servlet 程序初始化时使用。
Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对
象。
自己的Servlet类重写init方法,如果在后续的方法中需要使用ServletConfig 类对象,则需要调用
super.init(config)
方法保存ServletConfig 类对象。
1、可以获取 Servlet 程序的别名 servlet-name 的值
2、获取初始化参数 init-param
3、获取 ServletContext 对象
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
<!-- 初始化参数 是一个键值对 -->
<init-param>
<!-- 初始化参数名 -->
<param-name>username</param-name>
<!-- 初始化参数值 -->
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
@Override
public void init(ServletConfig servletConfig) throws ServletException {
// System.out.println("2.初始化方法被调用");
// 1、可以获取 Servlet 程序的别名 servlet-name 的值
System.out.println("Servlet 程序的别名: " + servletConfig.getServletName());
// 2、获取初始化参数 init-param
System.out.println("初始化参数username的值: " + servletConfig.getInitParameter("username"));
System.out.println("初始化参数password的值: " + servletConfig.getInitParameter("password"));
// 3、获取 ServletContext 对象
System.out.println("ServletContext 对象" + servletConfig.getServletContext());
}
1、ServletContext 是一个接口,它表示 Servlet 上下文对象
2、一个 web 工程,只有一个 ServletContext 对象实例。
3、ServletContext 对象是一个域对象。
4、ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。
<web-app ... >
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
<param-name>password</param-name>
<param-value>root</param-value>
</context-param>
...
<servlet>
<servlet-name>ContextServlet</servlet-name>
<servlet-class>ContextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ContextServlet</servlet-name>
<url-pattern>/context</url-pattern>
</servlet-mapping>
</web-app>
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取ServletContext对象
ServletContext servletContext = getServletContext();
//- 1、获取 web.xml 中配置的上下文参数 context-param
System.out.println("contest-param username: " + servletContext.getInitParameter("username"));
System.out.println("contest-param password: " + servletContext.getInitParameter("password"));
//- 2、获取当前的工程路径,格式: /工程路径
System.out.println("当前工程路径: " + servletContext.getContextPath());
//- 3、获取工程部署后在服务器硬盘上的绝对路径
// / 斜杠被服务器解析地址为:http://ip:port/工程名/ 映射到 IDEA 代码的 web 目录
System.out.println("工程部署后在服务器硬盘上的绝对路径" + servletContext.getRealPath("/"));
System.out.println("工程下WEB-INF目录在服务器硬盘上的绝对路径" + servletContext.getRealPath("/WEB-INF"));
//- 4、像 Map 一样存取数据
System.out.println("数据保存前获取" + servletContext.getAttribute("key1"));
servletContext.setAttribute("key1", "value1");
System.out.println("数据保存后获取" + servletContext.getAttribute("key1"));
}
协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。所谓 HTTP 协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。HTTP 协议中的数据又叫报文。
客户端给服务器发送数据叫请求。服务器给客户端回传数据叫响应。
MIME 是 HTTP 协议中数据类型。MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。
MIME 类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应。
常见的 MIME 类型:
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的HTTP 协议信息解析好封装到 Request 对象中。然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//- getRequestURI() 获取请求的资源路径
System.out.println("URI =>" + request.getRequestURI());
//- getRequestURL() 获取请求的统一资源定位符(绝对路径)
System.out.println("URL =>" + request.getRequestURL());
//- getRemoteHost() 获取客户端的 ip 地址
// 使用localhost访问得到的客户端IP地址为127.0.0.1
// 使用127.0.0.1访问得到的客户端IP地址为127.0.0.1
// 使用服务器真实的IP访问得到的客户端IP地址为真实的客户端IP
System.out.println("客户端 IP =>" + request.getRemoteHost());
//- getHeader() 获取请求头
System.out.println("请求头 User-Agent =>" + request.getHeader("User-Agent"));
//- getMethod() 获取请求的方式 GET 或 POST
System.out.println("请求方式 =>" + request.getMethod());
// 设置请求体的字符集为UTF-8防止获取Post请求参数时中文乱码问题
// 获取请求参数前调用才有效
request.setCharacterEncoding("UTF-8");
//- getParameter() 获取请求的参数
System.out.println("请求参数 username =>" + request.getParameter("username"));
//- getParameterValues() 获取请求的参数(获取的请求参数有多个值的时候使用)
System.out.println("请求参数 =>" + request.getParameterValues("hobby").toString());
}
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求的参数(办事的材料)查看
String username = request.getParameter("username");
System.out.println("在 Servlet1(柜台 1)中查看参数(材料):" + username);
// 给材料 盖一个章,并传递到 Servlet2(柜台 2)去查看
// 设置一个域数据
request.setAttribute("key1", "柜台 1 的章");
// 问路:Servlet2(柜台 2)怎么走
// 获取到Servlet2的请求转发路径
// 请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到 IDEA 代码的 web 目录
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.baidu.com");
// 走向 Sevlet2(柜台 2)
// 并将请求对象和响应对象传递过去
requestDispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取请求的参数(办事的材料)查看
String username = request.getParameter("username");
System.out.println("在 Servlet2(柜台 2)中查看参数(材料):" + username);
// 查看 柜台 1 是否有盖章
Object key1 = request.getAttribute("key1");
System.out.println("柜台 1 是否有章:" + key1);
// 处理自己的业务
System.out.println("Servlet2 处理自己的业务 ");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
base 标签可以设置页面相对路径工作时,参照哪个路径进行跳转。
在页面进行跳转时会先看页面中是否有base标签,如果页面中设置了base标签,则页面进行跳转会参照base标签href属性中的地址进行跳转。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
base 标签设置页面相对路径工作时参照的地址
href 属性就是参数的地址值
地址中的资源文件可以省略,但是最后的 / 不能省略,有 / 才表示b/是一层目录
-->
<base href="http://localhost:8080/07_servlet/a/b/">
</head>
<body>
这是 a 下的 b 下的 c.html 页面<br/>
<a href="../../index.html">跳回首页</a><br/>
</body>
</html>
在 web 中 / 斜杠 是一种绝对路径。
/ 斜杠 如果被浏览器解析,得到的地址是:http://ip:port/
<a href="/">斜杠</a>
/ 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径
<url-pattern>/servlet1</url-pattern>中的 /
servletContext.getRealPath(“/”);
request.getRequestDispatcher(“/”);
特殊情况: response.sendRediect(“/”);
(请求重定向) 把斜杠发送给浏览器解析。得到 http://ip:port/
HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用。
HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置。
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取字符流
PrintWriter writer = response.getWriter();
// 向客户端传递字符串数据
writer.write("服务端回传的字符串数据");
}
响应字符的默认编码为ISO-8859-1
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 响应字符的默认编码
System.out.println(response.getCharacterEncoding());
// 获取字符流
PrintWriter writer = response.getWriter();
// 向客户端传递字符串数据
writer.write("服务端回传的字符串数据");
}
解决响应中文乱码方案一(不推荐使用):
// 设置服务器字符集为 UTF-8
resp.setCharacterEncoding("UTF-8");
// 通过响应头,设置浏览器也使用 UTF-8 字符集
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
解决响应中文乱码方案二(推荐):
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 响应字符的默认编码
System.out.println(response.getCharacterEncoding());
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
response.setContentType("text/html; charset=UTF-8");
System.out.println(response.getCharacterEncoding());
// 获取字符流
PrintWriter writer = response.getWriter();
// 向客户端传递字符串数据
writer.write("服务端回传的字符串数据");
}
请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)。
请求重定向的第一种方案:
// 设置响应状态码 302 ,表示重定向,(已搬迁)
response.setStatus(302);
// 设置响应头,说明 新的地址在哪里
response.setHeader("Location", "http://localhost:8080/JavaWeb01_war_exploded/servlet2");
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("访问Servlet1");
// 设置响应状态码 302 ,表示重定向,(已搬迁)
response.setStatus(302);
// 设置响应头,说明 新的地址在哪里
response.setHeader("Location", "http://localhost:8080/JavaWeb01_war_exploded/servlet2");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("访问Servlet2");
// 设置编码
response.setContentType("text/html; charset=UTF-8");
// 响应数据
response.getWriter().write("当前访问的为Servlet2");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
请求重定向的第二种方案(推荐使用):
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("访问Servlet1");
// 设置响应状态码 302 ,表示重定向,(已搬迁)
// response.setStatus(302);
// 设置响应头,说明 新的地址在哪里
// response.setHeader("Location", "http://localhost:8080/JavaWeb01_war_exploded/servlet2");
response.sendRedirect("http://localhost:8080/JavaWeb01_war_exploded/servlet2");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
jsp 的全称是 java server pages。Java 的服务器页面。
jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据。
因为 Servlet 程序回传 html 页面数据是一件非常繁锁的事情。开发成本和维护成本都极高。
public class PringHtml extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
// 通过响应的回传流回传 html 页面数据
// 设置编码格式
resp.setContentType("text/html; charset=UTF-8");
// 获取响应流
PrintWriter writer = resp.getWriter();
// 向浏览器回传响应html页面
writer.write("<!DOCTYPE html>\r\n");
writer.write(" <html lang=\"en\">\r\n");
writer.write(" <head>\r\n");
writer.write(" <meta charset=\"UTF-8\">\r\n");
writer.write(" <title>Title</title>\r\n");
writer.write(" </head>\r\n");
writer.write(" <body>\r\n");
writer.write(" 这是 html 页面数据 \r\n");
writer.write(" </body>\r\n");
writer.write("</html>\r\n");
writer.write("\r\n");
}
}
jsp 页面和 html 页面一样,都是存放在 web 目录下。访问也跟访问 html 页面一样。web 目录下,a.html 页面访问地址是 http://ip:port/工程路径/a.html;b.jsp 页面访问地址是 http://ip:port/工程路径/b.jsp。
jsp 页面本质上是一个 Servlet 程序。当我们第一次访问 jsp 页面的时候。Tomcat 服务器会帮我们把 jsp 页面翻译成为一个 java 源文件。并且对它进行编译成为.class 字节码程序。jsp 翻译出来的 java 类,它间接了继
承了 HttpServlet 类。也就是说,翻译出来的是一个 Servlet 程序。
jsp 翻译出来的 java 类,其底层实现,也是通过输出流,把 html 页面数据回传给客户端。
jsp 的 page 指令可以修改 jsp 页面中一些重要的属性,或者行为。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
language 属性:表示 jsp 翻译后是什么语言文件,暂时只支持 java。
contentType 属性:表示 jsp 返回的数据类型是什么,也是源码中response.setContentType()参数值
pageEncoding 属性:表示当前 jsp 页面文件本身的字符集。
import 属性:跟 java 源代码中一样,用于导包,导类。
autoFlush 属性:该属性是给 out 输出流使用,设置当 out 输出流缓冲区满了之后,是否自动刷新缓冲区。默认值是 true。
buffer 属性:该属性是给 out 输出流使用,设置 out 缓冲区的大小。默认是 8kb
errorPage 属性:设置当 jsp 页面运行时出错,自动跳转去的错误页面路径。这个路径一般都是以斜杠打头,它表示请求地址为 http://ip:port/工程路径/,(斜杠由服务器解析)映射到代码的 Web 目录。
isErrorPage 属性:设置当前 jsp 页面是否是错误信息页面。默认是 false。如果是 true 可以获取异常信息。
session 属性:设置访问当前 jsp 页面,是否会创建 HttpSession 对象。默认是 true。
extends 属性:设置 jsp 翻译出来的 java 类默认继承谁。
<%! 声明 java 代码 %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %><%--
Created by IntelliJ IDEA.
User: cw
Date: 2023-01-01
Time: 17:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>HELLO WORLD!!!</h1>
<%--1、声明类属性--%>
<%!
private Integer id;
private String name;
private static Map<String, Object> map;
%>
<%--2、声明 static 静态代码块--%>
<%!
static {
map = new HashMap<String, Object>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
}
%>
<%--3、声明类方法--%>
<%!
public int abc() {
return 12;
}
%>
<%--4、声明内部类--%>
<%!
public static class A {
private Integer id = 12;
private String abc = "abc";
}
%>
</body>
</html>
声明脚本代码翻译对照:
<%= 表达式 %>
1、所有的表达式脚本都会被翻译到_jspService() 方法中
2、表达式脚本都会被翻译成为 out.print()输出到页面上
3、由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用。
4、表达式脚本中的表达式不能以分号结束。
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %><%--
Created by IntelliJ IDEA.
User: cw
Date: 2023-01-01
Time: 17:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>HELLO WORLD!!!</h1>
<%!
private Integer id;
private String name;
private static Map<String, Object> map;
%>
<%!
static {
map = new HashMap<String, Object>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
}
%>
<!-- 表达式脚本 -->
<%= 12 %> <br>
<%= 12.12 %> <br>
<%= "我是字符串" %> <br>
<%= map %> <br>
<%= request.getParameter("username") %>
</body>
</html>
翻译对照:
<%
java 语句
%>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %><%--
Created by IntelliJ IDEA.
User: cw
Date: 2023-01-01
Time: 17:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%--1.代码脚本----if 语句--%>
<%
int i = 13;
if (i == 12) {
%>
<h1>Hello</h1>
<%
} else {
%>
<h1>World</h1>
<%
}
%>
<br>
<%--2.代码脚本----for 循环语句--%>
<table border="1" cellspacing="0">
<%
for (int j = 0; j < 10; j++) {
%>
<tr>
<td>第 <%=j + 1%>行</td>
</tr>
<%
}
%>
</table>
<%--3.翻译后 java 文件中_jspService 方法内的代码都可以写--%>
<%
String username = request.getParameter("username");
System.out.println("用户名的请求参数值是:" + username);
%>
</body>
</html>
html 注释:
<!-- 这是 html 注释 -->
java 注释:
<%
// 单行 java 注释
/* 多行 java 注释 */
%>
jsp 注释
<%-- 这是 jsp 注释 --%>
jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。
<%@ include file=""%>
,file 属性指定你要包含的 jsp 页面的路径,地址中第一个斜杠 / 表示为 http://ip:port/工程路径/ 映射到代码的 web 目录。<jsp:include page=""></jsp:include>
,page 属性是指定你要包含的 jsp 页面的路径JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
<jsp:include page="/include/footer.jsp">
<jsp:param name="username" value="bbj"/>
<jsp:param name="password" value="root"/>
</jsp:include>
// 获取传递的参数
request.getParameter("参数的name")
语法:<jsp:forward page=""></jsp:forward>
,是请求转发标签,它的功能就是请求转发,page 属性设置请求转发的路径。
<jsp:forward page="/scope2.jsp"></jsp:forward>
客户端浏览器将请求发给servlet程序,servlet程序进行相应的数据处理,将数据保存在request域中给jsp页面,然后再请求转发给jsp页面,jsp页面从request域中取出数据展示到页面上。
servlet程序用于数据处理,jsp页面用于数据的展示。
public class MyServletContextListenerImpl implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext 对象被创建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext 对象被销毁了");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
<!--配置监听器-->
<listener>
<listener-class>MyServletContextListenerImpl</listener-class>
</listener>
...
</web-app>
${表达式}
<body>
<%
// 向request域中存储数据
request.setAttribute("key","value");
Object num = null;
%>
<%=num%><br/>
${num}<br/>
表达式脚本输出 key 的值是:
<%=request.getAttribute("key")==null?"":request.getAttribute("key")%><br/>
<!--EL表达式取出request域中的数据直接使用键名即可-->
EL 表达式输出 key 的值是:${key}
</body>
<%
//往四个域中都保存了相同的 key 的数据。
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
<p>key:${
key}</p>
文章浏览阅读1k次。需要注意的是如果要从后端获取文件名,需要res.headers["content-disposition"]去获取并处理,前提是先检查前端axios请求拦截器是否进行了相应的拦截处理并且后端header头部加上。题外话:如果通过a标签和location.href直接访问请求链接(?xx=可带参),浏览器会直接下载对应的文件,但无法处理节流问题,所以需要异步请求来实现需求。补充:如果遇到跨域问题,如有reset(),请在reset之后添加以下Header。_后端二进制文件流 下载
文章浏览阅读8.3k次。 Java游戏服务器开发之十四--在handler和dao层中添加service层现在我们的写法是将dao注入到handler中,如果遇到要写业务逻辑的话,其实不是太方便,所以我们在handler和dao层中添加service层这样dao的所有接口都只暴露给service,整个的数据流向就是handler--service--dao主要变化是:添加 UserService/UserSe..._handler.newuserservice
文章浏览阅读7.7w次,点赞7次,收藏56次。使用Docker来安装Home-Assistant前提:目的明确,了解Home-Assistant是什么东西你的机子已经安装了 Docker该教程只是作者的操作记录,希望能帮到你。查找镜像docker search home-assistant可以看到上图中被圈起来且排在第一的 homeassistant/home-assistants 它的星标最多,虽然写着不是官方的,但是...
文章浏览阅读1.3k次。【摘要】在这个科学技术高速发展的时代,越来越多的人都开始选择学习编程软件,那么首先被大家选择的编程软件就是python,也用在各行各业之中,并被大家所熟知,所以也有越来越多的python学习者关注python的问题,今天环球网校的小编就来和大家讲讲Python if else对缩进的要求。Python 是以缩进来标记代码块的,代码块一定要有缩进,没有缩进的不是代码块。另外,同一个代码块的缩进量要相..._在python中if语句的下一句一定要缩进
文章浏览阅读389次,点赞7次,收藏4次。所谓交叉编译指的是能够在一个平台(例如x86)编译并构建二进制文件,而在另一个平台(例如ARM)运行。编译二进制文件的机器称为主机(host),而运行生成的二进制文件的平台称为目标平台(target)。为相同平台(主机与目标机器相同)编译代码称为本机编译(native assembler),而当主机与目标机器为不同平台时编译代码称为交叉编译(cross-compiler)。本文会讲述LLVM交叉编译的技术,可以为主机平台不同的平台编译LLVM,因此能够在所需要的特定目标平台使用构建的二进制文件。_llvm交叉编译
文章浏览阅读1.6k次。毕业设计-基于深度学习的时间序列预测方法:时间序列是一种广泛存在于现实各领域之中的海量高维数据, 时间序列预测是该领域的一个研究重点. 传统的时间序列预测方法仅仅从时间的维度对时间序列进行分析,忽略了外界影响因素对时间序列可能产生的影响. 针对传统时间序列预测方法存在的问题, 提出一种基于深度学习的时间序列预测模型 DAFDC-RNN (dual-stage attention and full dimension convolution based recurrent neural network).为_深度学习的时间序列预测方法
文章浏览阅读127次。文件名称: MyRobot下载 收藏√ [5 4 3 2 1]开发工具: Java文件大小: 120 KB上传时间: 2016-12-31下载次数: 0提 供 者: zen详细说明:在机器人软件平台上建立一个包含若干个静止障碍物和运动障碍物的仿真环境,设定机器人的起始点和终点后,机器人能够规划出一条从起始点到目标点的安全路径。查阅相关路径规划算法,实现一种以上算法并相互比较。要求给..._机器人障碍翻越代码
文章浏览阅读1k次。这是为了(也许)成为MetaTrader 4/5及其相应语言MQL4的指导性文章,它们都设置为上下文,并将数据发送到外部服务器。在在我的特殊情况下,我正在构建一个基于Django/Python的web应用程序,它将处理外汇交易数据以供进一步使用。在因此,我正在寻找一个合适的解决方案,将数据从MetaTrader 4/5终端定期(例如每60秒)发送到外部服务器,格式为json或{}(如果可能的话)。..._mql4 webrequest
文章浏览阅读4.1k次,点赞9次,收藏21次。enumerate(sequence, [start = 0])python内置的enumerate函数将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。sequence: 序列、迭代器或者其他支持迭代的对象start: 下标起始位置for循环和enumerate结合使用>>>seq = ['one', 'two', 'three']>>> for i, element in enumer_np.ndenumerate
文章浏览阅读2.2k次。NFC手机一枚Root ExplorerNFC Taginfo方法/步骤1,读取卡的ID。安装“NFC TagInfo”,打开手机的NFC设置,门禁卡贴到手机后盖NFC部分,“NFC TagInfo”读取校园卡ID。可以看到我的卡ID是13:67:A9:0A修改手机NFC的ID。打开R.E.管理器,根目录-->etc,找到etc文件夹中的“libnfc-nxp.conf”(如果没找到,就全盘..._门禁文件如何导入手机
文章浏览阅读90次。Windows操作系统相比Linux操作系统,必须要先安装了ipmitool驱动的情况下才能不带IBMC的IP、用户名和密码的情况下执行ipmitool的相关命令,所以Windows操作系统在忘记IBMC的用户名、密码或者IP的情况下必须先安装ipmitool驱动包。3) 查看BMC用户信息,使用命令“ipmitool user list 1”或者"ipmitool user list 0xe"(仅支持1和0xe通道)2) 查看BMC配置信息,使用命令“ipmitool lan print”。_带内获取bmc用户名密码
文章浏览阅读607次,点赞22次,收藏5次。备注软件测试)**[外链图片转存中…(img-wlLhHX93-1712680136534)]