4 创建servlet的三种方式
4.1 实现Servlet接口的方式
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;@WebServlet("/test1")
public class Servlet1 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {//s使用ServletConfig对象初始化我们的Servlet//执行了,从这个地方可以说明一个问题 Servlet已经被实例化了System.out.println("init方法执行");}@Overridepublic ServletConfig getServletConfig() {//获取servlet配置信息对象//没有执行System.out.println("getServletConfig方法执行");return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {//核心方法 类似于我们的doGet()方法,和doPost()方法 请求和响应//一定执行的System.out.println("service");}@Overridepublic String getServletInfo() {//获取Servlet的详细信息//没有执行System.out.println("getServletInfo方法执行");return null;}@Overridepublic void destroy() {//当tomcat关闭的时候,执行销毁这个servlet的方法System.out.println("destroy方法执行");//只有当tomcat关闭的时候,才会执行这个方法}
}
4.2 继承GenericServlet抽象类的方式
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
/*
* 第二种方式:继承GenericServlet
*
* */
@WebServlet("/test2")
public class Servlet2 extends GenericServlet {//只有一个方法是必须重写的,抽象方法//为什么?service是核心方法,因为请求和响应就是执行这个方法@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {//解决中文乱码问题servletResponse.setContentType("text/html;charset=utf-8");servletResponse.getWriter().append("我是第二种创建Servlet的方法");}
}
4.3 继承HttpServlet的方式
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("/test3")
public class Servlet3 extends HttpServlet {//因为在前端的时候,有两种请求方式get和post//doGet和doPost方法写在了Service方法中了@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");resp.getWriter().println("我是HttpServlet创建的Servlet");}
}
这三个创建方式选择哪个?
最好的方式是继承HttpServlet
1.可以减少对其他方法的要求 init destroy
2.可以根据前端的要求进行分门别类 doGet doPost
5 Servlet获取前端提交的参数
学好Servlet必须紧紧围绕着请求和响应这两个概念
以上写的代码只是进行请求,然后再响应到客户端。请求的时候没有带数据给Servlet
下面开始写在请求的时候前端带数据到servlet里面,我们servlet要接收前端给我们的这个数据
- login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>$Title$</title></head><body><form action="user/login" method="post"><input type="text" name="username"/><br><input type="text" name="password"/><br><input type="submit" value="提交"></form></body>
</html>
- servlet实例
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");//html页面中 input标签发送的数据,都会存到HttpServlet这个对象里面//通过前端input标签name的属性值获取前端发送的数据String username = request.getParameter("username");String password = request.getParameter("password");System.out.println("username: " + username+"===password"+password);//Servlet响应数据到客户端的时候,如果是中文的话,会乱码response.setContentType("text/html;charset=utf-8");response.getWriter().write("username: " + user+"===password"+password);}
}
- web.xml
<servlet><servlet-name>login</servlet-name><servlet-class>com.by.servlet.LoginServlet</servlet-class></servlet><servlet-mapping><servlet-name>login</servlet-name><url-pattern>/login</url-pattern></servlet-mapping>
6 中文乱码的解决方案
请求时候的乱码问题:
//前端发送数据到Servlet,如果是post请求的话,input输入中文数据的时候,Servlet接到的数据是乱码的。
request.setCharacterEncoding("utf-8");
响应时候中文乱码的问题:
//Servlet响应数据到客户端的时候,如果是中文的话,会乱码
response.setContentType("text/html;charset=utf-8");
7 重定向和转发
web网站上面有一些跳转按钮。比如登录成功以后跳转到主页面!!!
7.1 重定向
- 是什么
用户通过浏览器发送一个请求,Tomcat服务器接收这个请求,会给浏览器发送一个状态码302,并设置一个重定向的路径,浏览器如果接收到了这个302的状态码以后,就会去自动加载服务器设置的路径
一个页面跳转到另外一个页面(应用场景)、登录页面跳转到主页面:
login.jsp====>LoginServlet====>main.jsp
- 特征:
①重定向的过程是浏览器(客户端)的行为
②实际上浏览器做了2次请求(当点击登录按钮的时候做了两次请求)(分别是请求login和main.jsp)
③注意上一次请求的request对象会丢失
④重定向有一个非常明显的特征,即浏览器的url变化了
- 重定向就一句核心代码:
response.sendRedirect("main.jsp"); //就这一行代码,但是这一行代码必须写在doGet或者doPost方法中
- login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%--请求RedirectServlet--%>
<form action="redirect" method="post"><input type="text" name="username"/><br><input type="text" name="password"/><br><input type="submit" value="提交">
</form>
</body>
</html>
- RedirectServlet
package com.by.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class RedirectServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置字符编码request.setCharacterEncoding("utf-8");String username = request.getParameter("username");String password = request.getParameter("password");request.setAttribute("username", username);request.setAttribute("password", password);//登录以后跳转到主页//重定向//这个TestLoginServlet里面的数据是不能传给target.html的response.sendRedirect("main.jsp");}
}
- web.xml
<servlet><servlet-name>redirect</servlet-name><servlet-class>com.by.servlet.RedirectServlet</servlet-class></servlet><servlet-mapping><servlet-name>redirect</servlet-name><url-pattern>/redirect</url-pattern></servlet-mapping>
- main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
这是main页面<br>
<%--
<%=request.getAttribute("username")%>
<%=request.getAttribute("password")%>
--%>${username}
${password}
</body>
</html>
- 测试
7.2 转发
- 是什么
用户发送数据请求到服务器,服务器接收当前请求,会调用内部方式(转发)处理该请求,最终把响应给客户端
- 特征:
①转发是服务器的行为
②浏览器在这个过程中只有一次行为
③转发可以带有数据 request对象中
④url不会发生任何的变化
- 核心代码也只有一行
request.getRequestDispatcher(“main.jsp”).forward(request,response);
//这一行代码就表示进行了转发,url没有变,但是响应的结果却是一次请求干了两个活
- login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%--请求ForwardServlet--%>
<form action="forward" method="post"><input type="text" name="username"/><br><input type="text" name="password"/><br><input type="submit" value="提交">
</form>
</body>
</html>
- ForwardServlet
package com.by.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class ForwardServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置字符编码request.setCharacterEncoding("utf-8");String username = request.getParameter("username");String password = request.getParameter("password");request.setAttribute("username", username);request.setAttribute("password", password);//登录以后跳转到主页//重定向//这个TestLoginServlet里面的数据是不能传给target.html的request.getRequestDispatcher("main.jsp").forward(request, response);}
}
- web.xml
<servlet><servlet-name>forward</servlet-name><servlet-class>com.by.servlet.ForwardServlet</servlet-class></servlet><servlet-mapping><servlet-name>forward</servlet-name><url-pattern>/forward</url-pattern></servlet-mapping>
- main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
这是main页面<br>
${username}
${password}
</body>
</html>
- 测试
8 Servlet的自动加载
默认情况下,第一次访问servlet的时候,创建servlet对象。如果servlet构造函数里面的代码或者init方法里面的代码比较多,就会导致用户第一次访问servlet的时候比较慢。这个时候,我们可以改变servlet对象的创建时机:提前到加载web应用的时候。在servlet的配置信息中,加上一个<load-on-startup>
标签即可。
<servlet><servlet-name>loadOnStartup</servlet-name><servlet-class>com.by.servlet.LoadOnStartupServlet</servlet-class><!--容器是否在启动时加载该servlet,数字越小优先级越高越高--><load-on-startup>1</load-on-startup>
</servlet>
servlet实例:
public class LoadOnStartupServlet implements HttpServlet {public LoadOnStartupServlet(){System.out.println("LoadOnStartupServlet constructor method has run....");}
}
这样配置之后,servlet的构造函数和init方法就会在web应用加载的时候就会执行。
9 ServletConfig对象
-
是什么
ServletConfig是javax.servlet.包下的一个接口,ServletConfig它是Servlet的一个配置对象;
ServletConfig是由tomcat容器创建,通过init方法传入给Servlet;
-
ServletConfig对象如何获取?
在GenericServlet里面定义了:
public ServletConfig getServletConfig() {return this.config;
}
- 常用方法
getInitParameter(String parameterName); //根据参数名称获取指定的参数值
getInitParameterNames(); //获取所有的参数名称
- 需求:
获取servlet里面定义的参数
<servlet><servlet-name>demo2</servlet-name><servlet-class>com.by.servlet.ServletConfigServlet</servlet-class><!--Servlet的初始化参数--><init-param><param-name>username</param-name><param-value>root</param-value></init-param><init-param><param-name>password</param-name><param-value>root123</param-value></init-param></servlet><servlet-mapping><servlet-name>demo2</servlet-name><url-pattern>/demo2</url-pattern></servlet-mapping>
package com.by.servlet;import javax.servlet.*;
import javax.servlet.http.HttpServlet;public class ServletConfigServlet extends HttpServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException {//1.获取ServletConfig对象ServletConfig servletConfig = getServletConfig();//2.获取Servlet中的初始化参数String username = servletConfig.getInitParameter("username");System.out.println(username);String password = servletConfig.getInitParameter("password");System.out.println(password);//3.获取ServletContext对象(域对象)ServletContext servletContext = servletConfig.getServletContext();}
}
思考:param参数可不可以在另外的Servlet中获取? 不能
public class ServletConfigServlet2 extends HttpServlet {@Overridepublic void goGet(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException {//1.获取ServletConfig对象ServletConfig servletConfig = getServletConfig();//2.获取Servlet中的初始化参数String username = servletConfig.getInitParameter("username");//不能获取System.out.println(username);String password = servletConfig.getInitParameter("password");//不能获取System.out.println(password);//3.获取ServletContext对象(域对象)ServletContext servletContext = servletConfig.getServletContext();}
}
10 ServletContext对象
-
是什么
ServletContext是javax.servlet包下的一个接口,又称上下文对象,是配置对象也是一个域对象;
当服务器启动时,会为服务器中的每一个web应用程序创建一个ServletContext对象;
在web应用中的servlet要想实现资源的共享,可以通过ServletContext来完成;
-
如何获取这个对象:
public ServletContext getServletContext() {//获取ServletContext对象return this.getServletConfig().getServletContext();
}
- 这个对象里面也有很多方法:
getInitParameter() //获取指定参数名称的全局参数值
getRealPath(String path) //获得当前项目的服务器磁盘路径
getContextPath() //获取项目的根路径
getAttribute(String parameterName) //获取ServletContext域中指定名称的参数值;
setAttribute(String paramterName,Object parameterValue) //存储参数到ServletContext域中;
removeAttribute(String parameterNam) //将ServletContext域中指定名称的参数移除;
- 需求
获取servlet里面定义的参数
<context-param><param-name>username</param-name><param-value>root</param-value></context-param><context-param><param-name>password</param-name><param-value>root456</param-value></context-param>
package com.by.servlet;import javax.servlet.*;
import javax.servlet.http.HttpServlet;public class ServletContextServlet extends HttpServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException {//获取ServletContext对象ServletContext servletContext = getServletContext();//1.获取全局初始化参数String username = servletContext.getInitParameter("username");System.out.println(username);String password = servletContext.getInitParameter("password");System.out.println(password);//2.获取服务器真实路径String upload = servletContext.getRealPath("");System.out.println(upload);//3.获取项目的根路径String contextPath = servletContext.getContextPath();System.out.println(contextPath);//4.往ServletContext域中,存储一个名称为msg的属性,值为"hello"String str = "hello";servletContext.setAttribute("msg",str);}
}
思考:param参数可不可以在另外的Servlet中获取? 不能
package com.by.servlet;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;public class ServletContextServlet2 extends HttpServlet {@Overridepublic void doGet(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException {//从ServletContext域中取出msg的值ServletContext servletContext = getServletContext();//1.获取全局初始化参数String username = servletContext.getInitParameter("username");System.out.println(username);String password = servletContext.getInitParameter("password");System.out.println(password);//2.获得msg属性Object msg = servletContext.getAttribute("msg");//能获取System.out.println(msg);}
}
package com.by.servlet;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;public class ServletContextServlet3 extends HttpServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException {//1.获取ServletContext对象ServletContext servletContext = getServletContext();//将ServletContext域中的msg参数移除servletContext.removeAttribute("msg");}
}
<servlet><servlet-name>context3=</servlet-name><servlet-class>com.by.servlet.ServletContextServlet</servlet-class></servlet><servlet-mapping><servlet-name>context3=</servlet-name><url-pattern>/context=</url-pattern></servlet-mapping><servlet><servlet-name>context2</servlet-name><servlet-class>com.by.servlet.ServletContextServlet2</servlet-class></servlet><servlet-mapping><servlet-name>context2</servlet-name><url-pattern>/context2</url-pattern></servlet-mapping><servlet><servlet-name>context3</servlet-name><servlet-class>com.by.servlet.ServletContextServlet3</servlet-class></servlet><servlet-mapping><servlet-name>context3</servlet-name><url-pattern>/context3</url-pattern></servlet-mapping>
11 Request对象
- 是什么
ServletRequest是一个接口,用户访问服务器,服务器会生成一个对象包含了http所有请求头,由于使用的是http协议,所以该对象的名字叫HttpServletRequest
- 常用的方法
getRequestURL() //获取的完整的URL,即统一资源定位符
getRequestURI() //获取资源的名字,即统一资源标识符
getQueryString() //获取一个url参数部分
getRemoteAddr() //返回的是客户端的ip地址
getRemoteUser() //返回的是客户端的用户
getRemotePort() //返回的是客户端的主机的端口号
getRemoteHost() //返回的是客户端的主机地址
getCookie() //获取Cookie对象
getSession() //获取Session对象
getLocalName() //获取Web服务器主机的名字
getServletContext() //获取上下文对象的
setCharacterEncoding() //设置编码集的
getParameter() //获取前端传过来的数据
setAttribute() //将数据设置给request对象
geAttribute() //获取request对象中的数据
- servlet实例
package com.by.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class RequestServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception{//获取一个完整的url//http://localhost:8080/01_servlet_HelloWorld_war/request1System.out.println(request.getRequestURL());//获取资源的名字//比如:http://localhost:8080/day42_xkh/request1System.out.println(request.getRequestURI());///01_servlet_HelloWorld_war/request1//获取一个url的参数部分//比如 http://localhost:8080/01_servlet_HelloWorld_war/request1?username=goudanSystem.out.println(request.getParameter("username"));//获取前端传送过来的数据request.setCharacterEncoding("utf-8");//设置请求的编码集//给request这个对象设置数据request.setAttribute("name","狗蛋");//获取request对象的值request.getAttribute("name");//获取上下文对象ServletContext servletContext = request.getServletContext();//转发request.getRequestDispatcher("target.jsp").forward(request,response);}
}
<servlet><servlet-name>request</servlet-name><servlet-class>com.by.servlet.RequestServlet</servlet-class></servlet><servlet-mapping><servlet-name>request</servlet-name><url-pattern>/context</url-pattern></servlet-mapping>
12 Response对象
- 是什么
响应对象,把数据给客户端
我们的Servlet紧紧围绕着两个点(Request,Response)请求和响应
- 常用方法
setHeader() //设置响应头的参数
setContentType() //设置字符编码集
getWriter() //获取字符输出流对象
addCookie() //对浏览器新增一个Cookie
sendRedirect() //重定向
- servlet实例
package com.by.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class ResponseServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception{/**************乱码问题*****///方式一response.setCharacterEncoding("utf-8");//设置 HttpServletResponse使用utf-8编码response.setHeader("Content-Type", "text/html;charset=utf-8");//通知浏览器使用utf-8解码//方式二response.setContentType("text/html;charset=utf-8;aaa=bbb"); //包含方法一的两个功能//向客户端发送响应数据response.getWriter().write("<h1>hello<h1>");/************重定向***********///方式一//在响应头中添加302状态码,告诉浏览器需要进行重定向response.setStatus(302);//在响应头中添加Location,指定重定向的位置response.setHeader("Location", "http://www.baidu.com");//方式二response.sendRedirect("http://www.baidu.com"); //包含方法一的两个功能}
}
<servlet><servlet-name>response</servlet-name><servlet-class>com.by.servlet.ResponseServlet</servlet-class></servlet><servlet-mapping><servlet-name>response</servlet-name><url-pattern>/response</url-pattern></servlet-mapping>