用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤: 1、编写一个Java类,实现servlet接口。 2、把开发好的Java类部署到web服务器中。
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
①Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。 ②装载并创建该Servlet的一个实例对象。 ③调用Servlet实例对象的init()方法。 ④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。 ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
通过配置改变Servlet实例化时机
@WebServlet(rulPatterns = "/demo",loadOnStartup = 1)
// 1 负整数:第一次被访问时创建Servlet对象
// 2 0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
public class ServletDemo1 implements Servlet{
}
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
package com.itheima.web;
import javax.servlet.*;
import java.io.IOException;
@WebServlet("/demo1") /*3.配置访问路径*/
public class ServletDemo1 implements Servlet{
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hallo Servlet~");
}
}
查看控制台会发现执行了刚刚我们写在java类中的service方法
void init(ServletConfig config)
void service(ServletRequset req,ServletResponse res)
void destroy()
ServletConfig getServletConflg()
String getServletInfo()
package com.itheima.web;
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;
@WebServlet("/demo1")
public class ServletDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
总结:
一个Servlet,可以配置多个 urlPattern
WebServlet(urlPatterns={"/demo1","/demo2"})
urlPattern 配置规则
① 精确匹配:
@WebServlet("/user/select") //配置路径
// 访问路径:localhost:8080/web-demo/user/select
② 目录匹配:
@WebServlet("/user/*") //配置路径
// 访问路径:localhost:8080/web-demo/user/aaa
// 访问路径:localhost:8080/web-demo/user/bbb
精确匹配的优先级比目录匹配是要高的
③ 匹配名匹配:
@WebServlet("*.do*") //配置路径
// 访问路径:localhost:8080/web-demo/aaa.do
// 访问路径:localhost:8080/web-demo/bbb.do
注意:匹配名匹配的配置路径中不得以/开头,否则就会报错
④ 任意匹配:
@WebServlet("/") //配置路径
@WebServlet("/*") //配置路径
// 访问路径:localhost:8080/web-demo/hehe
// 访问路径:localhost:8080/web-demo/haha
基本不用:因为很危险
<servlet>
<servlet-name>demo5<servlet-name>
<servlet-class>com.itheima.web.servlet.ServletDemo5<servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo5</servlet-name>
<url-pattern>/demo5</url-pattern>
</servlet-mapping>
这是旧版的配置方式了解就好
Web浏览器发送HTTP请求到Web服务器,而请求数据就是一些字符串,字符串会被Tomcat解析,解析完后其实tomcat就会将数据存在request对象中
requset对象保存了请求解析后的数据
在处理完请求的数据后,我们需要对用户进行响应,然后浏览器接受将数据展示在页面上。Tomcat会发送一些响应的字符串,而这些响应的字符串就在 respons中
response对象保存了响应时的数据
于是将来我们就可以拿来做一些事情:
请求数据分为三部分:
GET/request-demo/req1?username=zhangsan HTTP/1.1
User-Agent:Mozilla/5.0 Chorme/91.0.4472.106
username=superbaby&password=123
当HTTP请求发送过来时,系统会自动帮我们将数据截断,放入一个键值队Map数据里,且对于相同键的数据不会覆盖,而是以数组的形式存储,所以这个Map 定义为 Map<String,String[]>我们可以通过这个Map获取到我们想要的数据
请求参数存在中文数据,则会乱码
乱码原因:编解码字符集不一致
URL编码 1.将字符串按照编码方式转为二进制 2.每个字符转为2个16进制数并在前面加上%
解决方案:
req.setCharacterEncoding("UTF-8");
new String(username.getBytes("ISO-8859-1"),"UTF-8");
URL编码实现方式:
URLEncoder.encode(str,"utf-8");
URLDecoedr.decode(s,"ISO-8859-1");
Tomcat8 之后其实就已经解决了中文乱码问题
说的是一种在服务器内部的资源跳转方式
req.getRequestDispatcher("资源B路径").forward(req,resp);
响应数据分为3部分:
HTTP/1.1 200 OK
void setStatus(int sc); //设置响应状态码
Content-Type:text/html
void setHeader(String name,String value); //设置响应头键值对
<html><head><body></body></head></html>
PrintWriter getWriter(); //获取字符输出流
ServletOutputStream getOutputStream(); //获取字节输出流
说的是一种资源调整方式:当服务器处理不了浏览器的请求,但其他资源可以处理请求时,会返回状态码以及其他资源的响应头给浏览器。浏览器拿到状态码和资源路径就会将请求发送给指定资源处理
实现方式:
// 1.设置响应状态码
resp.setStatus(302);
// 2.设置响应头
resp.setHeader("location","资源B的路径");
// 简化写法
resp.sendRedirect("资源B的路径");
客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问
// 1. 创建Cookie对象,设置数据
Cookie cookie = new Cookle("key","value");
// 2. 发送Cookie到客户端:使用response对象
response.addCookle(cookie);
// 1. 获取客户端携带的所有Cookie,使用request对象
Cookie[] cookies=request.getCookies();
// 2. 遍历数组,获取每个Cookie对象:for
// 3. 使用Cookie对象方法获取数据
cookie.getName();
cookie.getValue();
Cookie 的实现是基于HTTP协议的
Cookie 不能直接存储中文,如果需要存储,则需要进行转码:URL 转码
String value="张三";
//URL编码
value = URLEncoder.encode(value,"UTF-8");
Cookie cookie = new Cookie("username",value);
//URL解码
value = URLDecoder.decode(value,"UTF-8");
服务端会话跟踪技术,将数据保存到服务端,这其实是一种比较不安全的方式。因为数据往返频繁有被截取拦截的风险。
JavaEE 提供 HttpSession接口,来实现一次会话的多次请求间数据的共享功能
//1.获取Session对象
HttpSession session =request.getSession();
//2.Session对象功能:
void setAttribute(String name,Object o);//存储数据到 session 域中
Object getAttribute(String name);//根据 key,获取值
void removeAttribute(String name);//根据 key,删除该键值对
Seesion 的实现是基于cookie
Filter 表示过滤器,是Javaweb 三大组件(Servlet、Filter、Listener)之一。过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。过滤器一般完成一些通用的操作,比如:权限控制、统一编码处理、敏感字处理等等...
//1. 定义类,实现 Filter接口,并重写其所有方法
public class FilterDemo implements Filter{
public void init(FilterConfig filterConfig)
public void doFilter(ServletRequest request)
public void destroy(){}
// 核心方法:doFilter 每次访问Filter时都会执行
}
//2. 配置Filter拦截资源的路径:在类上定义@WebFilter 注解
@WebFilter("/*")
public class FilterDemo implements Filter{
//3. 在doFilter方法中输出一句话,并放行
public void doFilter(ServletRequest request,Ser){
System.out.println("filter 被执行了...");
//放行
chain.doFilter(request,response);
}
@WebFilter("/*")
public class FilterDemo
// 拦截具体的资源:/index.jsp:只访问index.jsp时才会被拦截
// 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
// 后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
// 拦截所有:/*:访问所有资源,都会被拦截
一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤链
注释配置的Filter,优先级按照过滤器类名(字符串)的自然排序
Listener 表示监听器,是JavaWeb三大组件(Servlet、Filter、Listener)之一。监听器可以监听就是application,session,request三个对象创建、销毁、或者往其中添加修改删除属性时自动执行代码的功能组件
监听器分类 | 监听器名称 | 作用 |
---|---|---|
ServletContext监听 | ServletContextListener | 用于对ServletContext对象进行监听(创建、销毁) |
ServletContextAttributeListener | 对ServletContext对象中属性的监听(增删改属性) | |
Session监听 | HttpSessionListener | 对Session对象的整体状态的监听(创建、销毁) |
HttpSessionAttributerListener | 对Session对象中的属性监听(增删改属性) | |
HttpSessionBindingListener | 监听对象于Session的绑定和解除 | |
HttpSessionActivationListener | 对Session数据的钝化和活化的监听 | |
Request监听 | ServletRequestListener | 对Request对象中属性进行监听(创建、销毁) |
ServletRequestAttributeListener | 对Request对象中属性的监听(增删改属性) |
监听器主要就是使用这个监听器
//2.在类上添加@WebListener注解
@WebListener
public class ContextLoaderListener implements ServletContextListener{
//1. 定义类,实现ServletContextListener接口
/**
* ServletContext 对象被创建:整个web应用发布成功
* @param sce
*/
public void contextInitialized(ServletContextEvent sce) {}
/**
* ServletContext 对象被销毁:整个web应用卸载
* @param sce
*/
public void contextDestroyed(ServletContextEvent sce) {}
}