文章目录
Servlet技术
一、Servlet简介
-
Servlet就是sun公司开发动态web的一门技术
-
Sun在这些API中提供了一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
-
把实现了Servlet接口的Java程序叫做Servlet
-
Servlet接口为HttpServlet的根接口
-
Mavne仓库地址:https://mvnrepository.com/
二、Servlet使用
四大步骤:
- 导入Servlet依赖
- 继承HttpServlet类 或 实现Servlet接口
- 注解配置Servlet访问路径 或 web.xml配置
- 浏览器访问 Servlet
1、创建Servlet程序
创建Web项目
选择Servlet
在pom.xml中配置 servlet 依赖,也可以通过Tomcat服务器配置
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<!--在运行时排除该jar包,因为当我们将项目部署到Tomcat时可能出现jar包冲突,Tomcat中默认有该jar包-->
<scope>provided</scope>
</dependency>
编写 index.jsp 文件
继承HttpServlet类,并重写doGet和doPost方法,Ctrl+O重写方法
编写 web.xml 配置文件,映射Servlet的URL地址
使用注解配置Servlet的URL地址
运行Tomcat服务器
2、Servlet的配置
1、web.xml配置Servlet请求路径
- Servlet3.0之前使用的是web.xml配置
- 通过web.xml配置Servlet找到对应的页面。
1、web.xml配置 相当于 Servlet 里的注解 @WebServlet。
2、@WebServlet注解 和 web.xml 不能同时存在。
3、servlet 里的 servlet-name 的值自定义。
4、servlet 里的 servlet-class 需要配置的 Servlet 的位置,包含包名和类名。
5、servlet-mapping 里的 servlet-name 值,与 servlet 里的 servlet-name 对应必须一样。
6、servlet-mapping 里的 url-pattern 是映射URL地址必须加上 " / ",与前端的 form 标签中的 action 的值对应,前端中可以不写 " / "
-
一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/sgz</url-pattern> </servlet-mapping>
-
一个Servlet可以指定多个映射路径,需要配置多个 servlet-mapping
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/sgz</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/sgz1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/sgz2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/sgz3</url-pattern> </servlet-mapping>
-
一个Servlet可以指定通用映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/sgz/*</url-pattern> </servlet-mapping>
-
指定一些后缀或者前缀等等
自定义后缀实现请求映射
注意:* 前面不能加映射的路径
只要以 .sgz结尾的都可以:sgz/fsfasfdas.sgz<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.sgz</url-pattern> </servlet-mapping>
-
默认请求路径,直接进入Servlet(不建议配置)
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
2、@WebServlet注解配置Servlet请求路径(常用)
- Servlet3.0之后使用的是@WebServlet注解配置
- 设置一个 urlPatterns 的值
- name 的值自定义
- urlPatterns 的值是URL 路径,且必须有 " / ",与前端的 form 标签中的 action 的值对应,前端中可以不写 " / "
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
- 设置多个 urlPatterns 的值
- 使用 {“1”,“2”,“3”,…} 设置多个userPattern的值
@WebServlet(name = "LoginServlet", urlPatterns = {"/login","/submit"})
3、Servlet生命周期
- Servlet 接口里有三个生命周期方法
- init:初始化,进去Servlet会执行,只会调用一次
- service:刷新服务,运行时执行,多次调用
- destroy:销毁,关闭服务器或退出Web时执行,只会调用一次
/**
* Servlet 接口里有三个生命周期方法
* init:初始化
* service:刷新服务
* destroy:销毁
*/
@WebServlet(urlPatterns = "/life.do")
public class LifeServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init 初始化被调用");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service 刷新服务被调用");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy 销毁被调用");
}
}
三、ServletConfig接口
- Servlet运行期间的配置,如编码、Servlet共享等。
1、@WebServlet注解初始化参数initParams
@WebServlet(name = "DemoServlet", urlPatterns = "/ConfigServlet",
initParams = {@WebInitParam(name = "email", value = "123@qq.com"),
@WebInitParam(name = "password", value = "123123")})
public class ConfigServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
ServletConfig config = this.getServletConfig();
String email = config.getInitParameter("email");
String password = config.getInitParameter("password");
out.println(email);
out.println(password);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
四、ServletContext接口
- web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。
1、web.xml配置初始化参数
getServletContext():获取上下文信息
getInitParameter():获取初始化值,通过 键 获取 值
getInitParameterNames():获取初始化参数名(键)
web.xml配置初始化参数
<context-param>
<param-name>姓名</param-name>
<param-value>沈公子</param-value>
</context-param>
<context-param>
<param-name>age</param-name>
<param-value>22</param-value>
</context-param>
方法一
// 获取上下文信息 getServletContext() ,不然会出现null数据
ServletContext context = getServletContext();
// 获取初始化值 getInitParameter() ,通过 键 获取 值
String name = context.getInitParameter("姓名");
String age = context.getInitParameter("age");
response.getWriter().println(name);
response.getWriter().println(age);
方法二
// 获取上下文信息 getServletContext() ,不然会出现null数据
ServletContext config = getServletContext();
// 获取初始化参数名 getInitParameterNames() ,通过 Enumeration 对象进行遍历,获取初始化数据
Enumeration<String> parameterNames = config.getInitParameterNames();
// 通过 hasMoreElements() 循环看它是否有元素,有的话就通过 nextElement() 获取参数名称
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement(); // 获取键 nextElement()
String value = config.getInitParameter(name); // 获取值 getInitParameter()
response.getWriter().println(name + ":" + value);
}
2、多个Servlet对象共享数据
getServletContext():获取上下文信息
getAttributeNames():返回Enumeration对象,获取ServletContext中键
setAttribute():设置共享数据
getAttribute():获取共享数据
removeAttribute():删除属性名对应的值
第一个Servlet设置数据,getServletContext() —> setAttribute()
ServletContext context = getServletContext(); // 获取 getServletContext()
context.setAttribute("username", "admin"); // 设置共享数据 setAttribute()
context.setAttribute("password","123123");
context.setAttribute("age","22");
第二个Servlet获取数据,getServletContext() —> getAttribute()
ServletContext context = getServletContext(); // 获取 getServletContext()
String username = (String) context.getAttribute("username"); // 获取共享数据 getAttribute()
获取多个Servlet数据
ServletContext context = getServletContext();
// getAttributeNames() 返回Enumeration对象,获取ServletContext中键
Enumeration<String> enumeration = context.getAttributeNames();
while (enumeration.hasMoreElements()){
String name = enumeration.nextElement();
if (name.equals("username") || name.equals("password") || name.equals("age")){
Object value = context.getAttribute(name);
response.getWriter().println(value);
}
}
删除ServletContext中的属性
ServletContext context = getServletContext();
context.setAttribute("username", "root");
context.setAttribute("password", "123123");
context.setAttribute("age", "22");
context.removeAttribute("age"); // removeAttribute():删除键名为age所对应的值
五、HttpServletResponse对象
1、请求重定向
一种资源跳转方式
- 浏览器地址会改变
- 可以重定向到任意位置的资源(服务器内部、外部均可)
- 两次请求,不能在多个资源使用request共享数据
- 需要浏览器的默认路径,所有在编写时加上浏览器默认路径(虚拟目录),需要加 " / "
- sendRedirect()
// 静态获取虚拟路径
response.sendRedirect("/demo04_war/welcome.html");
// 动态获取虚拟路径:request.getContextPath()
response.sendRedirect(request.getContextPath()+"/welcome.html");
2、解决响应中文乱码问题
方法一:(常用)
response.setContentType("text/html;charset=utf-8");
方法二
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type","text/html;charset=utf-8");
3、状态码相关方法
getStatus():获取响应消息状态码
sendError():一个参数 发送错误状态码,两个参数 发送错误消息提示和状态码
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter(); // PrintWriter:字符输出流对象
// 获取请求参数,通过url地址传参获取 http://localhost:8080/Demo_war_exploded/StatusServlet?param=0
String str = request.getParameter("param");
if (str == null) {
out.println("没有提供请求参数");
} else if (str.equals("0")) {
out.println(response.getStatus() + "<br>"); // getStatus():获取响应消息状态码
} else if (str.equals("1")) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN); //禁止的 403
} else if (str.equals("2")) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); //没有权限的 401
} else {
response.sendError(404, "resource cannot found!"); // 发送错误消息提示和状态码
// response.sendError(404); // 不会在消息中提示,只会显示 404
}
4、字符方法响应对象
PrintWriter out = response.getWriter();
out.println(username);
5、字节方法响应对象
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(username.getBytes());
六、HttpServletRequest对象
可以通过前端的name值获取到前端的数据,HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有消息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获取客户端的所有信息。
1、请求转发
一种在服务器内部的资源跳转方式
- 浏览器地址不会改变
- 只能转发到当前服务器的内部资源
- 一次请求,可以在转发的资源间使用request共享数据
- 指定转发路径时需要加 " / "
- getRequestDispatcher().forward()
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/success.jsp").forward(request, response); // 合并
// 请求转发,需要一个请求转发路径,它会走这个转发的路径,请求路径不会改变,必须加 " / "
// RequestDispatcher request1 = context.getRequestDispatcher("/success.jsp");
// request1.forward(request,response); // 调用 forward 实现请求转发
2、获取请求数据
-
请求行
- String getMethod():获取请求方式:GET
- String getContextPath():获取虚拟目录:/demo
- StringBuffer getRequestURL():获取URL:htpp://localhost:8080/demo/a
- String getRequestURI():获取URI:/demo/a
- String getQueryString():获取请求参数:username=zhangsan&password=123123
-
请求头
- String getHead(String name):根据请求头名称,获取值
-
请求体
- ServletInputStream getInputStream():获取字节输入流
- BufferedReader getReader():获取字符输入流
3、获取请求参数
index.jsp页面
<form action="hello-servlet" method="get">
用户名:<input type="text" name="username"> <br>
兴趣:<input type="checkbox" name="happy" value="play">玩
<input type="checkbox" name="happy" value="ect">吃
<input type="checkbox" name="happy" value="he">喝
<input type="checkbox" name="happy" value="pao">泡 <br>
<input type="submit" value="提交">
</form>
Java代码
- getParameter():获取单个参数,前端或浏览器地址
- getParameterValues():获取多个参数(数组),前端或浏览器地址
- getParameterMap():获取所有参数Map集合
@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
// 单个参数
String username = request.getParameter("username");
System.out.println(username);
// 多个参数
String[] happies = request.getParameterValues("happy");
for (int i = 0; i < happies.length; i++) {
System.out.println(happies[i] + " ");
}
// 获取所有参数的Map集合
Map<String, String[]> map = request.getParameterMap();
for (String key : map.keySet()) { // 快捷键:iter
System.out.print(key+":"); // username:zhangsan lisi
String[] values = map.get(key); // 获取值
for (String value : values) { // 遍历输出获取的值
System.out.print(value+" ");
}
System.out.println();
}
getServletContext().getRequestDispatcher("/success.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
4、Request共享数据
- 一次请求中才可以在转发资源间使用request共享数据
当前为 Servlet1
request.setAttribute("username","沈公子");
request.getRequestDispatcher("/Servlet2").forward(request,response); // 只有在同一个request才可以共享数据
当前为 Servlet2
Object username = request.getAttribute("username");
System.out.println(username);
5、解决请求中文乱码问题
request.setCharacterEncoding("utf-8");
七、重定向和转发的区别
- 相同点:
- 页面都会实现跳转
- 不同点:
- 请求转发的时候,url不会产生变化,307,getRequestDispatcher().forward(),不需要tomcat地址,一次请求,可以使用request共享数据,只能访问内部服务器资源,不需要虚拟目录
- 重定向的时候,url地址栏会发生变化,302,sendRedirect(),需要tomcat地址,两次请求,不可以使用request共享数据,可以访问内部与外部服务器资源,需要虚拟目录
八、IDEA模板创建Servlet
九、Servlet总结
- Servlet创建
- Servlet请求路径配置,两种方式
- web.xml(四种格式)
- @WebServlet注解(四种格式)(常用)
- Servlet生命周期
- Servlet初始化参数
- Servlet共享数据
- 重定向
- 请求转发
- 设置状态码
- 解决乱码问题
- 获取请求数据
- 获取请求参数