Java-Servlet技术入门笔记

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

System.out.println(“hello doGet”);

//由于GenericServlet类中的config没有保存值,所以getServletConfig()方法出现空指针异常

ServletConfig servletConfig = getServletConfig();

System.out.println(“Servlet程序的别名为” + servletConfig.getServletName());

}

}

三、ServletContext类


1、什么是ServletContext

代表整个web工程,可以与程序的容器(Tomcat服务器)通信

  1. ServletContext是一个接口,它表示Servlet上下文对象

  2. 一个web工程,只有一个ServletContext对象实例

  • ServletConfig对象取决于有多少个Servlet程序(一一对应,只能访问到配置文件中属于自己的配置信息)

  • 但ServletContext对象还能访问配置文件中上下文参数

  1. ServletContext对象是一个域对象

  2. ServletContext对象是在web工程部署启动的时候创建,在web工程停止的时候销毁

什么是域对象

域对象指的是可以像Map一样存取数据的对象

这里的域指的是存取数据的操作范围——整个web工程

| | 存数据 | 取数据 | 删除数据 |

| :-: | :-: | :-: | :-: |

| Map | put() | get() | remove() |

| 域对象 | setAttribute() | getAttribute() | removeAttribute() |

2、获取ServletContext对象的方法

  1. 通过HttpServletRequest对象获取
  • request.getServletContext();
  1. 通过HttpServlet获取
  • this.getServletContext();
  1. 通过servletConfig对象获取
  • servletConfig.getServletContext();

@WebServlet(“/getcontext”)

public class GetContextServlet extends HttpServlet {

@Override

p

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

//通过HttpServlet获取

ServletContext servletContext1 = this.getServletContext();

//通过HttpServletRequest req对象获取

ServletContext servletContext2 = req.getServletContext();

//通过servletConfig对象获取

ServletContext servletContext3 = this.getServletConfig().getServletContext();

System.out.println(servletContext1);

System.out.println(servletContext2);

System.out.println(servletContext3);

}

}

3、ServletContext类的四大作用

  1. 获取web.xml中配置的上下文参数context-param

  2. 获取当前工程路径,格式:/工程路径

  3. 获取工程部署在服务器硬盘上的绝对路径

  4. 像Map一样存取数据

1)获取信息
<?xml version="1.0" encoding="UTF-8"?>

<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”>

username

context

password

root

HelloServlet

com.first.cyh.HelloServlet

username

root

url

jdbc:mysql//localhost/test

HelloServlet

/hello

public class ContextServlet extends HttpServlet {

@Override

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

//获取配置文件中的上下文参数

ServletContext context = getServletConfig().getServletContext();

System.out.println(context.getInitParameter(“username”));

System.out.println(context.getInitParameter(“password”));

//获取当前的工程路径,格式:/工程路径

System.out.println(context.getContextPath());

//获取工程部署后在服务器硬盘的绝对路径

/*

getRealPath()返回一个给定虚拟路径的真实路径

这个斜杆表示站点的根,也就是获取网站的根目录,即工程部署路径

而/css就是表示该路径下的css文件夹

*/

System.out.println(context.getRealPath(“/”));

System.out.println(context.getRealPath(“/css”));

System.out.println(context.getRealPath(“/jpg”));

}

}

上述程序执行后会返回

context

root

/myfirst

E:\eclipse-workspace\Javaweb-servlet\out\artifacts\Javaweb_servlet_war_exploded

E:\eclipse-workspace\Javaweb-servlet\out\artifacts\Javaweb_servlet_war_exploded\css

E:\eclipse-workspace\Javaweb-servlet\out\artifacts\Javaweb_servlet_war_exploded\jpg

而为什么获得的路径为什么和我们项目创建的路径不一样,在我的另一篇博文(web工程部署路径与getServletConfig().getRealPath()_得过且过的勇者y的博客-CSDN博客中详细讲解了

为什么需要获取工程存放路径呢?

因为项目在本地开发后,项目中的文件路径写的是本地的路径。然而当项目部署到其他设备后,物理地址发生改变,就会导致文件找不到而报错。

2)存取数据

