JavaWeb Servlet
Servlet
Service()
servlet中的service方法实际上就是完成请求的分发处理,会根据客户端不同的提交的方式来执行不同的方法!
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取客户端的提交方式
String method=req.getMethod();
System.out.println("客户端提交方式为:"+method);
if (method.equals("GET"))
{
doGet(req,resp);
}else if (method.equals("POST"))
{
doPost(req,resp);
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行了doGet方法!!!");
//获取servlet核心配置对象
ServletConfig servletConfig = getServletConfig();
String mysql = servletConfig.getInitParameter("mysql_url");
System.out.println(mysql);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行了doPost方法!!!");
}
<!--xml中servletConfig.getInitParameter("mysql_url")的配置-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.zc.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>mysql_url</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</init-param>
</servlet>
一般来说客户端提交的方式是Get形式,所以Service()方法据此执行doGet()方法。
如果我们写一个前端html文件,生成一个form表单,设置提交方式为Post,那么Service()方法据此执行doPost()方法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Servlet/HelloServlet" method="post">
<input type="submit" value="提交">
</form>
</body>
</html>
Servletconfig、ServletContext
Servletconfig
生命周期:ServletConfig代表当前Servlet在web.xml中的配置信息,是Servlet中的一个核心配置对象,而且该对象的生命周期是随着容器的创建而创建,容器的销毁而销毁,在工程的任意位置去获取该实例的时候,指向的都是同一份内存地址
作用: 在Servlet实例加载的时候去获取局部的(当前Servlet实例)初始化信息。在Servlet的配置文件中,可以使用一个或多个
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
将ServletConfig对象传递给Servlet。进而,通过ServletConfig对象就可以得到当前Servlet的初始化参数信息。
作用范围:当前Servlet类
单例:
ServletConfig servletConfig01 = getServletConfig();
ServletConfig servletConfig02 = getServletConfig();
System.out.println("-------------ServletConfig配置对象是否是单例的-----------------");
System.out.println(servletConfig01);
System.out.println(servletConfig02);
System.out.println(servletConfig01 == servletConfig02);//true
ServletConfig配置
栗子:
有一个名为HelloServlet的Servlet,在web.xml中的
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.zc.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>mysql_url</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</init-param>
</servlet>
那么在当前的Servlet类中就可以获取到上面的参数:
ServletConfig servletConfig = getServletConfig();
String mysql = servletConfig.getInitParameter("mysql_url");
System.out.println(mysql);
ServletContext
ServletContext 上下文域对象。
生命周期:ServletContext是Servlet中的一个上下文对象,而且该对象的声明周期是随着容器的创建而创建,容器的销毁而销毁,在工程的任意位置去获取该实例的时候,指向的都是同一份内存地址。
作用:ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext()方法获得ServletContext对象。可以像map一样存放数据,取出数据,而且是在工程的任意位置取出数据,作业范围是整个web工程,可以去读取全局的初始化信息,可以在工程的任何位置读取。
其他域对象:
-
request(也是一个域对象,也可以去存取数据,不过该对象的取值范围比较小)
-
session(会话对象,会对客户端和服务端进行绑定)
作用范围:由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
单例:
ServletContext servletContext1 = getServletContext();
System.out.println("-------------Servlet上下文配置对象是否是单例的-----------------");
System.out.println(servletContext);
System.out.println(servletContext1);
System.out.println(servletContext == servletContext1);//true
ServletContext共享数据
栗子:
HelloServlet02.java:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取域对象
ServletContext servletContext = getServletContext();
//往域中存放数据 以类似键值对的形式
servletContext.setAttribute("username","root");
servletContext.setAttribute("password","123456");
//取出域中的数据 除此类的此方法外 其他类的其他方法都可以获取到
System.out.println("username的值:"+servletContext.getAttribute("username"));
System.out.println("password的值:"+servletContext.getAttribute("password"));
}
HelloServlet03.java:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取上下文域对象
ServletContext servletContext = getServletContext();
//要先访问HelloServlet02后端资源 存入ServletContext的值 再访问HelloServlet03后端资源获取值
//取出域中的数据
System.out.println("username的值:"+servletContext.getAttribute("username"));
System.out.println("password的值:"+servletContext.getAttribute("password"));
}
在xml中配置全局初始化数据
栗子:
<!--配置全局的初始化数据-->
<context-param>
<param-name>name</param-name>
<param-value>jack</param-value>
</context-param>
<context-param>
<param-name>age</param-name>
<param-value>20</param-value>
</context-param>
<context-param>
<param-name>sex</param-name>
<param-value>男</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
//取出全局的初始化数据
String name = servletContext.getInitParameter("name");
String age = servletContext.getInitParameter("age");
String sex = servletContext.getInitParameter("sex");
System.out.println(name+" "+age+" "+sex);
}
HTTP协议:
Get和Post请求方式
Get请求方式会将发送到服务器端的数据封装在地址上,Post请求方式会将数据封装在请求体中,所以Post请求方式相对来说安全一点,因为数据是隐藏在请求体中的。而Get方式相对不安全,在地址栏上可以直接看见请求的数据,而且Post请求方式所能够传递的数据大小要高于Get方式。所以经常使用的请求方式一般是Post。
Get请求
-
请求行
1)请求的方式Get
2)请求的资源路径 [+?+请求参数] 请求的协议的版本号HTTP/1.1 -
请求头
key : value组成不同的键值对,表示不同的含义
Post请求
-
请求行
1)请求的方式Post
2)请求的资源路径 [+?+请求参数]
3)请求的协议的版本号HTTP/1.1 -
请求头key : value不同的请求头,有不同的含义
-
请求体:就是发送给服务器的数据
HttpRequestServlet
常用方法
Get方式
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理中文乱码,一般POST方式会出现中文乱码
req.setCharacterEncoding("utf-8");
if (req.getMethod().equals("GET"))
doGet(req,resp);
else if (req.getMethod().equals("POST"))
doPost(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的资源路径
String requestURI = req.getRequestURI();
// /Servlet/hello05
System.out.println("请求的资源路径为:"+requestURI);
StringBuffer requestURL = req.getRequestURL();
// http://localhost:8080/Servlet/hello05
System.out.println("统一资源定位符"+requestURL);
String remoteHost = req.getRemoteHost();
// 0:0:0:0:0:0:0:1
System.out.println(remoteHost);
String header = req.getHeader("User-Agent");
// Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
System.out.println(header);
}
通过Get方式传递数据给后端,后端通过req.getParameter()方法获取数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String age = req.getParameter("age");
String sex = req.getParameter("sex");
System.out.println(name);
System.out.println(age);
System.out.println(sex);
}
- 在浏览器端输入地址后面带上参数
- 然后访问后,也可以在浏览器的开发者工具(按下键盘的F12)Network下面查看到传递的数据
- 如果要接收的key值有多个value,则需要调用请求对象的req.getParameterValues()方法
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过请求对象来接收value有多个的key
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
- 在浏览器端输入带参数的地址,hobby一共有3个值
- 同理我们可以在网页的开发者工具中看到参数,也可以在控制台上看到打印的输出
打篮球
敲代码
打游戏
Post方式
- 要以Post方式进行提交,需要在新html文件中使用表单标签,设置提交方式为Post
hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--跳转到后端的HelloServlet05资源-->
<form action="http://localhost:8080/Servlet/HelloServlet05" method="post">
username: <input type="text" name="username"><br>
password: <input type="password" name="password"><br>
<!--单选按钮表单控件-->
sex: 男:<input type="radio" value="男" name="sex">
女:<input type="radio" value="女" name="sex">
<br>
<!--下拉菜单控件-->
country: <select name="country">
<option name="1">--请选择--</option>
<option name="美国">美国</option>
<option name="中国">中国</option>
<option name="德国">德国</option>
</select>
<br>
<!--复选框 跟单选框的区别就是可以选多个值-->
hobby:
睡觉<input type="checkbox" name="hobby" value="睡觉"><br>
打篮球<input type="checkbox" name="hobby" value="打篮球"><br>
打乒乓球<input type="checkbox" name="hobby" value="打乒乓球"><br>
</select><br>
<input type="submit" value="提交">
</form>
</body>
</html>
- 浏览器访问:
- HelloServlet05.java
除了在Web.xml中手动配置资源外,还可以基于注解的方式进行xml资源配置
例如
//基于注解进行xml资源配置
@WebServlet("/HelloServlet05")
//基于注解进行xml资源配置
@WebServlet("/HelloServlet05")
public class HelloServlet05 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理中文乱码,一般POST方式会出现中文乱码
req.setCharacterEncoding("utf-8");
if (req.getMethod().equals("GET"))
doGet(req,resp);
else if (req.getMethod().equals("POST"))
doPost(req,resp);
}
//这里主要演示Post方式,doGet方法忽略
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String sex = req.getParameter("sex");
String country = req.getParameter("country");
System.out.println(username);
System.out.println(password);
System.out.println(sex);
System.out.println(country);
//用getParameterValue方法返回多个值
//通过请求对象来接收value有多个的key
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
}
- 点击浏览器页面表单的提交按钮,在 网页-检查-Network-HelloServlet05 里可以看到以Post方式传递的数据:
- 此外,在后端控制台上,也调用了doPost()方法输出:
jack
123456
男
德国
睡觉
打篮球
打乒乓球
HttpServletResponse
- 后端通过HttpServletResponse对象响应给客户端传递数据
-
字节流getOutPutStream()
常用于下载(传递二进制数据)
-
字符流getWriter()
常用于回传字符串(常用)
-
响应的乱码解决
setContentType("text/html;charset=utf-8")
package com.zc.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;
//基于注解进行xml资源配置
@WebServlet("/HelloServlet06")
public class HelloServlet06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//传递数据给前端
//response.setCharacterEncoding("utf-8"); 这样一般不解决问题,
//可以让前后端字符集统一的方法
resp.setContentType("text/html;charset=utf-8");
//向Web容器(Tomcat 服务器)请求字符流对象
resp.getWriter().print("hello servlet");
resp.getWriter().print("<br/>");
resp.getWriter().print("响应成功!!");
resp.getWriter().print("<br/>");
resp.getWriter().print("<input type='text'>");
/*
//向Web容器(Tomcat 服务器)请求字节流对象
response.getOutputStream().print("hello servlet");
response.getOutputStream().print("hello servlet");
*/
}
}
- 浏览器端显示服务器端回传的数据: