1、Servlet简介
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
2、HelloServlet
1.构建一个Maven项目。删掉里面的src目录,以后我们就在这个项目里建moudel,这个空的工程就是Maven主工程。
2.关于Maven父子工程的理解:
父项目会有:
<modules>
<module>servlet-01</module>
</modules>
子项目会有:
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.wsn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目的jar包子项目可以直接使用。
3.Maven环境优化:
- 修改web.xml为最新的。
- 将maven的结构搭建完整
4.编写一个servlet
- 编写一个普通类
- 实现Servlet接口,这里我们直接继承HttpServlet
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同的方式,里面的代码都长得一样,所以节省空间,我们可以让他们互相调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();//响应流
writer.print("HelloServlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5.编写Servlet的映射
为什么需要映射:我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的servlet,还需要给他一个浏览器能访问的路径。
<!--注册servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.wsn.servlet.HelloServlet</servlet-class>
</servlet>
<!--servlet的映射(请求路径)-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
6.配置Tomcat
7.启动测试
3、Servlet原理
Servlet是由wen服务器调用,web
4、Mapping问题
-
一个Servlet可以指定一个映射路径
<!--注册servlet--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.wsn.servlet.HelloServlet</servlet-class> </servlet> <!--指定一个映射路径,只能通过localhost:8080/wsn/hello访问--> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
一个Servlet可以指定多个映射路径
<!--注册servlet--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.wsn.servlet.HelloServlet</servlet-class> </servlet> <!--指定多个映射路径,可以通过 localhost:8080/wsn/hello localhost:8080/wsn/hello1 localhost:8080/wsn/hello2 localhost:8080/wsn/hello3访问 --> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping>
-
一个Servlet可以指定通用映射路径
<!--注册servlet--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.wsn.servlet.HelloServlet</servlet-class> </servlet> <!--指定通用映射路径,可以通过localhost:8080/wsn/hello本身和/任何字符 localhost:8080/wsn/hello localhost:8080/wsn/hello/sadsadasdas localhost:8080/wsn/hello/wrqwr localhost:8080/wsn/hello/21312dsad访问 --> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
指定默认路径(不建议使用)
<!--注册servlet--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.wsn.servlet.HelloServlet</servlet-class> </servlet> <!--指定默认路径,localhost:8080/wsn不会走首页而是走这个servlet,会把首页干掉,不要这样写--> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
-
可以自定义后缀映射路径
<!--注册servlet--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.wsn.servlet.HelloServlet</servlet-class> </servlet> <!--指定自定义后缀映射路径,通过 localhost:8080/wsn/dasdasdsas.wangshaonan localhost:8080/wsn/sadas.wangshaonan localhost:8080/wsn/sda231.wangshaonan localhost:8080/wsn/fasd3213asda.wangshaonan访问 --> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>*.wangshaonan</url-pattern><!--注意这里*前面不能加任何映射路径--> </servlet-mapping>
优先级问题:
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求,也就是/*的映射
例子:自定义404的映射
//创建一个ErrorServlet响应自定义的404
public class ErrorServlet extends HttpServlet {
//重写doGet,doPost方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");//设置字符集
resp.setContentType("text/html");//响应类型为text/html
PrintWriter writer = resp.getWriter();//响应输出流
writer.print("<h1>404</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);//相互调用
}
}
xml映射
<!--注册servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.wsn.servlet.HelloServlet</servlet-class>
</servlet>
<!--注册errorServlet(404)-->
<servlet>
<servlet-name>errorServlet</servlet-name>
<servlet-class>com.wsn.servlet.ErrorServlet</servlet-class>
</servlet>
<!--servlet的映射-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--404的映射-->
<servlet-mapping>
<servlet-name>errorServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
//结果:运行后,走localhost:8080/wsn/hello是可以进我们映射的指定页面,除此之外的任何地址都会跳转到我们自定义的404的页面,实现自定义的404页面。其实利用的就是‘固有的映射路径优先级最高’,其余的没设置的都走我们设定好的映射。
5、ServletContext(了解学习)
这一节下面的方法后面学习都会干掉,这里仅作为了解学习
web容器在启动的时候,为每个web程序都创建一个对应ServletContext对象,他代表了当前的web应用,凌驾于所有Servlet之上。
5.1、共享数据
共享数据:我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到。
假设有三个Servlet实现类,各自都有对应的映射互不影响,那么怎么做能让他们之间的数据共享呢,在认识ServletContext之前我们能想到的方式就是用IO操作,例如servlet1将数据用输出流保存在一个文件(中介)中,然后servlet2要用的时候就用输入流读取这个文件中的内容实现数据传输。
显然这种方式效率太低,所以我们可以用ServletContext去实现Servlet之间的数据共享。
具体操作:
1.首先我们需要创建一个放置数据的类
public class HellowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getServletContext(); Servlet上下文
String username = "wangshaonan";//数据
ServletContext context = this.getServletContext();//创建一个上下文context容器
//将一个数据以键值对的形式保存在SrevletContext中
context.setAttribute("username",username);//第一个参数是key,第二个参数是value
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.然后创建一个取出数据的类
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
//读取HelloServlet中存在SrevletContext中的数据
//创建上下文ServletContext对象
ServletContext context = this.getServletContext();
//context.getAttribute(key)通过key获得value
String username = (String) context.getAttribute("username");
//创建响应输出流对象
PrintWriter writer = resp.getWriter();
//将刚才get的数据打印在网页上
writer.print("名字是"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.配置注册和映射
<!-- hellowServlet注册 -->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.wsn.servlet.HellowServlet</servlet-class>
</servlet>
<!-- getServlet注册 -->
<servlet>
<servlet-name>getServlet</servlet-name>
<servlet-class>com.wsn.servlet.GetServlet</servlet-class>
</servlet>
<!-- hellowServlet映射 -->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!-- getServlet映射 -->
<servlet-mapping>
<servlet-name>getServlet</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
4.运行
当我们运行http://localhost:8080/wsn/get时发现我们存的数据是取不到的。
然后我们试着先运行存数据的页面http://localhost:8080/wsn/hello后再运行http://localhost:8080/wsn/get发现值正常取到了。
5.结论:ServletContext可以实现Servlet之间的数据共享,之间是存在先存后取的逻辑关系。
5.2、获得初始化参数
1.举例我们在web.xml里配置了jbdc连接数据库的初始化参数。
<!-- 设置初始化jdbc的url参数-->
<context-param>
<param-name>jdbcUrl</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
2.在ServletDemo03中用getInitParameter(String str)去获取初始化的那条参数。
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获得getServletContext()上下文
ServletContext context = this.getServletContext();
//getInitParameter(str)通过键(Str key)获取 一条 初始化参数。
String jdbcUrl = context.getInitParameter("jdbcUrl");
//将他响应在网页上方便看效果:
PrintWriter writer = resp.getWriter();
writer.print(jdbcUrl);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.注册映射ServletDemo03
<!--ServletDemo03注册 -->
<servlet>
<servlet-name>ServletDemo03</servlet-name>
<servlet-class>com.wsn.servlet.ServletDemo03</servlet-class>
</servlet>
<!--ServletDemo03注册 -->
<servlet-mapping>
<servlet-name>ServletDemo03</servlet-name>
<url-pattern>/sp</url-pattern>
</servlet-mapping>
4.运行,获取成功
5.3、请求转发
1.编写转发的ServletDemo04类
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//getRequestDispatcher(String url)转发的请求路径,参数里面是转发的映射路径
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/sp");
requestDispatcher.forward(req,resp);//上面那个只是设置了路径,只有执行forward(req,resp)才是转发,参数对应请求和响应的参数。
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.注册映射ServletDemo04类
<!--ServletDemo04注册 -->
<servlet>
<servlet-name>ServletDemo04</servlet-name>
<servlet-class>com.wsn.servlet.ServletDemo04</servlet-class>
</servlet>
<!--ServletDemo04映射 -->
<servlet-mapping>
<servlet-name>ServletDemo04</servlet-name>
<url-pattern>/zf</url-pattern>
</servlet-mapping>
3.运行,发现我们访问http://localhost:8080/wsn/zf时展示的页面是http://localhost:8080/wsn/sp的页面,实现了转发。
5.4、读取资源文件
5.4.1、配置资源位置问题
properties类:
- 在java目录下新建propereties。
- 在resource目录下新建properties。
发现:
1.在java目录下新建propereties的文件运行后无法正常打包,而在resource目录下新建properties的文件会打包。因为resource目录下的文件会被默认打包,而java目录下的properties不会被打包,解决办法在之前Maven中讲到过,需要在pom.xml文件中加入两段配置代码。
<build>
<resources>
<resource><!-- 允许resource下的文件都被打包,也可以不写,默认就会打包 -->
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource><!-- 允许java下的文件都被打包 -->
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
配置完之后再次运行两个地方的资源都会被正常的打包。
2.发现java和resource下的资源都被打包在了同一路径下:classes,我们俗称这个路径为calsspath(类路径)。
5.4.2、读取资源
思路:主要就是怎么样把资源文件变成流。getResourceAsStream()
1.在resource文件夹下新建一个db.properties配置文件
username=root
password=123456
2.编写获取资源的ServletDemo05的类
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();//获取上下文对象(只要是获得资源都用这个)
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");//获取资源变成一个流对象,传入的参数是资源路径的字符串。
//现在我们将获取的资源变成一个流,我们就可以使用properties对象去读取资源
Properties prop = new Properties();//获取Properties对象
prop.load(is);//加载资源,传入的是一个流对象
String user = prop.getProperty("username");//获取资源文件里的参数
String pwd = prop.getProperty("password");//获取资源文件里的参数
//响应到网页,方便查看结果
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3.注册映射ServletDemo05
<!--servletDemo05注册 -->
<servlet>
<servlet-name>servletDemo05</servlet-name>
<servlet-class>com.wsn.servlet.ServletDemo05</servlet-class>
</servlet>
<!--servletDemo05映射-->
<servlet-mapping>
<servlet-name>servletDemo05</servlet-name>
<url-pattern>/s5</url-pattern>
</servlet-mapping>
4.运行,发现资源正常得到读取展示。
6、HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象和代表响应的一个HttpServletResponse对象。
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应过去一些信息:找HttpServletResponse
6.1、简单将方法分个类(源码)
负责像浏览器发送数据的方法
//ServletResponse源码的方法
ServletOutputStream getOutputStream() throws IOException;//输出字节流
PrintWriter getWriter() throws IOException;//输出字符流
负责向浏览器发送一些请求头的方法(举例:设置编码和字符集)
//ServletResponse源码的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
//HttpServletResponse源码的方法
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
设置状态码的常量
//HttpServletResponse源码的常量
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
6.2、实现下载文件
-
下载文件,我们平时在浏览器下载一些资源时,点击下载 就会跳转到一个页面,然后开始下载,就是用这个实现的。
- 获取下载文件的路径。
- 获取下载文件的文件名。
- 设置想办法让浏览器能够支持下载我们需要的东西。
- 获取下载的输入流。
- 创建缓冲区(Buffered)
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区。
- 使用OutputStream将缓冲区的数据输出到客户端。
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 获取下载文件的路径。
//通过上下文的getRealPath获取绝对路径
String realPath ="E:\\Study\\java\\javaweb-02-servlet\\httpresponse\\src\\main\\resources\\liuchang.jpg";
System.out.println("下载文件的路径:"+realPath);
//2. 获取下载文件的文件名。
//通过字符串的substring方法截取最后一个\符号的后面一个
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
//3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西。中文文件名用URLEncoder.encode编码,否则会乱码
resp.setHeader("Content-Disposition","attachment;filename"+ URLEncoder.encode(fileName,"utf-8"));
//4. 获取下载的输入流。
FileInputStream fis = new FileInputStream(realPath);//把文件变成流
//5. 创建缓冲区(Buffered)
byte[] buffer = new byte[1024];
int length = 0;
//6. 获取OutputStream对象
ServletOutputStream ops = resp.getOutputStream();
//7. 将FileOutputStream流写入到buffer缓冲区。使用OutputStream将缓冲区的数据输出到客户端。
while ((length=fis.read(buffer))>0){
ops.write(buffer,0,length);
}
fis.close();
ops.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.3、验证码功能
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器3秒刷新一次
resp.setHeader("refresh","3");
//在内存创建一个图片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) image.getGraphics();//笔
//设置图片的背景颜色
g.setColor(Color.pink);
g.fillRect(0,0,80,20);//填充背景颜色
//给图片写数据
g.setColor(Color.BLUE);//换颜色
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Prama","no-cache");
//把图片写给浏览器
ImageIO.write(image, "jpg", resp.getOutputStream());
}
//生成随机数的方法
private String makeNum(){
Random random = new Random();
String str = random.nextInt(9999999)+"";//八位数
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-str.length(); i++) {
sb.append("0");
}
String num=sb.toString()+str;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.4、重定向(需掌握)
一个web资源B收到客户端A的请求后,他会通知客户端A去访问另外一个web资源C,这个过程叫重定向。
常见使用场景:
- 用户登录
void sendRedirect(String var1) throws IOException;
测试代码:
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
原理其实就是:
resp.setHeader("location","/wsn/img")
resp.setStatus(302);
*/
resp.sendRedirect("/wsn/img");//sendRedirect重定向,当web访问这个servlet时,会跳转到/wsn/img
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
运行后red后跳转到img。
面试题:请你聊一聊重定向和转发的区别?
相同点:
- 页面都会实现跳转。
不同点:
- 请求转发的时候,url不会发生变化。
- 重定向的时候,url地址栏会发生变化。
6.5、重定向表单测试(需掌握)
1.将首页index.jsp设置一个简单的登录表单,当点击提交时实现重定向跳转到success.jsp,这里注意action提交的路径问题。
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径需要寻找到项目路径--%>
<%--${pageContext.request.contextPath}代表当前项目路径--%>
<form action="${pageContext.request.contextPath}/login" method="get">
<span>用户名:</span>
<input type="text" name="username"><br>
<span>密码:</span>
<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>
2.写一个简单的success.jsp,作为提交成功的展示页面
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>
3.编写重定向的RequestServlet
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String user = req.getParameter("username");//获取用户名
String pwd = req.getParameter("password");//获取密码
System.out.println(user+":"+pwd);//输出到控制台
//重定向注意路径问题。否则404
resp.sendRedirect("/wsn/success.jsp");//处理完成,重定向至success.jsp
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,我们可以获取到客户端的所有信息。
7.1、获取参数,并请求转发
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置请求编码
req.setCharacterEncoding("utf-8");
//获取表单数据
String user = req.getParameter("username");//获取用户名
String pwd = req.getParameter("password");//获取密码
String[] checkval = req.getParameterValues("hobbys");//获取checkbox的数据
//输出到控制台
System.out.println("==============================================================");
System.out.println("用户名:"+user);
System.out.println("密码:"+pwd);
System.out.println(Arrays.toString(checkval));
System.out.println("==============================================================");
resp.setCharacterEncoding("utf-8");
//通过请求转发
req.getRequestDispatcher(req.getContextPath()+"/success.jsp").forward(req,resp);
// //重定向转发
// resp.sendRedirect(req.getContextPath()+"/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
面试题:请你聊一聊重定向和转发的区别?
相同点:
- 页面都会实现跳转。
不同点:
- 请求转发的时候,url不会发生变化。状态码:307
- 重定向的时候,url地址栏会发生变化。状态码:302