public class ContextServlet1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//GenericServlet获取获取ServletContext对象的方式,等同于getServletConfig().getServletContext()

ServletContext servletContext = getServletContext();

System.out.println(“保存之前Context1中获取域数据key1的值是:” + servletContext.getAttribute(“key1”));

//存数据

servletContext.setAttribute(“key1”,“value1”);

//取数据

System.out.println(“Context1中获取域数据key1的值是:” + servletContext.getAttribute(“key1”));

}

}

public class ContextServlet2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

ServletContext servletContext = getServletContext();

System.out.println(“Context2中获取域数据key1的值是:” + servletContext.getAttribute(“key1”));

}

}

以下为两次访问ContextServlet1输出的结果(没有重新部署)

保存之前Context1中获取域数据key1的值是:null

Context1中获取域数据key1的值是:value1

保存之前Context1中获取域数据key1的值是:value1

Context1中获取域数据key1的值是:value1

重新部署后再次访问ContextServlet1输出的结果

保存之前Context1中获取域数据key1的值是:null

Context1中获取域数据key1的值是:value1

这是因为ServletContext对象是在web工程部署启动的时候创建,在web工程停止的时候销毁,所以没有重新部署的话key1在set之后就一直存在,所以第二次及以后访问时都会有保存之前Context1中获取域数据key1的值是:value1,而重新部署之后第一次访问就又是null

而前文中的getInitParameter()获取的数据是保存在xml文件中的,故一直存在

总结

setAttribute方式存参数相当于把数据存在内存中,工程停止时消失,而xml方式存参数则是持久化到硬盘中

getInitParameter获得的是xml方式存储的参数

getAttribute获得的是setAttribute方式存储的参数

而当我们已经访问完ContextServlet1后再访问ContextServlet2,会输出

Context2中获取域数据key1的值是:value1

这是因为一个web工程,只有一个ServletContext对象实例,两个Servlet程序中的servletContext其实是相同的,如果我们在两个程序中都输出servletContext这个对象,值是相同的

所以当第一个Servlet程序设置完key1参数后,第二个自然也可以使用它

3)获取MIME类型

MIME类型是在互联网通信过程中定义的一种文件数据类型,格式为:大类型/小类型,如text/html,image/jpg

用处:响应头中content-type需要返回响应体的数据类型,这时候就要获取我们返回的数据的MIME类型

获取方法:通过文件后缀名在tomcat配置文件(tomcat的conf目录下的web.xml)中寻找对应的MIME类型(因为context对象可以与tomcat进行通信)

@WebServlet(“/getmime”)

public class GetMime extends HttpServlet {

@Override

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

ServletContext servletContext = this.getServletContext();

//定义文件名

String filename = “a.jpg”;

//通过文件名的后缀获取对应MIME类型

String mimeType = servletContext.getMimeType(filename);

System.out.println(mimeType);

}

}

返回image/jpeg

四、HttpServletRequest类


1、作用

每次只要有请求进入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():获取请求转发对象

public class RequestAPIServlet extends HttpServlet {

@Override

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

System.out.println(“URI–>” + req.getRequestURI());//URI–>/myfirst/req

System.out.println(“URL–>” + req.getRequestURL());//URL–>http://localhost:8080/myfirst/req

//如果以localhost访问,则返回0:0:0:0:0:0:0:10:0:0:0:0:0:0:1

//以127.0.0.1访问,则返回127.0.0.1

//以真实ip访问,则返回真实ip

System.out.println(“HOST–>” + req.getRemoteHost());

//HEADER–>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30

System.out.println(“METHOD–>” + req.getMethod());//GET

System.out.println(“HEADER–>” + req.getHeader(“User-Agent”));

}

}

public class RequestGetParameter extends HttpServlet {

@Override

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

System.out.println(“用户名” + req.getParameter(“username”));

System.out.println(“密码” + req.getParameter(“password”));

String[] hobbies = req.getParameterValues(“hobby”);

try{

System.out.println(“兴趣爱好” + Arrays.asList(hobbies));

}catch (Exception e){

System.out.println(e.getStackTrace());

}

}

}

注意点

如果使用的是post请求,则需要设置字符集,否则在post请求参数是中文会出现乱码

