栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Servlet

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Servlet

1.执行流程


1.浏览器发出http://localhost:8080/web-demo/demo1请求,从请求中可以解析出三部分内容,分别是localhost:8080、web-demo、demo1

  • 根据localhost:8080可以找到要访问的Tomcat Web服务器
  • 根据web-demo可以找到部署在Tomcat服务器上的web-demo项目
  • 根据demo1可以找到要访问的是项目中的哪个Servlet类,根据@WebServlet后面的值进行匹配

2.找到ServletDemo1这个类后,Tomcat Web服务器就会为ServletDemo1这个类创建一个对象,然后调用对象中的service方法

  • ServletDemo1实现了Servlet接口,所以类中必然会重写service方法供Tomcat Web服务器进行调用
  • service方法中有ServletRequest和ServletResponse两个参数,ServletRequest封装的是请求数据,ServletResponse封装的是响应数据,后期我们可以通过这两个参数实现前后端的数据交互
2.生命周期
  • 生命周期: 对象的生命周期指一个对象从被创建到被销毁的整个过程。
    1.加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
    2.初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
    3.请求处理每次请求Servlet时,Servlet容器都会调用Servlet的==service()方法对请求进行处理
    4.服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的
    destroy()==方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
@WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)
  初始化方法
     *  1.调用时机:默认情况下,Servlet被第一次访问时,调用
     *       loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用
     *  2.调用次数: 1次


init
 *  初始化方法
     *  1.调用时机:默认情况下,Servlet被第一次访问时,调用
     *      * loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用
     *  2.调用次数: 1次
     * @param config
     * @throws ServletException

service


destroy
 
3.体系结构


在HttpServlet中我们一般封装了一些方法,变量和常量 当发送不同类型的请求时-Post或者Get,我们一般需要判断来获得其中的参数等等内容,这个HttpServlet这个类进行了封装,我们只需要重写doGet和doPost两个方法即可。其中的判断继承的HttpServlet已经帮我们写好了。

  1. HttpServlet的使用步骤

继承HttpServlet

重写doGet和doPost方法

  1. HttpServlet原理

获取请求方式,并根据不同的请求方式,调用不同的doXxx方法

视频:96 --Javaweb

4.urlPattern

1.精确匹配

@WebServlet(urlPatterns={“/demo7”,“/demo8”})

2.目录匹配

3.扩展名匹配

4.任意匹配

