天天看点

javaWeb学习笔记6

作者:Date202209130134

6. Servlet

6.1、 Servlet简介

·Servlet就是Sun公司开发动态Web的一门技术

·Sun在这些API中提供一个接口叫做:Servlet,如果你要开发一个Servlet程序,只需要完成两个小步骤:

·编写一个类,实现Servlet接口

·把开发好的java类部署到web服务器中

把实现了Servlet接口的java程序叫做Servlet

Servlet接口Sun公司默认有两个实现类HttpServlet,GenericServlet

6.2、HellowServlet

1.构建一个Maven项目

javaWeb学习笔记6

2.下一步写好名称和路径。

javaWeb学习笔记6

3.删除Src,以后我们的学习就在这个项目使用Moudel。空的工程就是主工程。

javaWeb学习笔记6

4.找一些依赖导入

javaWeb学习笔记6

5.复制导入到Maven中

javaWeb学习笔记6
javaWeb学习笔记6

6.新建模块

7.因为Servlet是web模块,所以先建一个Web模块

javaWeb学习笔记6

8.输入模块名称,下一步

javaWeb学习笔记6

9.保持好Maven主路径,错了要修改

javaWeb学习笔记6

10.关于Maven父子工程的理解

javaWeb学习笔记6

·父项目会出现

·子项目会出现

javaWeb学习笔记6

父项目中的java---->子项目能直接使用

子项目的父项目不能使用

11.新建目录,构成初步项目目录结构

javaWeb学习笔记6

12.根据自动提示新建src\main\java。

javaWeb学习笔记6
javaWeb学习笔记6

13.根据自动提示新建src\main\resources。

14.可忽略的步骤,添加部署web模块,修改部署路径(为了和狂神目录结构一致,因为没配置好运行环境,自动创建没弄好,这里是手动设置的一步,到后面才发现问题原因。)

javaWeb学习笔记6

15.可忽略的步骤,配置web资源目录,(为了和狂神目录结构一致,因为没配置好运行环境,自动创建没弄好,这里是手动设置的一步,到后面才发现问题原因。)

javaWeb学习笔记6

16.可忽略的步骤,新建index.Jsp文件(为了和狂神目录结构一致,因为没配置好运行环境,自动创建没弄好,这里是手动设置的一步,到后面才发现问题原因。)

javaWeb学习笔记6
javaWeb学习笔记6

17.将想要部署的tomcat服务器版本的根路径复制到web.xml,(为了更好地兼容即将部署的服务器)

javaWeb学习笔记6

18.完成后结果如下图所示

javaWeb学习笔记6

19.编写一个Servlet程序,一个Servlet程序一定要实现Servlet接口。

新建一个包和类

javaWeb学习笔记6

20.继承HttpServlet

javaWeb学习笔记6

21.接口方法关系图

javaWeb学习笔记6

22.编写完类

javaWeb学习笔记6

23.编写映射

javaWeb学习笔记6

我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务注册我们写的Sevelt

24.配置tomcat,启动部署项目

25.遇到问题!!!

发现,无法启动tomcat,无法读取jar包,原因,我在更新Maven路径后,没有更改配置。

解决方案:

重新配置Java版本和JDK路径,jdk环境变量

重新配置Maven版本和路径,重新配置Maven环境变量

在IDEA中重新更改Maven设置

6.3、 Servlet原理

servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:

javaWeb学习笔记6
javaWeb学习笔记6

6.4、 Mapping原理

1.一个Servlet可以指定一个映射路径,如访问“localhost:8081/webapp/use”

javaWeb学习笔记6

2.一个Servlet可以指定多个映射路径,

如访问“localhost:8081/webapp/use”,“localhost:8081/webapp/use1”

“localhost:8081/webapp/use2”等等

javaWeb学习笔记6

3.一个Servlet可以指定通用映射路径

如访问“localhost:8081/webapp/use/任意字符”

javaWeb学习笔记6
javaWeb学习笔记6

4.默认路径,会盖住index.jsp作用,最好不要这么写

5.指定一些后缀或者前缀......

