Resquest/Response

正则表达式的书写

image-20220327141826432

开头和结尾是必要的,我已我们一般先写好开头结尾再往里面加内容

WEB核心技术

image-20220327142016934

一个成熟的web需要运用到多种语言的书写,这里的数据库连接我们已经学了使用jdbc以及mybatis的方式完成数据的获取与修改

HTTP

image-20220327142313567

请求体和i请求头之间有空格隔开的

对应的参数存放到请求体中

GET/POST的区别

1.GET请求参数放到请求行中,没用请求体。POST请求参数放到请求体中

2.GET请求请求参数大小有限制,POST 没有

HTTP响应数据格式

image-20220327143640094

WEB服务器-Tomcat

这种类似的web服务器是一个软件,对http协议操作进行封装,使程序员不必直接对协议进行操作,让WEB开发更加快捷

可以将web项目部署到服务器中,对外提供网上浏览服务

我们用的tomcat是一个轻量级web服务器

这是一个绿色软件直接解压即安装,删除文件夹即卸载

打开方式点开bin start.bat安全打开,ctrl+c安全关闭

image-20220327154006297

在idea中可以本地部署tomcat

image-20220327161757769

image-20220327161835669

也可以使用pom中添加配置

image-20220327161902905

Servlet

image-20220327163443917

Servlet快速入门

image-20220327164927782

1.在pom文件里导入依赖jar包,直接复制以后都是一样的

这里注意一定要定义一个scope为provided

image-20220327225008778

2.写一个方法完成servlet接口,重写其方法

image-20220327225216413

3.配置访问路径使其能被访问到

image-20220327225306219

这里说一下我这里困扰了一下午的tomcat页面一直404输入路径也无法跳转,最后我重新以模板的形式生成了maven新的工程,在pom中导入tomcat就解决了,真是让人头疼

这里我们的service方法里只是写了输出语句,其实这是用来接收以及向服务器返回数据的方法,之后学习了过后,会具体使用

servlet生命周期

image-20220328181618828

package com.ember.web;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet(urlPatterns = "/demo1",loadOnStartup = 1)
public class ServletDemo2 implements Servlet {
   /*完成初始化的方法
   * 1.调用时机:默认情况下,servlet被第一次访问时调用
   * loadOnStartup:默认是-1,改成正整数则访问servlet的时候直接创建
   * (使用属性来更改调用的时机使用属性要先补全注解里面的属性值urlPatterns =)
   * 2.调用次数:1次*/
   @Override
   public void init(ServletConfig servletConfig) throws ServletException {
       System.out.println("init");
  }
   /*提供服务
   * 1.调用时机:每一次servlet被访问时就调用
   * 2.调用次数:每次访问页面就会被调用*/
   @Override
   public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
       System.out.println("selevet hello world");
  }
   /*1销毁方法
   * 调用时机:内存释放或者服务器关闭的时候,servlet对象会被销毁,调用该方法释放资源
   * 调用次数:1次*/
   @Override
   public void destroy() {
       System.out.println("destroy");
  }



   @Override
   public ServletConfig getServletConfig() {

       return null;
  }



   @Override
   public String getServletInfo() {
       return null;
  }




}

其他两个方法在需要使用时查看javaee api

这里说一下要在一个方法中使用另一个方法中的成员变量,则直接提升改成与变量的作用域

image-20220328185743589

image-20220328185821140

servlet体系结构

image-20220328190019014

@WebServlet(urlPatterns ="/demo3")
public class ServletDemo3 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println("get...");
  }

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println("post...");
  }
}

以上代码显示servlet会根据页面的访问方式调用不同的方法,这里用一个例子显示了调用的是哪个方法我们通过a.html提交数据到demo3时使用的post方式则会调用dopost方法,直接访问用get方式则使用doget方法

http协议里一共有七种请求方式,对应了七种方法,用到的时候都是要复写的

HttpServlet的使用步骤:1.写类继承HttpServlet2.重写doget和dopost方法

使用原理:获取请求方式,并且根据不同的请求方式,调用不同的doxxx方法

servlet urlPattern配置

一个servlet可以配置多个urlPattern,通过这些路径都可以访问到servlet

@WebServlet(urlPatterns ={"/demo3""/demo4"})

urlPattern的配置规则:

image-20220328195144331

当一个路径同时符合精确匹配也符和路径匹配,则精确匹配的优先级要高一点

一般只用前三种,第四种尽量不要使用

优先级依次递减

xml方式编写servlet(旧方法,现在一般使用注解的方式配置)

image-20220328195644051

1.继承httpservlet

public class ServletDemo4 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println("demo4.get...");
  }

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println("demo4.post...");
  }
}

2、在web.xml里面完成配置

