Serlect&Response

简介: Servlet快速入门1. 创建web项目,导入Servlet依赖坐标

Servlet快速入门

  1. 创建web项目,导入Servlet依赖坐标

<dependency>

  <groupId>javax.servlet</groupId>

           <artifactId>javax.servlet-api</artifactId>

           <version>3.1.0</version>

           <scope>provided</scope>

       </dependency>

  1. 注意:scope:这里的provided设置在本xml中生效,因为tomcat本省就自带就servlet,全局使用会引起冲突
  2. 创建:定义一个类,实现Servlet接口,并重写接口中所有方法,并在service方法中输入一句话

publicclassServletDemo1implementsServlet {

   @Override

   publicvoidservice(ServletRequestservletRequest, ServletResponseservletResponse) throwsServletException, IOException {

       System.out.println("Servlet hello word");

   }

   @Override

   publicvoidinit(ServletConfigservletConfig) throwsServletException {

   }

   @Override

   publicServletConfiggetServletConfig() {

       returnnull;

   }

   @Override

   publicStringgetServletInfo() {

       returnnull;

   }

   @Override

   publicvoiddestroy() {

   }

}

  1. 配置:在类上使用@WebServlet注解,配置该Servlet的访问路径

@WebServlet("/demo1")

  1. 访问:启动Tomcat,浏览器输入URL访问该Servlet

http://localhost:8080/tomcat-demo1/

Servlet执行流程

  • 想想问什么我们没有创建servlet对象,也没有执行调用它的方法,它是怎么创建和执行的呢?

  • 其实是由web服务器创建的里面的方法也是被tomcatweb服务器调用的
  • 那么服务器怎么知道Servlet中一定有servlet方法?
    因为我们自定义的servlet,必须是实现servlet接口并复写其方法,而servlet接口中有service方法

Servlet生命周期

  • 对象的生命周期指一个对象从被创建到销毁的整个过程
  • Servlet运行在Servlet容器(web服务器中)其生命周期由容器来管理,分为4个阶段:
  1. 加载和实例化:默认情况下,当Servlet第一次被访问时(默认情况下),由容器创建Servlet对象那么在没有默认情况下可以通过
  2. 初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如:加载配置文件,创建连接等初始化的工作,该方法只调用一次
  3. 请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理
  4. 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放,在destory()方法调用之后,容器会释放这个Servlet实例,该实例随后会被java的垃圾收集器回收

Servlet体系结构

  • Servlet   ->体系根接口
  • GennericServlet ->Servlet抽象实现类
  • HttpServlet  -> 对HTTP协议封装的Servlet实现类
  • HttpServlet使用步骤
  • 继承HttpServlet
  • 重写doGet和doPost方法
  • 原理就是:获取请求方式,并根据不同的请求方式,调用不同的方法

Servlet urlPattern配置

  • Servlet要想被访问,必须配置其访问路径(urlPattern)
  1. 一个Servlet,可以配置多个urlPattern

@WebServlet(urlPatterns= {"/demo7","/demo8"});

  1. urlPattern的配置规则
  1. 精确匹配
  • 配置路径:

@WebServlet(urlPatterns="/user/select")

  • 访问路径:

http://localhost:8080/tomcat-demo1//user/select

  1. 目录匹配:上面精确匹配高于目录
  • 配置路径:

@WebServlet(urlPatterns="/user/*")

  • 访问路径:

http://localhost:8080/tomcat-demo1//user/aaa

  1. 扩展名匹配
  • 配置路径:这里*前面不要加/

@WebServlet(urlPatterns="*.do")

  • 访问路径:anyone代表这里填任意都行

http://localhost:8080/tomcat-demo1/anyone.do

  1. 任意匹配
  • 配置路径:

@WebServlet(urlPatterns="/")

@WebServlet(urlPatterns="/*")

