文章目录
servlet概念
- servlet是javaEE规范之一。规范就是接口。
- servlet是运行在服务器上的一个java小程序,它可以接受客户端发送的请求,并响应客户端的请求。
手动实现servlet程序
- 编写一个类去实现servlet接口
- 实现service方法,处理请求,并响应数据
- 到web.xml中配置servlet的访问地址
servlet-name标签: Servlet程序起了一个别名(一般是类名)
servlet-class标签 : 是Servlet程序的全类名
servlet-name标签 : 作用是告诉服务器,我当前配置的地址是给哪个Servlet程序使用
url-pattern标签 :配置访问地址
注意:
/斜杆在服务器解析的时候,表示地址为http://IP:port/工程路径
<!--web/xml的配置 -->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.zzq.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
servlet生命周期
- 构造器(创建时访问)(仅一次)
- init(创建时访问)(仅一次)
- service(每次访问都会调用)
- destroy(web工程停止时调用)
HttpServlet
一般在实际项目中,都是使用继承HttpServlet类的方式去实现Servlet程序
步骤:
- 编写一个类去继承HttpServlet类
- 根据业务重写doGet或者doPost方法
- 配置web.xml
Servlet继承体系
- Servlet :
接口,定义规范 - GenericServlet :
实现Servlet接口
做了很多空实现
持有一个ServletConfig类的引用,对ServletConfig的使用做了一些方法 - HttpServlet :
继承GenericServlet类
实现service()方法,实现请求的分发处理,它实现的doGet和doPost方法负责抛异常,说不支持GET/POST请求 - 自定义的Servlet程序
继承HttpServlet
我们根据业务只需要重写doGet和doPost方法即可
ServletConfig类
1、Servlet程序和ServletConfig对象都是Tomcat负责创建,我们负责使用
2、Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象,对象获取方式如下
ServletConfig servletConfig = getServletConfig();
作用:
- 获取Servlet程序的别名servlet-name的值
- 获取初始化参数init-param
- 获取ServletContext对象
init参数
<servlet>
<!--init-param是初始化参数-->
<init-param>
<!--参数名-->
<param-name>username</param-name>
<!--参数值-->
<param-value>root</param-value>
</init-param>
</servlet>
init方法
当我们自己编程序继承HttpServlet类时,如果重写init方法一定要调用父类的init(ServletConfig)方法!!!!!
否则,会出现类中持有的ServletConfig对象无法使用的情况
ServletContext
ServletContext是个接口,表示Servlet上下文对象
一个web工程,只有一个ServletContext对象实例,工程启动的时候创建,停止的时候销毁
ServletContext对象是一个域对象
域对象
什么是域对象?是可以像Map一样存取数据的对象,叫做域对象
这里的域指的是存取数据的操作范围。整个web工程。
存数据:setAttribute()
取数据:putAttribute()
删除数据:removeAttribute()
作用
- 获取web.xml配置的上下文参数context-param
- 获取当前的工程路径,格式:/工程路径
- 获取工程部署后在服务器磁盘上的绝对路径
- 像Map一样存取数据
ServletContext context = getServletConfig().getServletContext();
//1、获取web.xml配置的上下文参数context-param
String user = context.getInitParameter("user");
System.out.println("user值为:"+user);
//2、获取当前的工程路径,格式:/工程路径
System.out.println("工程路径:"+context.getContextPath());
//3、获取工程部署后在服务器磁盘上的绝对路径
System.out.println("工程部署后在服务器磁盘上的绝对路径:"+context.getRealPath("/"));
//4、像Map一样存取数据
context.setAttribute("key","value");
System.out.println(context.getAttribute("key"));
HttpServletRequest类
作用:
每次有请求进入Tomcat服务器中,Tomcat就会把请求过来的Http协议信息解析好封装到Request对象中,然后传递到service(doGet和doPost)方法中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息
常用方法
获取请求的信息
//获取请求的资源路径
System.out.println(req.getRequestURI());
//获取请求的绝对路径
System.out.println(req.getRequestURL());
//客户端ip地址
System.out.println(req.getRemoteHost());
//获取请求头
System.out.println(req.getHeader("User-Agent"));
//获取请求方式
System.out.println(req.getMethod());
获取请求参数
主要是两个方法
- getParameter()(获取单值参数)
- getParameterValues()(获取多值参数)
注意:doPost方法中需要指定字符串编码,否则会出现乱码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.asList(hobby));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.asList(hobby));
}
请求转发
请求转发是指,服务器收到请求后,从一个资源跳转到同一服务器的另一个资源的操作叫做请求转发。
注意:
- 请求转发虽然访问了两个资源,但是只有一个请求
- 他们共享Request域中的数据
- 可以转发到WEB-INF目录下!!!!!
- 不能访问工程以外的目录
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
System.out.println("Servlet1中查看参数:"+username);
//给材料盖章
req.setAttribute("key1","柜台1盖的章");
//问路,Servlet2怎么走
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
//走向Servlet2
requestDispatcher.forward(req,resp);
}
}
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
System.out.println("Servlet2中查看参数:"+username);
//查看Servlet1是否有盖章
Object key1=req.getAttribute("key1");
//处理自己的业务
System.out.println("Servlet2处理自己的业务");
}
}
base标签
设置页面相对路径工作时的参照地址
<base href="http://localhost:8080/07_servlet/a/b/c.html"/>
/在web中不同含义
- 被浏览器解析:
http://ip:port/
- 被服务器解析:
http://ip:port/工程路径
- 特殊情况:
把斜杠发送给浏览器解析,得到 http://ip:port/
response.sendRediect("/");
HttpServletResponse类
HttpServletResponse和HttpServletRequest类一样,每次有请求进入Tomcat服务器中,Tomcat都会创建一个Response对象传给Servlet程序使用。
HttpServletRequest表示请求的消息,HttpServletResponse表示所有相应的信息,我们如果需要返回给客户端信息,都可以通过HttpServletResponse对象来设置。
输出流
- 字节流:getOutputStream()
- 字符流:getWriter()
两个流只能使用一个,否则报错
1、避免方法一 :
下面代码同时设置浏览器和服务器都使用utf-8字符集来避免乱码,此方法必须在获取流之前设置才有效
resp.setContentType("text/html;charset=UTF-8");
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.println("返回的东西");
}
2、避免乱码方法二 :
先设置服务器字符编码
resp.setCharacterEncoding("utf-8");
再设置请求头的字符编码(也就是设置浏览器的字符编码)
resp.setHeader("Content-Type","text/html;charset=UTF-8");
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setHeader("Content-Type","text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.println("返回的东西");
}
请求重定向
客户端给服务器发请求,然后服务器告诉客户端说,我我给你一个新地址,你去访问新地址。
- 有两次请求
- 浏览器地址栏发生变化
- 不共享Request域中数据
- 不能进入WEB-INF目录
- 可以访问工程以外的资源
方法一 :
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("曾到此 Response1");
//设置响应状态码,表示重定向
resp.setStatus(302);
//设置响应头,说明新的地址
resp.setHeader("Location","http://localhost:8080/servlet/response2");
}
}
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Response2's result");
}
}
方法二 :
resp.setStatus(302);
resp.setHeader("Location","http://localhost:8080/servlet/response2");
改为 :
resp.sendRedirect("http://localhost:8080/servlet/response2");