req.setCharacterEncoding(“UTF-8”);

且此设置要在所有获取参数语句(不管会不会获取中文)的前面设置

只要有获取参数的语句在设置语句前面,不管这条语句会不会获取中文,都会导致设置失效,从而使那些在设置语句后的获取参数语句同样会乱码

3、请求转发

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e8l4Ttgx-1636276443283)(C:\Users\Ken-Chy\Desktop\大二临时\00自学部分\后端\笔记\请求转发.png)]

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

//处理业务

//doSth

username += “ahahha”;

System.out.println(“业务1完成,username=” + username);

//处理完业务,在request域中存储数据

req.setAttribute(“username”,username);

//询问servlet2的路径

//请求转发必须以斜杆开始,表示http://ip:8080/工程名/

RequestDispatcher requestDispatcher = req.getRequestDispatcher(“/servlet2”);

//带着请求走向servlet

requestDispatcher.forward(req,resp);

}

}

public class Servlet2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//查看请求带来的数据

String username = request.getParameter(“username”);

System.out.println(“servlet2中请求带来的数据:” + username);

//获取servlet1传入的数据

Object obj = request.getAttribute(“username”);

System.out.println(“servlet1传入的数据:”+obj);

//处理自己的业务

System.out.println(“业务处理完成”);

}

}

请求转发的特点

  1. 浏览器地址栏没有发生变化

  2. 它们是一次请求

  3. 它们共享Request域中的数据

  4. 可以转发到WEB-INF目录下

  5. 不可以访问工程以外的资源

4、base标签的作用

设置页面相对路径工作时参照的地址,href属性就是参数的地址值

应用场景

如果页面采用请求转发,跳转页面时地址不会发生改变,这时候在跳转到的页面中如果访问了设置成相对路径的地址,则会发生请求错误,因为如果没有设置base标签,默认相对地址会参照于当前浏览器的地址

5、web中’/‘的不同意义

在web中,’/'是一种绝对路径

如果被浏览器解析,得到的地址是:http://ip:port/

  • <a href="/"></a>

如果被服务器解析,得到的地址是:http://ip:port/工程路径

  • <url-pattern>/servlet1</url-pattern>

  • servletContext.getRealPath("/")

  • request.getRequestDispatcher("/")

特殊情况:response.sendRediect(“/”)是把斜杠发给浏览器解析,故得到的是http://ip:port/

五、HttpServletResponse类


1、作用

HttpServletResponse类和HttpServletRequest类一样,每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息。我们如果需要设置返回给客户端的信息,都可以通过它来设置。

2、两个输出流的说明

  • 字节流:getOutputStream()——常用于下载(传递二进制数据)

  • 字符流:getWrite()——常用于回传字符串(常用)

两个流同时只能使用一个,否则会报错

3、如何往客户端回传数据

回传字符串

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//设置服务器字符集

response.setCharacterEncoding(“UTF-8”);

//设置浏览器字符集

response.setHeader(“Content-Type”,“text/html;charset=UTF-8”);

PrintWriter writer = response.getWriter();

writer.write(“哈哈”);

}

设置字符集也可以使用以下方法

response.setContent-Type("text/html;charset=UTF-8")

此法会同时设置服务器和浏览器的字符集,并设置响应头

以上方法都应该在获取输出流之前调用

通过字节流回传字符串

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setContentType(“txt/html;charset=utf-8”)

PrintWriter writer = response.getOutputStream();

//获取字符串的字节数组

writer.write(“哈哈”.getBytes(“utf-8”));

//默认编码是本机编码,也可以自己设置编码

}

4、请求重定向

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aBJZQXEi-1636276443285)(C:\Users\Ken-Chy\Desktop\大二临时\00自学部分\后端\笔记\请求重定向.png)]

public class Response1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//第一种方法

/*

System.out.println(“我曾来过”);

//设置状态码302,表示重定向(已搬迁)

response.setStatus(302);

//设置响应头,说明新的地址在哪

response.setHeader(“Location”,“http://localhost:8080/myfirst/response2”);

*/

//第二种方法(推荐使用)