<!--  servlet全类名-->
 <servlet>
   <servlet-name>renyi</servlet-name>
   <servlet-class>com.ember.web.ServletDemo4</servlet-class>
 </servlet>
<!-- servlet访问路径-->
 <servlet-mapping>
   <servlet-name>renyi</servlet-name>
   <url-pattern>/demo4</url-pattern><!-- 配置可以访问的路径-->
 </servlet-mapping>

很明显注解的方式简单多了

Request/Response

Request:获取请求数据

Response:设置响应数据

以下代码实现以下浏览器的交互

@WebServlet(urlPatterns ="/demo3")
public class ServletDemo3 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
       //用request获取请求数据
       String name=request.getParameter("name");
       resp.setHeader("content-type","text/html;charset=utf-8");
       //用response 设置响应数据
       resp.getWriter().write("<h1>"+name+",欢迎您!<h1>");
  }

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println("post...");
  }
}

当我们在网址后面输入?name=xxx的时候页面会根据名字内容更改显示内容,这就是交互

Request继承体系:

image-20220328201037341

Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中

要使用request对象,直接查阅javaee api文档的httpservletrequest接口

Request获取请求数据

分为三步:获取请求行&请求头&请求体

image-20220329094700610

下面写一个例子

@WebServlet(urlPatterns = "/req1")
public class RequestDemo1 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       String method=req.getMethod();//获取请求方式GET
       System.out.println(method);
       String contextPath=req.getContextPath();
       System.out.println(contextPath);
       StringBuffer url=req.getRequestURL();
       System.out.println(url.toString());
       String uri = req.getRequestURI();
       System.out.println(uri);
       String queryString = req.getQueryString();//获取请求参数(get方式)
       System.out.println(queryString);
  }

   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       super.doPost(req, resp);
  }
}

对于我们要向页面传入一些信息我们可以写一个表单完成数据传入(注意这里要使用get方式,应为我们是在doget方法中写的测试)

<form name="user" action="/testtomcat2/req1" method="get">
username:<input name="uername">
  password:<input name="password">
   <input type="submit">
</form>

image-20220329095022459点击提交后会直接跳转,数据会返回到控制台

image-20220329095118154

image-20220329095348147

/*获取请求头
* user-agent获取浏览器的版本*/
String agent = req.getHeader("user-agent");
System.out.println(agent);

image-20220329095755571

以上呢get和post都会有,而请求体只有post请求才会有所以要测试请求体的方法则需要写一个表单

image-20220329095920184

<form  action="/testtomcat2/req1" method="post">
  用户名: <input type="text" name="username">
  密码:<input type="password" name="password">
   <input type="submit">
</form>
    @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//       获取post 请求体 请求参数
//       获取字符输入流
       BufferedReader br = req.getReader();
       String line = br.readLine();
       System.out.println(line);
  }

通过获取字节流或字符流获得数据

Request通用方式获取请求参数

image-20220329101635317

因为一个servlet根据请求方式的不同会调用不同的方法,但是这两个方法中只有获取请求的方式这一段代码不同其他的都是差不多的,这就造成了代码的重复,所以我们可以使用一种统一的获取请求参数的方式,从而统一doget和dopost方法内的代码

image-20220329102525772

首先我们判断是哪种请求在调用相应的获取参数的方式,系统将这些参数封装成一个Map集合,这三个方法就是request对象提供的通用获取请求参数的方法,以下是对三个方法的实现例子

@WebServlet("/req2")
public class RequestDemo2 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//       GET请求逻辑
       System.out.println("get.....");
//       1.获取所有参数的MAP集合(iter快捷遍历)
       Map<String, String[]> map = req.getParameterMap();
       for (String s : map.keySet()) {
//           获取的格式时username:zhangsan
           System.out.print(s+":");
           //       获取值
           String[] values = map.get(s);
           for (String value : values) {
               System.out.print(value+" ");
          }
           System.out.println();
      }
       System.out.println("...............");
//       根据key获取参数值(数组)
       String[] hobbies = req.getParameterValues("hobby");
       for (String hobby : hobbies) {
           System.out.println(hobby);
      }
//3.根据key获取单个的参数值
       String username = req.getParameter("username");
       String password = req.getParameter("password");
       System.out.println(username);
       System.out.println(password);

  }

将doget里面的代码全部复制到doget中也是可以获取到数据的这就是通用的三个方法

因为里面的代码是完全一样的,所以我们的dopost方法里只用调用doget就可以了

    @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//       POST请求逻辑
   this.doGet(req, resp);
  }
}

使用了通用方式之后,屏蔽了get和post的请求方式的不同,则我们可以使用servlet模板来创建servlet

image-20220329144430150

可以根据需要去改造模板

image-20220329144726987

Request post请求参数中文乱码处理

image-20220329145813651

