Servlet基础
1.1.名词解释
-
Web应用、HTTP服务器、Web应用服务器
Web应用被称为Web Application,通过浏览器访问的应用程序,从而为用户提供相关的服务,例如查询、购物等;淘宝,途牛旅游等提供服务的网站;也包含很多公司内部使用的软件,如oa系统,医院内使用的系统,企业内部业务管理系统等;
-
HTTP服务器:也称为Web服务器,主要功能是提供网上信息浏览服务,例如Apache、Nginx、IIS是比较常用的HTTP服务器;使用浏览器访问Web站点或者Web应用,则必须通过HTTP服务器;
-
Web应用服务器:Web应用服务器能够运行服务器上的应用程序,并将结果返回给客户端浏览器;例如,Tomcat就是一种Web应用服务器;通常情况下,Web应用服务器兼具HTTP服务器的部分功能;
1.2.Tomcat安装使用
-
直接解压到本地文件夹
-
如何启动,解压文件夹 下面的 bin/ 目录下 执行startup.bat
startup.bat
-
停止tomcat shutdown.bat
-
使用浏览器进行访问 http://127.0.0.1:8080
-
端口号的更改在conf/server.xml中 修改后需要重启
1.3.请求体和响应体
1.请求
// 请求行
GET http://localhost:8080/server1/index.html
//以下是请求头
HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36
x-ijt: v5m5qoph3mu1pt6sfo99rqeljt
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
2.响应
//响应行
HTTP/1.1 200
//响应头
Accept-Ranges: bytes
ETag: W/"143-1612149278066"
Last-Modified: Mon, 01 Feb 2021 03:14:38 GMT
Content-Type: text/html
Content-Length: 143
Date: Mon, 01 Feb 2021 07:05:08 GMT
//响应体,响应体和响应头之间有空行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello world
</body>
</html>
1.4.Servlet
- Servlet是JavaEE规范中的Web开发组件;
自定义servlet步骤
1.定义一个类去继承HttpServlet,重写doGet和doPost方法
public class CustomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("处理一个get请求");
}
}
2.配置web.xml文件
<?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">
<servlet>
<servlet-name>cus</servlet-name>
<!-- 类的全路径-->
<servlet-class>com.qy28.sm.CustomServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cus</servlet-name>
<!-- 映射的URL路径 -->
<url-pattern>/test</url-pattern>
</servlet-mapping>
</web-app>
3.发请求进行测试
http://localhost:8080/server1/test
4.给servlet配置多个请求路径,CustomServlet可以处理/test和 /a请求
<servlet>
<servlet-name>cus</servlet-name>
<!-- 类的全路径-->
<servlet-class>com.qy28.sm.CustomServlet</servlet-class>
</servlet>
<!-- 一个servlet类配置多个映射路径 -->
<servlet-mapping>
<servlet-name>cus</servlet-name>
<!-- 映射的URL路径 路径带有正斜杠 aaa-->
<url-pattern>/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cus</servlet-name>
<!-- 映射的URL路径 路径带有正斜杠 aaa-->
<url-pattern>/a</url-pattern>
</servlet-mapping>
1.5.状态码
- “2XX” 凡是2开头的都是成功 200
- “4XX” 都表示客户端问题 ,401 403 404 405
- “5XX” 都表示服务的问题,内部出错 , 502:网关错误
- “3XX” 资源重定向问题
1.6.servlet生命周期
- servlet会经历几个时期,构造了(构造方法)=》初始化了(init方法)-》提供服务(service方法)=》销毁了(destroy方法)
- 默认情况下,是在第一次访问的时候 执行构造和初始化并且这两个方法只会执行一次
- 每次请求的时候会访问service方法
- 应用卸载或者tomcat关闭的时候执行destroy方法
public class CustomServlet extends HttpServlet {
public CustomServlet() {
System.out.println("构造方法调用了");
}
@Override
public void init() throws ServletException {
System.out.println("servlet初始化了");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("接受所有类型请求的");
}
@Override
public void destroy() {
System.out.println("servlet 被销毁了");
}
}
1.7.登录案例
- 登录页面
<body>
<form action="/server1/auth">
user: <input type="text" name="username"> <br>
pass: <input type="password" name="password"> <br>
<input type="submit" value="提交">
</form>
</body>
- servlet代码
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("收到请求了");
String user = req.getParameter("username");
String pass = req.getParameter("password");
System.out.println(user + " : " + pass);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
- web.xml配置 LoginServlet
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.qy28.sm.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/auth</url-pattern>
</servlet-mapping>
Servlet进阶
1.1.Get和Post的区别
- Get用于向服务器获取资源信息,Post常用于向服务器提交数据
- Get的参数拼接在URL路径中(使用与URL路径隔开,&进行拼接),Post的请求参数在请求体中比Get相对安全
- Get的请求数据大小有限制,对URL长度有限制,不能超过2KB,Post默认情况下无限制
1.2.Servlet的其他配置信息
1.2.1.Servlet初始化参数
- 是给servlet配置的,其他servlet获取不到
1.web.xml的配置
<servlet>
<servlet-name>cus3</servlet-name>
<servlet-class>com.qy28.sm.CusServlet3</servlet-class>
<init-param>
<!-- 初始化参数 key:value -->
<param-name>jdbcUrl</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>cus3</servlet-name>
<url-pattern>/cus3</url-pattern>
</servlet-mapping>
2.servlet代码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get request");
//获取servlet中的初始化参数
System.out.println(getInitParameter("jdbcUrl"));
}
1.2.2.上下文参数
- 在所有的servlet中都可以获取到
1,web.xml配置
<!--上下文参数的配置 -->
<context-param>
<param-name>para</param-name>
<param-value>tom</param-value>
</context-param>
2,sevlet代码
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("收到请求了");
//获取servlet中的初始化参数
System.out.println(getInitParameter("jdbcUrl"));
// 获取上下文 参数
System.out.println(getServletContext().getInitParameter("para"));
}
1.2.3.启动加载配置
- load-on-startup默认是个负数,该servlet会在第一次请求过来的时候进行实例化和初始化,配置为1之后表示在应用部署完成后就进行实例化和初始化
1.web.xml配置
<servlet>
<servlet-name>cus3</servlet-name>
<servlet-class>com.qy28.sm.CusServlet3</servlet-class>
<init-param>
<!-- servlet 初始化参数 key:value -->
<param-name>jdbcUrl</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</init-param>
<!-- 启动加载 配置 -->
<load-on-startup>1</load-on-startup>
</servlet>
1.3. 乱码处理(请求/响应乱码)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("收到请求了");
// 请求设置编码格式
req.setCharacterEncoding("UTF-8");
//给响应头设置编码格式 数据格式和编码格式
resp.setContentType("text/html;charset=UTF-8");
String user = req.getParameter("username");
String pass = req.getParameter("password");
System.out.println(user + " : " + pass);
resp.getWriter().write("<h1>hello你好</h1>");
}
1.4.使用注解配置servlet
XML: 松耦合配置
注解:强耦合 ,但是更简洁
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
//配置servlet名字
String name() default "";
// value()和urlPatterns()是等价的,都是路径配置
String[] value() default {};
String[] urlPatterns() default {};
//配置启动加载参数
int loadOnStartup() default -1;
// 配置初始化参数
WebInitParam[] initParams() default {};
boolean asyncSupported() default false;
String smallIcon() default "";
String largeIcon() default "";
String description() default "";
String displayName() default "";
}
servlet代码
@WebServlet(name = "LoginServlet", value = {"/auth", "/auth2"}, loadOnStartup = 1, initParams = {@WebInitParam(name = "jdbc",value ="jdbc:mysql")})
//@WebServlet("/auth")
public class LoginServlet extends HttpServlet {
public LoginServlet() {
System.out.println("login构造了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("收到请求了");
/* //获取servlet中的初始化参数
System.out.println(getInitParameter("jdbcUrl"));
// 获取上下文 参数
System.out.println(getServletContext().getInitParameter("para"));*/
System.out.println(getInitParameter("jdbc"));
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
String user = req.getParameter("username");
String pass = req.getParameter("password");
System.out.println(user + " : " + pass);
resp.getWriter().write("<h1>hello你好</h1>");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
1.5.servlet多线程问题
- 每个请求过来,tomcat都会有个线程进行处理,本次请求结束后线程任务完成;
- servlet是单实例的,尽量不要有成员变量,防止多线程间共享成员变量线程安全问题
servlet代码验证
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("收到请求了");
//当前线程id
System.out.println(Thread.currentThread().getId());
//当前线程休眠10秒
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
1.6.域对象
- 用来存储信息,数据传递
1.request 对象
每次请求都会产生要给request,请求结束后消失
2.session
同一个用户(会话)一个session对象,当浏览器关闭或者session过期,session对象消失
3.ServletContext
整个应用期间只有一个对象,应用部署好就会生成,应用卸载(服务器关闭)消失
1.7.Servlet相关类
1.7.1.ServletContext上下文类
- 整个应用期间只有一个上下文对象,应用部署好就会生成,应用卸载(服务器关闭)消失
常用的方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取上下文对象
ServletContext servletContext = getServletContext();
//获取项目根路径
System.out.println(servletContext.getContextPath());
//获取上下文对象中的属性值
System.out.println(getServletContext().getAttribute("pass"));
//获取全局初始化参数
String para = servletContext.getInitParameter("para");
System.out.println(para);
}
1.7.2.ServletConfig配置信息类
- 每个servlet都有一个配置信息类
常用方法
// 获取配置信息类
ServletConfig servletConfig = getServletConfig();
//获取servlet初始化参数
String initParameter = servletConfig.getInitParameter("");
// 获取servlet名字
System.out.println(servletConfig.getServletName());
1.7.3.HttpServletRequest请求
- 每次请求都会有一个新的请求对象
- URL统一资源定位符,也就是网址
- URI统一资源标识符,端口号后面的内容(短的)
1.7.3.1. 常用方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//请求对象设置字符编码
req.setCharacterEncoding("UTF-8");
//URL
System.out.println(req.getRequestURL());
//URI
System.out.println(req.getRequestURI());
//获取请求方式 get/post
System.out.println(req.getMethod());
//指定key获取头信息
System.out.println(req.getHeader("Host"));
//获取根路径
System.out.println(req.getContextPath());
}
1.7.3.2.请求转发
- 浏览器发送请求给服务器,服务器内部进行了资源的转发()
- 特点
- 浏览器只发了一次请求(请求对象只有一个)浏览器中URL路径不变
- 可以向域对象中设值,用于数据传递
- 不能够转到其他应用
servlet1
@WebServlet("/check1")
public class GoodCheckServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//
System.out.println("check1 完成了");
//设置域对象属性值
req.setAttribute("check","1");
//获取转发对象
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/check2");
requestDispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
servlet2
@WebServlet("/check2")
public class GoodCheckServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("check2收到了");
System.out.println("获取域对象属性值:" + req.getAttribute("check"));
System.out.println("check2完成了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
1.7.3.3. “/”在web应用中的使用
- 如果是浏览器解析,为 http://ip:port
- 后台服务器解析 http://ip:port/serverPath
1.7.4.HttpServletResponse响应
1.7.4.1.常用方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//字符编码
resp.setContentType("text/html;charset=UTF-8");
//设置响应头
resp.setHeader("Content-Type","text/html;charset=UTF-8");
// 设置状态码
resp.setStatus(200);
req.setAttribute("check2","ok");
//字节输出流,只能使用其中一个,不能同时用
resp.getOutputStream().print("hello");
//字符输出流
resp.getWriter().write("hello");
}
1.7.4.2.重定向
- 浏览器向服务器发送一次请求,服务器返回一个新的地址,浏览器根据新的地址再次发送新的请求
- 特点
- 浏览器中URL路径发生改变
- 请求发送了2次,2个请求对象
- 可以重定向到其他项目资源
//重定向
resp.sendRedirect("/server1/check1");
面试题:转发和重定向的区别
注意点:web-INF是受保护的文件夹,内部的资源通过浏览器无法直接访问
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/192942.html