一、Servlet入门
参考资源:
https://www.cnblogs.com/whgk/p/6399262.html
https://www.runoob.com/servlet/servlet-tutorial.html
https://www.kuangstudy.com/bbs/1460111518577258498#header32
1、简介
servlet是sun公司开发动态web的一门技术。
开发servlet程序步骤:
编写一个直接或间接实现servlet接口的Java类;
写好Java类之后,把Java类部署到web服务器中。
我们把直接或间接实现了servlet接口的Java程序叫servlet。
百度:
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
2、编写Hello Servlet案例
1、创建一个普通的maven项目,删除src目录
2、在普通的maven项目的pom.xml中导入依赖
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
dependencies>
3、在普通maven项目目录下建立mavenweb模块
父子maven项目对比
父项目(普通maven项目)中有:
子项目(mavenweb模块)中有:
子项目可以使用父项目的jar包
4、子项目操作
更换web.xml
更新内容如下
version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
web-app>
添加Java、resources目录
5、编写servlet程序
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//响应的类型:html
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
//获取响应的输出流 resp.getOutputStream();(字节流) /resp.getWriter();(字符流)
PrintWriter out = resp.getWriter();
out.println("");
out.println("");
out.println("你好");
out.println("");
out.println("");
out.println("
你好
");
out.println("");
out.println("");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
在子项目的web.xml中编写servlet映射
为什么需要映射?
我们写的servlet程序,要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的servlet,还要给浏览器一个访问路径。
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hellourl-pattern>
servlet-mapping>
配置tomcat,启动...
3、servlet运行原理
servlet是由web服务器调用,web服务器在收到浏览器请求后,会:
4、tomcat和servlet的关系
Tomcat 是Web应用服务器,是一个Servlet/JSP容器. Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户.而Servlet是一种运行在支持Java语言的服务器上的组件. Servlet最常见的用途是扩展Java Web服务器功能,提供非常安全的,可移植的,易于使用的CGI替代品.
从http协议中的请求和响应可以得知,浏览器发出的请求是一个请求文本,而浏览器接收到的也应该是一个响应文本。但是在上面这个图中,并不知道是如何转变的,只知道浏览器发送过来的请求也就是request,我们响应回去的就用response。忽略了其中的细节,现在就来探究一下。
①:Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到。
②:Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器
Java Servlet API 是Servlet容器(tomcat)和servlet之间的接口,它定义了serlvet的各种方法,还定义了Servlet容器传送给Servlet的对象类,其中最重要的就是ServletRequest和ServletResponse。所以说我们在编写servlet时,需要实现Servlet接口,按照其规范进行操作。
5、servlet-mapping
一个servlet指定一个映射路径:
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello1url-pattern>
servlet-mapping>
一个servlet指定多个映射路径:
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello1url-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello2url-pattern>
servlet-mapping>
一个servlet指定通用映射路径:
<servlet>
<servlet-name>helloservlet-name>
<servlet-class>HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>helloservlet-name>
<url-pattern>/hello/*url-pattern>
servlet-mapping>
默认请求路径:
hello
HelloServlet
hello
/*
自定义后缀实现请求映射路径:
hello
HelloServlet
hello
*.libaizhi
指定了固有的映射路径优先级最高,如果找不到就会走默认的映射请求路径:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class ErrorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//响应的类型:html
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
//获取响应的输出流 resp.getOutputStream();(字节流) /resp.getWriter();(字符流)
PrintWriter out = resp.getWriter();
out.println("");
out.println("");
out.println("你好");
out.println("");
out.println("");
out.println("
404
");
out.println("");
out.println("");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
helloServlet
HelloServlet
helloServlet
/lbzlwz
errorServlet
ErrorServlet
errorServlet
/*
二、ServletContext
参考文章
https://www.jianshu.com/p/31d27181d542
https://blog.csdn.net/qq_36371449/article/details/80314024
https://www.kuangstudy.com/bbs/1460111518577258498#header28
1、ServletContext(接口)
说起ServletContext,一些人会产生误解,以为一个servlet对应一个ServletContext。其实不是这样的,事实是一个web应用对应一个ServletContext,所以ServletContext的作用范围是整个应用,明确这点很重要,这是基础中的基础。
一个web应用对应一个ServletContext实例,这个实例是应用部署启动后,servlet容器为应用创建的。ServletContext实例包含了所有servlet共享的资源信息。通过提供一组方法给servlet使用,用来和servlet容器通讯,比如获取文件的MIME类型、分发请求、记录日志等。
这里需要注意一点,如果你的应用是分布式部署的,那么每台服务器实例上部署的应用实例都各自拥有一个ServletContext实例。
2、共享数据
1、 域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据。
2、域对象都有如下3个方法:
void setAttribute(String var1, Object var2) | 往域对象里面添加数据,添加时以key-value形式添加 |
Object getAttribute(String var1) | 根据指定的key读取域对象里面的数据 |
void removeAttribute(String var1) | 根据指定的key从域对象里面删除数据 |
3、向ServletContext添加数据
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class SetData extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name","萧瑟");
servletContext.setAttribute("age","18");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
4、向ServletContext获取数据
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class GetData extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = (String)servletContext.getAttribute("name");
String age = (String)servletContext.getAttribute("age");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print(name+":"+age+"岁");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3、获取初始化参数
1、配置初始化参数(在web.xml中配置)
lover
李柏芝
2、通过ServletContet对象的getInitParameter()方法获取初始化参数
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 ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String lover = servletContext.getInitParameter("lover");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.getWriter().print("我爱的人-->"+lover);
}
}
4、请求转发
1、getRequestDispatcher()方法和getNamedDispatcher()方法
将指定的资源包装成RequestDispatcher实例并返回。区别是前者根据资源路径(该路径相对于当前应用上下文根),后者根据资源的名称(通过服务器控制台或者web.xml里面配置的,比如web.xml里面配置servlet的名称)。 RequestDispatcher这个接口,看名字就知道主要用来进行分发的。所有的资源都可以包装成RequestDispatcher实例(主要是用于包装servlet),然后调用它的方法进行转发和包含。这里比较简单,不过过多赘述,直接上源码。(这里只列关键的两个方法,简单介绍下forward。如有兴趣深入,可自行去研究RequestDispatcher相关知识)
public interface RequestDispatcher {
public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException;
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException;
}
2、实现请求转发
被请求的servlet:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class DispatchServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.getWriter().print("我希望你快乐!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
请求的servlet:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class DispatchServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//RequestDispatcher dispatch = servletContext.getRequestDispatcher("dispatch1");//转发地址
//dispatch.forward(req,resp);//调用forward实现转发
servletContext.getRequestDispatcher("/dispatch1").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5、读取配置文件
1、Properties类
https://www.cnblogs.com/bakari/p/3562244.html
2、新建properties文件
username=root
password=123456
1、在Java目录下新建properties文件
发现的问题:
启动tomcat后,这个文件没有保存到web应用中
解决方案:
在当前web应用的pom.xml导入:
src/main/resources
**/*.properties
**/*.xml
true
src/main/java
**/*.properties
**/*.xml
true
2、在resources目录下新建properties文件
启动tomcat后,这个文件保存到web应用中
保存的路径:/WEB-INF/classes(我们俗称这个路径为classpath)
3、读取配置文件
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.Properties;
public class PropertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/test.properties");
//this.getServletContext().getResourceAsStream(path),根据相对路径获取服务器上资源的输入字节流
//把资源变成流:"/"代表test01(web应用)
Properties prop = new Properties();
prop.load(is);
//oad ( InputStream inStream),从输入流中读取属性列表(键和元素对)。
String username = prop.getProperty("username");
// getProperty ( String key),用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
String password = prop.getProperty("password");
resp.getWriter().print(username);
resp.getWriter().print(password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}