这是我们写了一个例子来获取用户名,并且在html页面中提交了中文用户名导致的乱码

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//   获取username
       String username = request.getParameter("username");
       System.out.println(username);
  }
//        解决乱码 POST.getReader()获取字符流默认的编码不是utf-8,所以post请求的中文会乱码
       request.setCharacterEncoding("UTF-8");/*设置字符输入流的编码*/

在最上面加入如上代码,改变其编码与html相同image-20220329150557407

GET请求解决方案

解决中文乱码 get 乱码原因:浏览器处理数据进行url编码(UTF-8),服务器接收数据再进行url解码(ISO-8859-1),但是编码解码使用的字符集不一样导致乱码,只能从url编码底层入手

image-20220330113105616

以下是对get请求传入中文的username解决办法

        /*1.先对乱码数据进行编码,转为字节数组*/
//       byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
//       /*字节数组解码*/
//       username = new String(bytes, StandardCharsets.UTF_8);
       username=new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
       System.out.println("解决乱码后"+username);

熟练过后将上面两行代码合并成一行了,这种方式是一种通用的方式同样可以解决post乱码

Request请求转发

一种在服务器内部的资源跳转方式

//        请求转发
       request.getRequestDispatcher("/req6").forward(request,response);

将请求转发给另一个路径,一般两个路径要共享数据

image-20220330140526102

在req5页面中请求转发

        System.out.println("demo5''''[''");
//       存储数据
       request.setAttribute("msg","hello");
//       请求转发
       request.getRequestDispatcher("/req6").forward(request,response);

在req6中接收请求

       获取数据
       Object msg = request.getAttribute("msg");
       System.out.println(msg);
       System.out.println("demo6'''''''");
  }

转发的特点:

浏览器地址栏路径不发生改变

只能转发到当前服务器的内部资源

一次请求,可以在转发资源间使用request共享数据

Response设置响应数据

以下是响应数据的分类以及对应的设置的方法

image-20220330142126987

Response完成重定向

即当不能处理请求的时候返回其他路径

image-20220330142800855

即分为两步:

1.返回状态码302

2.返回跳转路径

实现:

resp.setStatus(302);

resp.setHeader("location","资源b的路径")

以下例子

resp1

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       System.out.println("resp1..........");
//       重定向
//       1.设置响应数据码302
       response.setStatus(302);
//       2.设置响应头Location
       response.setHeader("Location","/testtomcat2/resp2");//注意资源路径要写服务器的虚拟前缀
  }

resp2

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   System.out.println("resp2..........");
}

只要访问resp1就自动跳转到resp2

可以发现这个代码只有跳转的路劲会有改变所以以后这样写

//        简化方式完成重定向
       response.sendRedirect("/testtomcat2/resp2");

(注意:可以重定向到任意路径)

对于路径书写

浏览器使用:需要加虚拟目录(项目访问路径)

服务端使用:不加虚拟目录(即不需要浏览器跳转页面访问)

对于要加虚拟路径的时候直接写虚拟目录,使得耦合性太强了,以后一改路劲就会出错,所以我们一般采用动态路径

//        简化方式完成重定向
//       response.sendRedirect("/testtomcat2/resp2");
//       动态获取虚拟目录
       String contextPath = request.getContextPath();
       response.sendRedirect(contextPath+"resp2");
Response响应字符&字节数据

image-20220330151151363

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   /*防止设置的字节流是中文乱码以及能够解析html格式和文本格式的字符流*/
   response.setContentType("text/html;charset=utf-8");
   /*1.获取字符输出流*/
   PrintWriter writer = response.getWriter();
   writer.write("设置的响应字符");
   writer.write("<h1>wy,你好</h1>");


}

获取字节流就是使用的获取方法不一样,用与获取一些文件并输出

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//       1. 获取文件
       FileInputStream fis = new FileInputStream("C://Users//Ember//Desktop//icon//file.png");
//       2.获取Response字节输出流
       ServletOutputStream os = response.getOutputStream();
//       3.完成流的Copy
       byte[] buff=new byte[1024];
       int len=0;
       while((len=fis.read(buff))!=-1){
           os.write(buff,0,len);
      }
       fis.close();
  }

这种复制方法是javaIO中的知识,我们一般使用工具类来简化

先去pom里增加依赖

<dependency>
 <groupId>commons-io</groupId>
 <artifactId>commons-io</artifactId>
 <version>2.6</version>
</dependency>

导入后即可使用IOUtils的方法了

//        3.完成流的Copy
//       byte[] buff=new byte[1024];
//       int len=0;
//       while((len=fis.read(buff))!=-1){
//           os.write(buff,0,len);
//       }
       IOUtils.copy(fis,os);
       fis.close();

(注意:这里选着IOUtils时要注意导入的包是apache)

posted @   Ember00  阅读(245)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示