如:访问"localhost:8081/webapp/后缀名为".liZhaoYuan"

javaWeb学习笔记6

6.优先级问题

指定了固有的映射路径的优先级最高,如果找不到就会走默认的。

6.5、 ServletContext

web容器在启动时,它会为每一个web程序都创建一个对应的Servlet对象,它代表了当前的web应用。

·共享数据

我在这个Servlet保存的数据,可以在另外的一个Servlet中拿到;

原理图:

javaWeb学习笔记6

6.5.1、一个共享数据的Servlet程序

(1)保存数据的程序

package com.kuang.servlet;

import javax.servlet.ServletContext;

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 HellowServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//this.getInitParameter();--------->初始化参数,也可以在web.xml中配置

//this.getServletConfig();---------->Servlet配置

//this.getServletContext();--------->Servlet上下文

req.setCharacterEncoding("UTF-16");

resp.setCharacterEncoding("UTF-16");

ServletContext Context = this.getServletContext(); //创建了一个 ServletContext 对象,这个对象每个web程序都有

String Name="李照垣"; //假设有一个数据

Context.setAttribute("userName",Name); //以键值对的形式存储Name对象,("key",value),就将一个数据保存到了ServletContext当中

// //用响应头把键写出去

String userName = (String)Context.getAttribute("userName");

resp.getWriter().print("asda");

// System.out.println("hellow");

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req,resp);

}

}

(2)读取数据的程序

package com.kuang.servlet;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

//共享数据,在这个程序中读取HellowServlet保存的数据

public class GetServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

ServletContext Context = this.getServletContext(); //建立ServletContext对象

String userName = (String) Context.getAttribute("userName"); //通过键获取值,因为我们知道保存的是String,强转类型后赋值

resp.setContentType("text/html"); //设置文本类型,通过浏览器可见

resp.setCharacterEncoding("utf-8"); //设置编码格式,通过浏览器可见

resp.getWriter().print("名字"+userName);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}

6.5.2、获取初始化参数

1.在web.xml中写入以下配置

<!-- 设置web程序初始化参数-->

<context-param>

<param-name>url</param-name>

<param-value>jdbc:mysql://localhost:3306</param-value>

</context-param>

2.使用Servlet程序获取

package com.kuang.servlet;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.util.Properties;

//一个获取web程序配置的初始化参数

public class ServletDemo03 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

ServletContext Context = this.getServletContext(); //建立ServletContext对象

String url = Context.getInitParameter("url"); //---->获取web.xml中的初始化参数,键值“url”

resp.getWriter().print(url); //---->打印web.xml中的初始化参数,值“jdbc:mysql//localhost:3306”

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}

6.5.3、请求转发

1.过程图:

javaWeb学习笔记6

A访问只能通过B访问C的资源

package com.kuang.servlet;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletContext;

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 ServletDemo04 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

ServletContext Context = this.getServletContext(); //建立ServletContext对象

System.out.println("进入了Demo04");//----------->测试程序是否进入这个doget方法

RequestDispatcher requestDispatcher = Context.getRequestDispatcher("/getIn");//getRequestDispatcher-->获取请求转发方法路径,// 有一个参数,这个参数就是我们要转发的地址

requestDispatcher.forward(req,resp);//调用forward()方法实现请求转发,所有的请求是第一个参数,所有的响应是第二个参数,它起到转发的作用

//

// Context.getRequestDispatcher("/getIn").forward(req,resp);//----->上面两行语句合并写法,

// //这样程序就通过Demo04程序访问了Demo03页面,路访问径是/getRe,但是页面访问是Demo03

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}

6.5.4、读取资源文件

1.Properties类

·在java目录下新建properties

·在resource目录下新建properties

javaWeb学习笔记6

发现都被打包到同一路径下

javaWeb学习笔记6

我们俗称这个路径为类路径“classespath;”(没有aa.properties是因为资源打包失败,习惯大于约束,在pom.xml的building中配置)

知道路径后就可以读取了

思路:需要一个文件流,方法很多这只举了一个。

2.读取db.properties资源文件