response.sendRedirect(“https://www.baidu.com”);

}

}

public class Response2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setHeader(“Content-Type”,“text/html;charset=UTF-8”);

response.getWriter().write(“欢迎您的到来”);

}

}

请求重定向的特点

  1. 浏览器地址栏会发生变化

  2. 两次请求

  3. 不共享Request域中的数据

  4. 不能访问WEB-INF下的资源

  5. 可以访问工程外的数据

六、乱码问题详解


1、乱码原因

服务器编码和浏览器端解码使用的字符集不一致

浏览器端默认使用的编码和当前操作系统的语言环境有关,如果是中文的windows系统则默认是GBK或gb2312

如果服务器中字符流是自己new创建出来的,则也是与本机字符集一致,不会乱码

而当服务器通过response.getWriter()获取字符输出流,这个输出流是通过tomcat返回的,tomcat使用的编码是ISO-8859-1

2、解决方法

获取流对象之前,设置流的默认编码

response.setCharacterEncoding("utf-8");

告诉浏览器服务器发送的消息体数据的编码,建议浏览器使用该编码解码

response.setHeader("context-type", "txt/html;charset=utf-8")

简单形式

response.setContentType(“txt/html;charset=utf-8”);

七、验证码的实现


本质:图片

目的:防止恶意表单注册

步骤:

  1. 创建一个对象,在内存中生成图片(验证码图片对象)

  2. 美化图片

  3. 将图片输出到页面展示

@WebServlet(“/checkcode”)

public class CheckCode extends HttpServlet {

int width = 100;

int height = 50;

@Override

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

//创建验证码图片对象

BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

//美化图片

//填充背景色

Graphics g = image.getGraphics();//画笔对象

g.setColor(Color.PINK);//设置画笔颜色

g.fillRect(0,0,width,height);

//画边框

g.setColor(Color.BLUE);

g.drawRect(0,0,width-1,height-1);

String str=“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890”;

Random random = new Random();

for(int i = 1; i <= 4; i++){

int index = random.nextInt(str.length());

//获取随机字符

char ch = str.charAt(index);

//生成验证码

g.drawString(ch+“”,width/5*i,height/2);

}

//画干扰线

for(int i = 0; i < 6; i++){

int x1 = random.nextInt(width);

int x2 = random.nextInt(width);

int y1 = random.nextInt(height);

int y2 = random.nextInt(height);

g.drawLine(x1,y1,x2,y2);

}

//将图片输出到页面展示

ImageIO.write(image,“jpg”,resp.getOutputStream());

}

}

八、文件下载的实现


1、需求

  1. 页面显示超链接

  2. 点击超链接后弹出下载提示框或直接下载(取决于浏览器)

  3. 完成图片文件下载

2、分析

  1. 默认情况下:超链接指向的资源如果能被浏览器解析(如图片),则直接在浏览器中展示,如果不能解析(如视频),则弹出下载提示框(有的浏览器不会弹出,自动下载)

  2. 我们想要实现任何资源都弹出下载提示框

  3. 使用响应头设置资源的打开方式:content-disposition:attachment;filename=xxx(有的浏览器处理attachment不一定会弹出提示框)

  • attachment表示以附件的形式,filename表示文件名称

3、步骤

  1. 定义页面,编辑超链接href属性,指向servlet,传递资源名称filename

  2. 定义servlet

  3. 获取文件名称

  4. 使用字节输入流加载文件进内存

  5. 找到文件的服务器路径

  6. 用字节流关联

  7. 指定response的响应头

  8. 设置响应头类型

  9. 设置响应头打开方式

  10. 将数据写出到response输出流

@WebServlet(“/download”)