这两种都行但是/*优先级更高

  • 这/和/*两个的区别:
  • 当我们的项目中的Servlet配置了"/",会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet
  • 当我们的项目中配置了"/*",意味着匹配任意访问路径
  • 访问路径:

http://localhost:8080/tomcat-demo1/writedowninthereanything

XML配置方式编写Servlet

  • Servlet从3.0版本后开始支持使用注解配置,3.0版本前只支持xml配置文件的配置方式
  • 步骤:
  1. 编写Servlet类
  2. 在web.xml中配置Servlet

<!-- 1Servlet全类名-->

 <servlet>

   <servlet-name>demo12</servlet-name>

   <servlet-class>com.wang.web.ServletDemo12</servlet-class>

 </servlet>

<!-- 2Servlet访问路径-->

 <servlet-mapping>

   <servlet-name>demo12</servlet-name>

   <url-pattern>/demo13</url-pattern>

 </servlet-mapping>

Request继承体系

  • ServletRequest(java提供的请求对象根接口)->HttpServletRequest(java提供的对Http协议封装的请求对象接口)->RequestFacade(Tomcat定义的实现类)
  • Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中
  • 使用request对象,查阅javaEEAPI文档的HttpServletRequest接口
Request获取请求数据
  • 请求数据分为3部分:
  1. 请求行:GET/request-demo/req?username=zhangsan&password=123 HTTTP/1.1

       //1String getMethod():获取请求方式:GET

       Stringmethod=req.getMethod();

       System.out.println(method);

       //2String getContexPath():获取虚拟目录(项目访问路径):/request-demo

       StringcontextPath=req.getContextPath();

       System.out.println(contextPath);

       //3StringBuffer getReuestURL():获取URL(统一资源定位符):http://localhost:8080/request-demo/req1

       StringBufferurl=req.getRequestURL();

       System.out.println(url);

       //4String getRequestURI():获取URI(统一资源标识符):/request-demo/req

       Stringuri=req.getRequestURI();

       System.out.println(uri);

       //5String getQueryString():获取请求参数(GET方式):username=zhangsan&password=123

       StringqueryString=req.getQueryString();

       System.out.println(queryString);

  1. 请求头:USer-Agent:Mozilla/5.0 Chrome/91.0.4472.106

 //获取请求头:user-agent:浏览器的版本信息

       Stringagent=req.getHeader("user-agent");

       System.out.println(agent);

  1. 请求体:username=superbaby&passwprd=123

//获取post请求体:请求参数

       //1.获取字符输入流

       BufferedReaderbr=req.getReader();

       //2.读取数据

       Stringline=br.readLine();

       System.out.println(line);

Request通过方式获取请求参数
  • Map<String,String[]> getParameterMap():s获取所有参数Map集合
  • Stirng[] getParameterValues(String name):根据名称获取参数值(数组)
  • String geParameter(String name):根据名称获取参数值(单个值)

//GET请求逻辑

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

       //1.获取所有参数的Map集合

       Map<String,String[]>map=req.getParameterMap();

       for (Stringkey: map.keySet()

            ) {

           System.out.print(key+"");

           //获取值

           String[] values=map.get(key);

           for (Stringvalue: values

                ) {

               System.out.println(value+"");

           }

       }

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

       //2.根据key获取参数值,数据

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

       for (Stringhobby:hobbies

            ) {

           System.out.println(hobby);

       }

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

       //根据key获取单个参数值

       Stringusername=req.getParameter("username");

       Stringpassword=req.getParameter("password");

       System.out.println(username);

       System.out.println(password);

  • 使用通用方式获取请求参数后,屏蔽了GET和POST的请求方式代码的不同,则代码可以定义为如下格式:

@Override

   protectedvoiddoGet(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException {

       //2.解决乱码:post,getReader()

       request.setCharacterEncoding("UTF-8");

       //1.获取username

       Stringusername=request.getParameter("username");

       System.out.println(username);

   }

   @Override

   protectedvoiddoPost(HttpServletRequestrequest, HttpServletResponseresponse) throwsServletException, IOException {

       this.doGet(request,response);

   }

  • 使用Servlet模板创建Servlet更高效,修改Servlet模板在Setting->Editor->File and code Templates->Other->Web->Servlet Annotated Class.java
解决请求参数中文乱码处理
  • 请求参数如果存在中文数据,则会乱码
  • 解决方案:
  • Post:设置输入流的编码

request.setCharacterEncoding("UTF-8");

  • Get:先编码,后解码

//GET获取参数的方式:get

       username=newString(username.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

       System.out.println(username);

  • 张三字符串会通过HTTP协议发送到服务器,而浏览器不支持中文,那么会对中文进行处理,这个处理就是URL编码,将编码发送到Tomcat里去,那么Tomcat会对数据进行解码如果Tomcat用的是UTF-8是不会乱码的,但是Tomcat用的是ISO-8859-1(这里写死了不能更改编码方式)字符集解码
    URL编码:1.将字符串安装编码方式转为二进制2.每个字节转为2个16进制并在前边加上%
  • 小知识点:Tomcat8之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8
Request请求转发
  • 请求转发:一种在服务器内部的资源跳转方式
  • 实现方式:

    request.getRequestDispatcher("/req6").forward(request,response);

  • 请求转发资源间共享数据:使用Request对象

//存储数据

request.setAttribute("msg","hello");

//获取数据

Objectmsg=request.getAttribute("msg");

//删除数据     request.removeAttribute("msg");

  • 特点
  1. 浏览器地址栏路径不发生变化
  2. 只能转发到当前服务器的内部资源
  3. 一次请求,可以在转发的资源间使用request共享数据

Response

  • 概念:Request对象用来获取请求数据Response用来设置数据

Response设置响应数据功能介绍

  • 响应数据分为3部分
  1. 响应行:HTTP/1.1 200 OK

voidsetStatus(intsc):设置响应状态码

  1. 响应头:Content-Type:text/html

voidsetHeader(Stringname,Stringvalue):设置响应头键值对

  1. 响应体:<html><haed><head><body><body></html>
  • PrintWriter getWrite():获取字符输出流
  • SevletOutPutSstream getOutputStream():获取字节输出流

Response完成重定向

  • 重定向:一种资源跳转方式
  • 实现方式:

resp.setStatus(302);

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

resp.sendRedirect("资源b路径")

//1设置重定向

       //设置响应状态码为302

       response.setStatus(302);

       //设置响应头:location        response.setHeader("Location","/request-demo1/reps2");

       //2简化写法

       response.sendRedirect("/request-demo1/resp2");

//3动态获取虚拟目录写法

       StringcontextPath=request.getContextPath();

       response.sendRedirect(contextPath+"/resp2");

  • 重定向特点:
  1. 浏览器地址栏路径发生变化
  2. 可以重定向到任意位置的资源(服务器内部,外部都可以)
  3. 两次请求,不能在多个资源使用request共享数据

Response响应字符数据

//获取字符输出流

PrintWriterwriter=response.getWriter();

//写数据

response.setHeader("content-type","text/html");

writer.write("<h1>html</h1>");

//细节:流不要关闭

  • text/html是转换成html形式
  • 这里存在一个问题输出中文字符的话会乱码所以将setHeader更换成

response.setContentType("text/html;charset=utf-8");

Response响应字节数据

//1.读取文件

FileInputStreamfis=newFileInputStream("路径");

//2.获取response字节输出流

ServletOutputStreamos=response.getOutputStream();

//完成流的拷贝

byte[] buff=newbyte[1024];

intlen=0;

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

    os.write(buff,0,len);

}

fis.close();

  • 更简便的方式工具类
  • 在pom.xml导入坐标

<dependency>

           <groupId>commons-io</groupId>

           <artifactId>commons-io</artifactId>

           <version>2.6</version>

       </dependency>

  • 使用

//1.读取文件

       FileInputStreamfis=newFileInputStream("C:\\Users\\为了谁\\Desktop\\截图图片\\微信图片_20220406133501.jpg");

       //2.获取response字节输出流

       ServletOutputStreamos=response.getOutputStream();

       //工具类的方法

       IOUtils.copy(fis,os);

       fis.close();

案例写写

  • 流程说明:
  1. 用户填写用户名密码,提交到LoginServlet
  2. 在LoginServlet中使用MyBatis查询数据库,验证用户名是否正确
  3. 如果正确,响应登入成功,如果错误,响应“登入失败”
  • 准备环境
  1. 复制资料中的静态页面到项目的webapp目录下
  2. 创建db1数据库,创建tb_user表,创建User实体类
  3. 导入MyBatis坐标,MySql驱动坐标
  4. 创建mybatis-config.xml核心配置文件,UserMapper.xml映射文件,UserMapper接口
相关文章
|
5月前
|
应用服务中间件 数据安全/隐私保护
|
5月前
response.setcontenttype详解
response.setcontenttype详解
|
5月前
|
存储 Java 应用服务中间件
Request&Response(3)
Request&Response
53 0
|
5月前
|
前端开发 Java 应用服务中间件
Request&Response(4)
Request&Response
39 0
|
5月前
|
Java Maven 数据安全/隐私保护
Request&Response(2)
Request&Response
45 0
|
5月前
|
Java 数据库连接 数据库
Request&Response(5)
Request&Response
49 0
|
5月前
|
Java 应用服务中间件 API
Request&Response(1)
Request&Response
62 0
|
6月前
|
Java 数据库连接 数据库
Request 和 Response详解(下)
Request 和 Response详解(下)
74 1
|
6月前
|
存储 缓存 前端开发
Request 和 Response详解(中)
Request 和 Response详解(中)
82 0
|
6月前
|
前端开发 Java 应用服务中间件
Request 和 Response详解(上)
Request 和 Response详解(上)
122 0