package com.kuang.servlet;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.InputStream;

import java.util.Properties;

//一个用来读取资源文件的程序

public class ServletDemo05 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//------这个方法把资源变成一个流,参照打包的写相对路径,这里”/“的意思是指向Servlet-02这个程序,

// 访问Servlet-02程序下的WEB-INF的classes的db.properties

Properties properties = new Properties(); //新建一个properties类

properties.load(resourceAsStream); //加载上面的流

String username = properties.getProperty("username");//获取资源的键

String password = properties.getProperty("password");//获取资源的键

resp.getWriter().print(username+":"+password); //响应到页面

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}

6.6、HttpServletResponse

6.6.1、HttpServletResponse的一些方法

web服务器收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletresponse;

·我们如果要获取客户端请求过来的参数:找HttpServletRequet

·如果要给客户端响应一些信息:找HttpServletResponse

1.简单分类

负责向浏览器发送数据的方法

·ServletOutputStream getOutputStream() throws IOException;

写一般流

·PrintWriter getWriter() throws IOException;

写中文用,其他的用会造成字符串损失。

负责向浏览器发送响应头的方法

· void setCharacterEncoding(String var1);

设置响应的编码

· void setContentLength(int var1);

设置响应的字符串长度

· void setContentLengthLong(long var1);

设置长度?

· void setContentType(String var1);

设置类型

· 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);

响应的状态码:

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.6.2、常见应用

1.向浏览器输出信息

2.下载文件

字符串处理

·要获取下载的文件的路径

·下载的文件名

·设置想办法让浏览器能够支持我们下载的东西

javaWeb学习笔记6

resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename));

·获取下载文件的输入流

IO流操作

·创建缓冲区

·获取OutputStream对象

·将FileOutputStream流写入到buffer缓冲区

·使用OutputStream将缓冲区中的数据输出到客户端

6.6.3、浏览器让客户端下载文件

package com.kuang.servlet;

import javax.servlet.ServletException;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.FileInputStream;

import java.io.IOException;

import java.net.URLEncoder;

//实现让浏览器可以下载文件

public class FileServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

// 字符串处理

//·要获取下载的文件的路径,假设有这个文件

// String realPath = this.getServletContext().getRealPath("/1.jpg");

String realPath = "C:\\Users\\a\\Desktop\\新项目\\javaweb-02-Servlet\\response\\target\\classes\\1.jpg";

System.out.println("获取下载的文件的路径"+realPath);

//·下载的文件名

String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);//------->这是一个极其精巧的方法,使用substring截取字符串,从“/”的后一位开始获取后缀子串。

//·设置想办法让浏览器能够支持我们下载的东西,百度搜索web下载文件的头消息,获取resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename));

//浏览器能够支持("Content-disposition")我们需要下载的东西

resp.setHeader("Content-disposition","attachment;filename="+filename);//-->通过设置响应头让浏览器给客户端下载文件

// resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));--->当文件名有中文,需要进行编码转换

//·获取下载文件的输入流

FileInputStream in = new FileInputStream(realPath);

//IO流操作

//·创建缓冲区

int len=0;

byte[] buffer = new byte[4096];

//·获取OutputStream对象

ServletOutputStream out = resp.getOutputStream();

//·将FileOutputStream流写入到buffer缓冲区

while ((len=in.read(buffer))>0){

out.write(buffer,0,len);

}

in.close();

out.close();

//·使用OutputStream将缓冲区中的数据输出到客户端

resp.getWriter().print(out);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}

6.6.4、验证码功能

·前端实现

·后端实现,需要使用java的图片类,生产一个图片

package com.kuang.servlet;

import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.io.IOException;

import java.util.Random;

//实现验证码的程序

public class ImageServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//如何让浏览器5秒自动刷新一次

resp.setHeader("refresh","3");

//在内存中创建一个图框,BufferedImage(图片的长,图片的宽,图片的颜色格式);

BufferedImage Image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);

//得到到笔,绘制2D图片

Graphics2D graphics =(Graphics2D) Image.getGraphics();//---->graphics想成一支笔

