1)编写一个类去实现Servlet接口。
2)实现service方法,处理请求,并响应数据。
package com.atguigu.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;
/**
* @author 龍
*/
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1.构造器方法。");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service:专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3.service方法");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String method = request.getMethod();
System.out.println("http的请求方式为:"+method);
if("GET".equalsIgnoreCase(method)){
doGet();
}else if("POST".equalsIgnoreCase(method)){
doPost();
}
}
public void doGet(){
System.out.println("doGet的方法");
}
public void doPost(){
System.out.println("doPost的方法");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4.销毁的方法");
}
}
3)到web.xml中去配置servlet程序以及访问地址。
<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>HelloServletservlet-name>
<servlet-class>com.atguigu.servlet.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>/helloServleturl-pattern>
servlet-mapping>
web-app>
常见错误
1)url-pattern中配置的路径没有以斜杠开头(invalid:无效的)。
注意:
很少直接实现Servlet接口,都是使用继承HttpServlet的方式实现。
在需要创建Servlet的包,右键点击,直接创建Servlet程序。
Servlet接口==>实现类GenericServlet==>子类HttpServlet==>自定义的Servlet程序
Servlet程序的的配置信息类。
作用:
可以获取Servlet程序的别名Servlet-name的值。
获取初始化参数:init-param。
获取ServletContext对象。
<servlet>
<servlet-name>HelloServletservlet-name>
<servlet-class>com.atguigu.servlet.HelloServletservlet-class>
<init-param>
<param-name>usernameparam-name>
<param-value>rootparam-value>
init-param>
<init-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/testparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>/helloServleturl-pattern>
servlet-mapping>
后台的代码实现:
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.init方法");
//1.获取ServletName
String servletName = servletConfig.getServletName();
System.out.println("ServletName是:"+servletName);
//2.获取初始化参数
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
String paramName=initParameterNames.nextElement();
System.out.println("初始化参数:"+paramName+"="+servletConfig.getInitParameter(paramName));
}
//3.获取ServletContext
ServletContext servletContext = servletConfig.getServletContext();
System.out.println("ServletContext是:"+servletContext);
}
运行结果:
ServletName是:HelloServlet
初始化参数:url=jdbc:mysql://localhost:3306/test
初始化参数:username=root
ServletContext是:org.apache.catalina.core.ApplicationContextFacade@3a93af64
注意:
Servlet程序和ServletConfig对象是由Tomcat负责创建,我们负责使用的。Servlet程序默认是第一次访问的时候创建的,ServletConfig是每个Servlet程序被创建的,就创建一个ServletConfig对象==>每一个Servlet程序都维护一个自己的ServletConfig对象。
如果我们使用继承HttpServlet的方式实现Servlet且重写了init方法,且需要获取web.xml中配置的初始化参数,一定要在init中调用super.init(config);否则会造成ServletConfig丢失。
//GenericServlet中的init(ServletConfig config)
public void init(ServletConfig config) throws ServletException {
this.config = config; //将config保存了起来。
this.init();
}
1 什么是ServletContext?
ServletContext是一个接口,表示Servlet上下文对象。
一个web工程,只有一个ServletContext对象实例。
ServletContext对象是一个域对象(域对象:可以向Map一样存取数据的对象)。
ServletContext对象是在web项目部署的时候创建,销毁的时候销毁。
2 ServletContext的常见作用
获取Web.xml中配置的上下文参数context-param。
获取当前工程路径。格式:/工程路径。
获取工程部署后在服务器硬盘上的绝对路径。
向Map一样存取数据==>多个Servlet共享数据。
<!--context-param是上下文参数,他属于整个Web工程-->
<context-param>
<param-name>user</param-name>
<param-value>context</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>19971001</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//方式1:ServletContext servletContext = getServletConfig().getServletContext();
ServletContext servletContext = getServletContext();
//1.获取上下文参数:context-param:注意和init-param没有任何关系
String user = servletContext.getInitParameter("user");
System.out.println("user="+user);
String password = servletContext.getInitParameter("password");
System.out.println("password="+password);
//2.获取当前工程路径
String contextPath = servletContext.getContextPath();
//当前工程路径为:/07_servlet
System.out.println("当前工程路径为:"+contextPath);
//3.获取工程部署在服务器硬盘上的绝对路径。"/被服务器解析为:http://ip:端口号/工程名称/"
String realPath = servletContext.getRealPath("/");
//E:\projects\ideacode\atguigu\JavaWeb\out\artifacts\07_servlet_war_exploded\==>"/"被映射为Idea代码的web目录。
System.out.println(realPath);
String realPath1 = servletContext.getRealPath("/imgs");
System.out.println(realPath1);
//4.存取数据:注意多个Servlet公用一个servletContext对象==>存储的key-value是公用的。
servletContext.setAttribute("name","张三");
System.out.println("name="+servletContext.getAttribute("name"));
}
1 HttpServletRequest类有什么用
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
2 常见方法
getRequestURI( ):获取请求的资源路径
getRequestURL( ):获取请求的统一资源定位符(绝对路径)
getRemoteHost( ):获取客户端的 ip 地址
getHeader( ):获取请求头
getParameter( ):获取请求的参数
getParameterValues( ):获取请求的参数值(多个值的时候使用)
getMethod( ):获取请求的方式 GET 或 POST
setAttribute(key, value):设置域数据
getAttribute(key):获取域数据
getRequestDispatcher( ):获取请求转发对象
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取uri:资源路径,不包含协议,ip以及端口号
String requestURI = req.getRequestURI();
//07_servlet/requestAPI
System.out.println("URI=="+requestURI);
//2.获取URL==>统一资源访问定位符:包含协议,ip,端口号以及资源路径
StringBuffer requestURL = req.getRequestURL();
//http://localhost:8080/07_servlet/requestAPI
System.out.println("URL=="+requestURL);
//3.获取客户端的ip地址。
String remoteHost = req.getRemoteHost();
//idea中使用localhost进行访问是127.0.0.1。如果是真实ip就会获取真实ip
System.out.println("ip=="+remoteHost);
//4.获取请求的头参数
String header = req.getHeader("User-Agent");
System.out.println("User-Agent=="+header);
//5.获取请求的类型GET或者POST等
String method = req.getMethod();
System.out.println(method);
}
3 获取客户端发送过来的参数
1)API
request.getParameter(“key”):获取key的value值
request.getParameterValues(“key”):获取key对应的多个value值
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题。注意:改代码必须在获取请求参数之前调用才有效。
req.setCharacterEncoding("UTF-8");
//getParameter():单个值使用
String username = req.getParameter("username");
String password = req.getParameter("password");
//getParameterValues():多个值使用
String[] hobby = req.getParameterValues("hobby");
System.out.println("username=="+username);
System.out.println("password=="+password);
System.out.println("hobby=="+ Arrays.toString(hobby));
}
2)当请求的方式是post且请求的参数含有中文,则会出现中文乱码问题==>设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题。
4 请求的转发
1)什么是请求的转发?
请求转发是指,服务器收到请求后,从一个资源跳到另外一个资源的操作,叫做资源的转发,注意客户端是无法感知的。
2)代码实现:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("servlet1查看了参数:username=="+username);
request.setAttribute("key","servlet1的专属标记");
//servlet2的路径:必须以/开头,映射为idea的web目录
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
//进行跳转;传入参数,请求和响应
requestDispatcher.forward(request,response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("servlet2查看了:username=="+username);
System.out.println("servlet2查看了:servlet1的key=="+request.getAttribute("key"));
System.out.println("柜台2开始处理自己的业务!!!");
}
代码执行结果:
servlet1查看了参数:username=="张三"
servlet2查看了:username=="张三"
servlet2查看了:servlet1的key==servlet1的专属标记
柜台2开始处理自己的业务!!!
3)请求转发的特点
4)请求包含
客户端请求servletA,servletA解决一部分,但是还剩下一部分无法解决,剩下的交给ServletB来进行解决。
5)请求转发和请求包含异同
同:
不同:
测试代码实现:
1)demo01
package com.zhiyou.servlet.includeAndForward;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/forward/servletDemo01")
public class ServletDemo01 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name=request.getParameter("name");
//获取相应的参数
System.out.println("demo01:name=="+name);
//设置请求域对象的信息
request.setAttribute("age", 18);
//设置响应头信息
response.setHeader("demo1", "demo01");
//设置响应体数据
response.getWriter().write("demo01-----");
//设置请求转发
//request.getRequestDispatcher("/forward/servletDemo02").forward(request, response);
//设置请求包含
request.getRequestDispatcher("/forward/servletDemo02").include(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
2)demo02
package com.zhiyou.servlet.includeAndForward;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/forward/servletDemo02")
public class ServletDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name=request.getParameter("name");
//获取相应的参数
System.out.println("demo02:name=="+name);
//获取请求域对象的信息
int age=(int)request.getAttribute("age");
System.out.println(age);
//设置响应头信息
response.setHeader("demo2", "demo02");
//设置响应体数据
response.getWriter().write("demo02-----");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
5 base标签的作用
可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转,通常情况下设置为当前项目路径。
6 相对路径和绝对路径
在javaweb中路径分为绝对路径和相对路径
1)相对路径:
. 表示当前目录
… 表示式上一级目录
资源名 表示当前目录/资源名
2)绝对路径:从协议开始算起
http://ip:port/工程路径/资源路径
7 web中/的不同意义
在web中/是一种绝对路径
如果被浏览器解析为:http://localhost:port/
如果被服务器解析为:http://localhost:port/工程路径
例如:
request.getRequestDispacher("/");
/servlet1;
servletContext.getRealPath("/");
特殊:response.sendRediect("/"); //把"/"给浏览器解析为:http://localhost:port/
1 HttpServletResponse类的作用。
HttpServletResponse和HttpServletRequest类一样,每次请求进来,tomcat都会创建一个该对象,传递给Servlet程序去使用,HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息,如果我们需要设置返回客户端的信息,都可以通过HttpServletResponse对象来进行设置。
2 两个输出流的说明
字节流 getOutputStream(); 常用于下载(传递二进制数据)
字符流 getWriter(); 常用于传递字符串(常用)
3 要求往客户端回传字符串数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置服务器字符集为UTF-8:用于解决中文乱码的问题。
//resp.setCharacterEncoding("utf-8");
//通过响应头告诉浏览器也是用utf-8
//resp.setHeader("Content-Type","text/html;charset=UTF-8");
//他会同时设置服务器和客户端都是用UTF-8字符集,还设置了响应头。
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("response的content!!!");
}
4 解决中文乱码问题
方式一:
//设置服务器字符集为UTF-8:用于解决中文乱码的问题。
resp.setCharacterEncoding("utf-8");
//通过响应头告诉浏览器也是用utf-8
resp.setHeader("Content-Type","text/html;charset=UTF-8");
方式二:此方法要在获取流对象之前使用才有效。
//他会同时设置服务器和客户端都是用UTF-8字符集,还设置了响应头。
resp.setContentType("text/html;charset=UTF-8");
5 请求重定向
客户端给服务器发请求,然后服务器告诉客户端一个新的地址,让其去新的地址访问。
特点:
浏览器的地址会发生变化==>两次请求==>不共享request域中的数据。
不能访问WEB-INF下的资源,但是可以访问工程外的资源。
方式一:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("到response1一游!");
//设置响应状态码302.表示是重定向
response.setStatus(302);
//设置响应头,表明新的地址信息
response.setHeader("location","http://localhost:8080/07_servlet/response2");
}
方式二:推荐
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("到response1一游!");
response.sendRedirect("http://localhost:8080/07_servlet/response2");
}
1 常见的get和post方式的的请求
①get
②post请求
2 get和post两者的区别
3 请求转发和重定向的区别
4 乱码的处理
1 页面上:
2 服务器端:request.setCharacterEncoding(“utf-8”);
3 mysql:
安装的时候设置的编码集。
创建表的时候:create table 表名( ) charset=“utf8”
4 服务器端给予响应:
response.setCharacterEncoding(“utf-8”);
response.setHeader(“content-type”,"text/html;charset=“utf-8”);
5 域对象
在指定的范围内实现数据共享的对象。
request:作用域为一个请求,一个请求被多个资源处理,这个资源就是一个资源链。只适用于请求转发和请求包含的两个servlet中实现数据共享。
session:作用域为一个对话,同一个ip,同一个浏览器对服务的发出的连续性请求。
servletContent:上下文对象,作用域是整个项目。
数。
4 乱码的处理
1 页面上:
2 服务器端:request.setCharacterEncoding(“utf-8”);
3 mysql:
安装的时候设置的编码集。
创建表的时候:create table 表名( ) charset=“utf8”
4 服务器端给予响应:
response.setCharacterEncoding(“utf-8”);
response.setHeader(“content-type”,"text/html;charset=“utf-8”);
5 域对象
在指定的范围内实现数据共享的对象。
request:作用域为一个请求,一个请求被多个资源处理,这个资源就是一个资源链。只适用于请求转发和请求包含的两个servlet中实现数据共享。
session:作用域为一个对话,同一个ip,同一个浏览器对服务的发出的连续性请求。
servletContent:上下文对象,作用域是整个项目。