注意:/和/*的区别?

  1. 当我们的项目中的Servlet配置了 “/”,会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet
  2. 当我们的项目中配置了"/*",意味着匹配任意访问路径
  3. DefaultServlet是用来处理静态资源,如果配置了"/"会把默认的覆盖掉,就会引发请求静态资源的时候没有走默认的而是走了自定义的Servlet类,最终导致静态资源不能被访问

小结

  1. urlPattern总共有四种配置方式,分别是精确匹配、目录匹配、扩展名匹配、任意匹配
  2. 五种配置的优先级为 精确匹配 > 目录匹配> 扩展名匹配 > /* > / ,无需记,以最终运行结果为准。
5.XML配置方式编写Servlet

前面对应Servlet的配置,我们都使用的是@WebServlet,这个是Servlet从3.0版本后开始支持注解配置,3.0版本前只支持XML配置文件的配置方法。

对于XML的配置步骤有两步:

  • 编写Servlet类
  • 在web.xml中配置该Servlet


    
    
    
    
    
        
        demo13
        
        com.itheima.web.ServletDemo13
    

    
    
        
        demo13
        
        /demo13
    

5.Request和Response   1.Request     1.Request继承体系

Request的继承体系

  • Request的继承体系为ServletRequest–>HttpServletRequest–>RequestFacade
  • Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法
  • 使用request对象,可以查阅JavaEE API文档的HttpServletRequest接口中方法说明
    2.Request获取请求数据

1.请求行包含三块内容,分别是请求方式、请求资源路径、HTTP协议及版本

  • 获取请求方式: GET

String getMethod()

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

String getContextPath()

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

StringBuffer getRequestURL()

  • 获取URI(统一资源标识符): /request-demo/req1

String getRequestURI()

  • 获取请求参数(GET方式): username=zhangsan&password=123

String getQueryString()

2.获取请求体数据

  • getReader() ------------ 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法

BufferedReader getReader()

BufferedReader reader = req.getReader();
        String s = reader.readLine();
        System.out.println(s);
  • getInputStream()—获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法

ServletInputStream getInputStream()
该方法可以获取字节

3.请求头数据
String getHeader(String name)

    //获取请求头: user-agent: 浏览器的版本信息
        String agent = req.getHeader("user-agent");
		System.out.println(agent);
    3.Request获取请求参数的通用方式
//@WebServlet(urlPatterns = "*.do")
public class Servletdemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       this.doGet(req, resp);   //核心
       
    }
}
  • 获取所有参数Map集合

Map getParameterMap()

  • 根据名称获取参数值(数组)

String[] getParameterValues(String name)

  • 根据名称获取参数值(单个值)

String getParameter(String name)

    //获取所有参数的Map集合
        Map parameterMap = req.getParameterMap();
        for (String s : parameterMap.keySet()) {
            System.out.print(s+':');

            String[] strings = parameterMap.get(s);
            for (String string : strings) {
                System.out.print(string);
            }
            System.out.println();
        }
        //根据名称获取参数值(数组)
        String[] usernames = req.getParameterValues("username");
        for (String username : usernames) {
            System.out.println(username);
        }
       //根据名称获取参数值(单个值)
        String username = req.getParameter("username");
        System.out.println(username);
    4.IDEA快速创建Servlet

1.按照自己的需求,修改Servlet创建的模板内容

2.创建Servlet项目

    5.Request解决请求参数中文乱码问题

1.POST
分析出现中文乱码的原因:

  • POST的请求参数是通过request的getReader()来获取流中的数据
  • TOMCAT在获取流的时候采用的编码是ISO-8859-1
  • ISO-8859-1编码是不支持中文的,所以会出现乱码

解决方案:

  • 页面设置的编码格式为UTF-8
  • 把TOMCAT在获取流数据之前的编码设置为UTF-8
  • 通过request.setCharacterEncoding(“UTF-8”)设置编码,UTF-8也可以写成小写

2.Get

URL编码:
这块知识我们只需要了解下即可,具体编码过程分两步,分别是:

(1)将字符串按照编码方式转为二进制

(2)每个字节转为2个16进制数并在前边加上%

张三按照UTF-8的方式转换成二进制的结果为:

1110 0101 1011 1100 1010 0000 1110 0100 1011 1000 1000 1001

   String username = "张三";
        //1. URL编码
        String encode = URLEncoder.encode(username, "utf-8");
        System.out.println(encode); //打印:%E5%BC%A0%E4%B8%89

       //2. URL解码
       //String decode = URLDecoder.decode(encode, "utf-8");//打印:张三
       String decode = URLDecoder.decode(encode, "ISO-8859-1");//打印:`å¼ ä¸ `
       System.out.println(decode);

GET请求中文参数出现乱码的原因

  • 浏览器把中文参数按照UTF-8进行URL编码
  • Tomcat对获取到的内容进行了ISO-8859-1的URL解码
  • 在控制台就会出现类上å¼ ä¸‰的乱码,最后一位是个空格

解决方案:

1.按照ISO-8859-1编码获取乱码å¼ ä¸‰对应的字节数组

2.按照UTF-8编码获取字节数组对应的字符串

 String username = request.getParameter("username");
        byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
        String s = new String(bytes, StandardCharsets.UTF_8);
        System.out.println(s);
    4.Request请求转发

1.请求转发(forward):一种在服务器内部的资源跳转方式。

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求

(2)资源A处理完请求后将请求发给资源B

(3)资源B处理完后将结果响应给浏览器

(4)请求从资源A到资源B的过程就叫请求转发

2.请求转发的实现方式:

req.getRequestDispatcher(“资源B路径”).forward(req,resp);

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

  • 1.存储数据到request域[范围,数据是存储在request对象]中

void setAttribute(String name,Object o);
request.setAttribute(“name”,“hello”);

  • 2.根据key获取值

Object getAttribute(String name);

  • 3.根据key删除该键值对

void removeAttribute(String name);



  2.Response

体系结构

    1.Respones请求重定向

Response重定向(redirect):一种资源跳转方式。

    //重定向
        //1.设置响应状态码 302
        response.setStatus(302);
        //设置响应头 Location
        response.setHeader("Location","/request-demo/resp2");
        
        //2.简化版本
        resposne.sendRedirect("/request-demo/resp2")

重定向和转发的区别

    2.路径问题

判断依据:

  • 浏览器使用:需要加虚拟目录(项目访问路径)
  • 服务端使用:不需要加虚拟目录
- `     超链接,从浏览器发送,需要加
- `
` 表单,从浏览器发送,需要加 - req.getRequestDispatcher("路径") 转发,是从服务器内部跳转,不需要加 - resp.sendRedirect("路径") 重定向,是由浏览器进行跳转,需要加 //简化方式完成重定向 //动态获取虚拟目录 String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/resp2");
    3.Response响应字符数据和字节数据

1.响应字符数据
一般为文字等等

  • 通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();
  • 通过字符输出流写数据: writer.write(“aaa”);

1.返回一串html字符串,并且能被浏览器解析 并且能够解析中文
response.setContentType(“text/html;charset=utf-8”);

 response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write("哈哈");
        writer.write("哈哈");

2.响应字节数据
为文件和图片等等

  • 通过Response对象获取字节输出流:ServletOutputStream outputStream = resp.getOutputStream();
  • 通过字节输出流写数据: outputStream.write(字节数据);
ServletOutputStream os = response.getOutputStream();

        byte[] buff = new byte[1024];
        int len=0;

        while ((len=fis.read(buff))!=-1){
            os.write(buff,0,len);
        }
        fis.close();

对于流的copy的代码还是比较复杂的,所以我们可以使用别人提供好的方法来简化代码的开发,具体的步骤是:
1.pom.xml添加依赖


    commons-io
    commons-io
    2.6

2.调用工具类方法

//fis:输入流
//os:输出流
IOUtils.copy(fis,os);

实现代码

FileInputStream fis = new FileInputStream("C://Users//Administrator//Desktop//aaa.jpg");
ServletOutputStream os = response.getOutputStream();
IOUtils.copy(fis,os);


6.JSP

初始开发环境

  • 在 dependencies 标签中导入 JSP 的依赖,如下

    javax.servlet.jsp
    jsp-api
    2.2
    provided

  • 在项目的 webapp 下创建jsp页面
  1.JSP 原理

JSP 本质上就是一个 Servlet , 其中html的代码转换成如下形式。
而Java代码直接显示。

  2.JSP 脚本

JSP 脚本有如下三个分类:

  • <%…%>:内容会直接放到_jspService()方法之中

<%
System.out.println(“hello,jsp~”);
int i = 3;
%>

  • <%=…%>:内容会放到out.print()中,作为out.print()的参数

<%=“hello”%>
<%=i%>

  • <%!…%>:内容会放到_jspService()方法之外,被类直接包含

<%!
void show(){}
String name = “zhangsan”;
%>

<%@ page import="com.itheima.pojo.Brand" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%
    // 查询数据库
    List brands = new ArrayList();
    brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
    brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
    brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));

%>





    
    Title




<% for (int i = 0; i < brands.size(); i++) { Brand brand = brands.get(i); %> <% } %>
序号 品牌名称 企业名称 排序 品牌介绍 状态 操作
<%=brand.getId()%> <%=brand.getBrandName()%> <%=brand.getCompanyName()%> <%=brand.getOrdered()%> <%=brand.getDescription()%> <%=brand.getStatus() == 1 ? "启用":"禁用"%> 修改 删除
  3.JSP缺点

由于 JSP页面内,既可以定义 HTML 标签,又可以定义 Java代码,造成了以下问题:

  • 书写麻烦:特别是复杂的页面,既要写 HTML 标签,还要写 Java 代码

  • 阅读麻烦,上面案例的代码,相信你后期再看这段代码时还需要花费很长的时间去梳理

  • 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…

  • 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存

  • 调试困难:出错后,需要找到自动生成的.java文件进行调试

  • 不利于团队协作:前端人员不会 Java,后端人员不精 HTML

    如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,由后端工程师再将该页面改为 JSP 页面

  4.EL 表达式

EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。

EL 表达式的主要作用是 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。

而 EL 表达式的语法也比较简单, ${expression} 。例如:${brands} 就是获取域中存储的 key 为 brands 的数据。

例如:

1. @WebServlet("/Servletdemo3")
//1. 准备数据
        List brands = new ArrayList();
        brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
        brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
        brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));

        request.setAttribute("brands",brands);
        request.getRequestDispatcher("/hello.jsp").forward(request,response);

2.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


hello jsp
  <%= "hello world"%>
  ${brands}


    域对象

JavaWeb中有四大域对象,分别是:

  • page:当前页面有效
  • request:当前请求有效 (如上案例)
  • session:当前会话有效
  • application:当前应用有效

el 表达式获取数据,会依次从这4个域中寻找,直到找到为止。而这四个域对象的作用范围如下图所示

例如: ${brands},el 表达式获取数据,会先从page域对象中获取数据,如果没有再到 requet 域对象中获取数据,如果再没有再到 session 域对象中获取,如果还没有才会到 application 中获取数据。

  5.JSTL标签

JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码。如下代码就是JSTL标签

使用前提导入内容

  • 导入坐标

    jstl
    jstl
    1.2


    taglibs
    standard
    1.1.2

  • 在JSP页面上引入JSTL标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 

1.if 标签



2.forEach 标签
1.类似于 Java 中的增强for循环。涉及到的 中的属性如下

  • items:被遍历的容器 ${对象}
  • var:遍历产生的临时变量
  • varStatus:遍历状态对象

从域对象中获取名为 brands 数据,该数据是一个集合;遍历遍历,并给该集合中的每一个元素起名为 brand,是 Brand对象。在循环里面使用 EL表达式获取每一个Brand对象的属性值


        
      -- <%--其中这个brand.id为直接通过id-----Id +get  去寻找这个方法获得数据--%>---
<%--            ${brand.id}--%>
            ${status.count}    ------------获取从一到后面的数字
            ${brand.brandName}
            ${brand.companyName}
            ${brand.ordered}
            ${brand.description}
            
                启用
            
            
                禁用
            
            修改 删除
        
    

2.类似于 Java 中的普通for循环。涉及到的 中的属性如下

  • begin:开始数
  • end:结束数
  • step:步长

    ${i}

  6.MVC模式和三层架构

1.MVC

MVC 是一种分层开发的模式,其中:

  • M:Model,业务模型,处理业务

  • V:View,视图,界面展示

  • C:Controller,控制器,处理请求,调用模型和视图

    MVC 好处:

  • 职责单一,互不影响。每个角色做它自己的事,各司其职。

  • 有利于分工协作。

  • 有利于组件重用

2.三层架构

  • 数据访问层:对数据库的CRUD基本操作
  • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如 注册业务功能 ,我们会先调用 数据访问层 的 selectByName() 方法判断该用户名是否存在,如果不存在再调用 数据访问层 的 insert() 方法进行数据的添加操作
  • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据

而整个流程是,浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,然后servlet将数据交由 JSP 进行展示。

三层架构的每一层都有特有的包名称:

  • 表现层: com.itheima.controller 或者 com.itheima.web
  • 业务逻辑层:com.itheima.service
  • 数据访问层:com.itheima.dao 或者 com.itheima.mapper

联系

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/858200.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号