//设置图片的背景图片,通过参数设置笔芯为白色

graphics.setColor(Color.white);

//填充一个矩形

graphics.fillRect(0,0,80,20);

//给图片写数据,通过参数设置笔芯为蓝色

graphics.setColor(Color.BLUE);

//设置字体的类型,BOLD粗体,大小20像素

graphics.setFont(new Font(null,Font.BOLD,20));

//画一些东西,在任意的位置开始绘制字符串makeNum

graphics.drawString(makeNum(),0,20);

//告诉浏览器这个请求用图片的方式打开

resp.setContentType("image/jpg");

//网站存在缓存,不让浏览器缓存,在百度搜索"响应头属性exprise -1"

resp.setDateHeader("exprise",-1);

//设置缓存控制属性

resp.setHeader("Cache-Control","no-cache");

//设置属性,具体我不清楚是啥,作用也是缓存控制

resp.setHeader("Pragma","no-cache");

//把图片写给浏览器ImageIO专门用来些图片

boolean write = ImageIO.write(Image,"jpg", resp.getOutputStream());

}

//生成随机数

private String makeNum(){

Random random = new Random();

//生成七位整数的验证码,(添加一个空的字符串,自动引入局部变量,转化成字符串)

String num = random.nextInt(9999999) + "";

//若生成的随机数位数小于7位,生成足够的0,用来补位数

StringBuffer sB = new StringBuffer();

for (int i = 0; i < 7-num.length(); i++) {

sB.append("0");

}

//补足位数

num = sB.toString() + num;

return num;

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}

6.6.5、页面重定向

javaWeb学习笔记6

一个web资源收到客户端请求后,他会通知客户端去访问另外一个web资源,这个过程叫做重定向。

常见场景:

·用户登陆

·void sendRedirect(String var1) throws IOException;

面试题:请你聊聊重定向和转发区别:

相同点:页面都会跳转

不同点:

·请求转发的时候,页面url不会发生变化

·在重定向的时候,页面url会发生变化

页面重定向

package com.kuang.servlet;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

//resp.sendRedirect()--------->实现页面重定向的方法

public class Redirect extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

// 这两行代码等价于resp.sendRedirect()

// resp.setHeader("Location","/img");

// resp.setStatus(302);

resp.sendRedirect("/webapp/img");//resp.sendRedirect()--------->实现页面重定向的方法,参数就是重定向的位置

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req,resp);

}

}

6.7、 HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest方法,获取客户端的所有信息。

javaWeb学习笔记6

request的一些方法:

6.7.1、获取前端传入的参数

package com.kuang.servlet;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

//处理前端请求的程序,获取前端传入的参数,前端页面是index.xml

public class RequestTest extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

System.out.println("进入这个请求了");

//处理请求,使用getParameter()方法通过参数获取前端的值

String username = req.getParameter("username");

String password = req.getParameter("password");

//输出获取的值

System.out.println(username+":"+password);

//获取到账户密码进行页面重定向

resp.sendRedirect("/webapp/success.jsp");

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req,resp);

}

}

6.7.2、获取参数,请求转发

package com.kuang.servlet;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.lang.reflect.Array;

import java.util.Arrays;

//获取前端的参数,并实现请求转发.

public class LoginServlet extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

resp.setCharacterEncoding("utf-8");

String username = req.getParameter("username");//---->获取index.jsp的username

String password = req.getParameter("password");//---->获取index.jsp的password

String[] hobbys = req.getParameterValues("hobbys");//---->以字符数组获取多选框“hobbys”的值

System.out.println("===============================================================");

System.out.println(username);//---->打印输出用户名

System.out.println(password);//---->打印输出密码

System.out.println(Arrays.toString(hobbys));//----->以字符串打印输出数组

System.out.println("===============================================================");

// resp.sendRedirect("/success.jsp");//重定向转发

req.setCharacterEncoding("utf-8");

req.getRequestDispatcher("/success.jsp").forward(req,resp);//请求转发

// this.getServletContext();//共享

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doGet(req, resp);

}

}