public class DownloadServlet extends HttpServlet {

@Override

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

//获取请求参数,文件名称

String filename = req.getParameter(“filename”);

//获取servletContext对象以获取文件的真实路径

ServletContext servletContext = this.getServletContext();

String realPath = servletContext.getRealPath(“/jpg/” + filename);

//用字节流关联文件

FileInputStream in = new FileInputStream(realPath);

//获取文件对应的MIME类型以设置响应头类型

String mimeType = servletContext.getMimeType(filename);

resp.setHeader(“content-type”,mimeType);

//设置响应头的打开方式

resp.setHeader(“content-disposition”,“attachment;filename=” + filename);

//将输入流的数据写出到输出流中

ServletOutputStream outputStream = resp.getOutputStream();

byte[] buff = new byte[1024 * 8];

int len = 0;

//read()读取一个字节,read(byte b[])读取b.length个字节的数据到b数组中,并返回读取到的字节数,如果没有字节可读了,即read()督导文件末尾了,则返回-1

while((len = in.read(buff)) != -1){

//public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流

outputStream.write(buff,0,len);

}

in.close();

}

}

复习的面试资料

这些面试全部出自大厂面试真题和面试合集当中,小编已经为大家整理完毕(PDF版)

  • 第一部分:Java基础-中级-高级

image

  • 第二部分:开源框架(SSM:Spring+SpringMVC+MyBatis)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 第三部分:性能调优(JVM+MySQL+Tomcat)

image

  • 第四部分:分布式(限流:ZK+Nginx;缓存:Redis+MongoDB+Memcached;通讯:MQ+kafka)

image

  • 第五部分:微服务(SpringBoot+SpringCloud+Dubbo)

image

  • 第六部分:其他:并发编程+设计模式+数据结构与算法+网络

image

进阶学习笔记pdf

  • Java架构进阶之架构筑基篇(Java基础+并发编程+JVM+MySQL+Tomcat+网络+数据结构与算法

image

  • Java架构进阶之开源框架篇(设计模式+Spring+SpringMVC+MyBatis

image

image

image

  • Java架构进阶之分布式架构篇 (限流(ZK/Nginx)+缓存(Redis/MongoDB/Memcached)+通讯(MQ/kafka)

image

image

image

  • Java架构进阶之微服务架构篇(RPC+SpringBoot+SpringCloud+Dubbo+K8s)

image

image

复习的面试资料

这些面试全部出自大厂面试真题和面试合集当中,小编已经为大家整理完毕(PDF版)

  • 第一部分:Java基础-中级-高级

[外链图片转存中…(img-GiBxwSFF-1716215224509)]

  • 第二部分:开源框架(SSM:Spring+SpringMVC+MyBatis)

[外链图片转存中…(img-4kXagR1i-1716215224509)]

  • 第三部分:性能调优(JVM+MySQL+Tomcat)

[外链图片转存中…(img-E3Cs9FwE-1716215224509)]

  • 第四部分:分布式(限流:ZK+Nginx;缓存:Redis+MongoDB+Memcached;通讯:MQ+kafka)

[外链图片转存中…(img-ALHyPsWh-1716215224510)]

  • 第五部分:微服务(SpringBoot+SpringCloud+Dubbo)

[外链图片转存中…(img-Vu0E1zLC-1716215224510)]

  • 第六部分:其他:并发编程+设计模式+数据结构与算法+网络

[外链图片转存中…(img-yTS7rxRs-1716215224510)]

进阶学习笔记pdf

  • Java架构进阶之架构筑基篇(Java基础+并发编程+JVM+MySQL+Tomcat+网络+数据结构与算法

[外链图片转存中…(img-NmdGiFoH-1716215224510)]

  • Java架构进阶之开源框架篇(设计模式+Spring+SpringMVC+MyBatis

[外链图片转存中…(img-BWJ6cG00-1716215224510)]

[外链图片转存中…(img-d9VlO8dA-1716215224511)]

[外链图片转存中…(img-mpZaJfbf-1716215224511)]

  • Java架构进阶之分布式架构篇 (限流(ZK/Nginx)+缓存(Redis/MongoDB/Memcached)+通讯(MQ/kafka)

[外链图片转存中…(img-Y08VSYAD-1716215224511)]

[外链图片转存中…(img-bk90v3tb-1716215224511)]

[外链图片转存中…(img-TaHRnYie-1716215224512)]

  • Java架构进阶之微服务架构篇(RPC+SpringBoot+SpringCloud+Dubbo+K8s)

[外链图片转存中…(img-CnGAduqZ-1716215224512)]

[外链图片转存中…(img-wjR4npPU-1716215224512)]

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值