JavaWeb学习之Servlet基础

学习笔记仅供参考,如有错误,请多指出

                                               java学习路上,与君共勉

​                                                                                                                                                                                                                                                                                                      作者:小饭


前言

原理操作来源于狂神说java的视频,所用图片来源于网络

基本上是看b站视频自己摘抄的笔记,保存到csdn是为了把笔记精华分享给大家,以及方便自己复习

1,Servlet简介

Servlet就是sun公司开发动态web的一门技术

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

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

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

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

2,HelloServlet

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

  1. 构建一个普通Maven项目,删掉里面的src目录,在项目中建立Module;这个空工程就是Maven的主工程

  2. 创建java web项目后,需要添加servlet,jsp依赖到pom.xml

    //servlet依赖
     <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
        </dependency>
        
    //jsp依赖
          <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>javax.servlet.jsp-api</artifactId>
          <version>2.3.3</version>
        </dependency>
        

  3. 右击项目名,创建一个Module,创建一个web-Maven项目

  4. 关于Maven父子工程的理解:

    父项目中有

        <modules>
            <module>servlet-1</module>
        </modules>

    父项目中java子项目可以直接使用

    son extends father

  5. Maven环境优化

    1.修改web.xml为最新(在tomcat的webapp中找)

    <?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"
             metadata-complete="true">
    </web-app>

    2.将Maven的结构搭建完整

    新创建mian->java->resources

  6. 编写一个Servlet程序

    1.编写一个普通类(在java中创建包,一般为三级目录com.fan.HelloServlet)

    2.实现Servlet接口,直接继承HttpServlet

public class HttpServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入到doGet方法");
        resp.setContentType("text/html;charset=UTF-8");//防止中文乱码
        PrintWriter writer = resp.getWriter();
        writer.println("HelloServlet,好好学习");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
 

编写Servlet的映射

为什么需要映射:我们写的是java程序,但是程序需要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,还需要给她一个浏览器可以访问的路径;

 <!--注册servlet-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.fan.Servlet.HelloServlet</servlet-class>
    </servlet>
    <!--servlet请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>    <!--映射-->
    </servlet-mapping>

配置tomcat

注意:配置项目发布的路径

启动测试

提示:如果项目出现中文乱码问题

在java文件中写入: resp.setContentType("text/html;charset=UTF-8");

3,Servlet原理

1, Servlet原理图:

2, Mapping问题

  1. 一个Servlet可以指定一个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  2. 一个Servlet可以指定多个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>

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

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

    /*:通配符,代表输入任何东西

  4. 一个Servlet可以指定一些后缀或者前缀等等

  5. <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    //默认请求路径(不建议这种写法)
  6. <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.fan</url-pattern>
    </servlet-mapping>
    //可以自定义后缀实现映射,但是注意*前面不能加项目映射路径
  7. 优先级问题

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

4,ServletContext

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

共享数据:

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

写两个java文件

set:

public class HelloServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello word");
        ServletContext context = this.getServletContext();
​
        String username = "小饭";
        context.setAttribute("username",username);//将一个数据保存在ServletContext中,名字为:username,值为:username
​
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

get:

public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String) context.getAttribute("username");//强转
​
        resp.setContentType("text/html;charset=UTF-8");//防止中文乱码
        resp.getWriter().println("名字"+username);
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
    }
}

配置web.xml文件 注册两个servlet

 <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.fan.servlet.HelloServletDemo</servlet-class>
    </servlet>
​
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
​
    <servlet>
        <servlet-name>getc</servlet-name>
        <servlet-class>com.fan.servlet.GetServlet</servlet-class>
    </servlet>
​
    <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>

最后:测试访问结果

如果先访问get,页面显示名字+null,

如果先访问set,再进入get,则输出名字+set输入的内容

获取初始化参数

 <!--配置一些web应用的初始化参数 -->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/study?&useSSL=false&serverTimezone=UTC</param-value>
    </context-param>
public class Servlet03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");
        resp.getWriter().println(url);
        resp.setContentType("text/html,charset=UTF-8");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
    }
}
​

注册servlet(上文有教程)

请求转发

从a中向b发送指令需求c的内容,b则询问c,c把内容返回给b,a则可以在访问b中得到c的内容

public class Servlet04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了demo04");
        ServletContext context = this.getServletContext();
//        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的路径
//        requestDispatcher.forward(req,resp);//调用forword实现请求转发;
        context.getRequestDispatcher("/gp").forward(req,resp);
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
    }
}

注册servlet,然后访问servlet04,得出的结果是/gp路径的结果

读取资源文件

Properties

  • 在java目录中新建properties

  • 在resources目录下新建properties

发现都被打包到同一路径:classes,俗称这个路径为:classpath

思路:需要一个文件流:

properties类:

public class PropertiesServlet extends HttpServlet {
    public void test(){
        Properties properties = new Properties();

    }
}
public class Servlet05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = this.getServletContext().getResourceAsStream("/WEB_INF/classes/db.properties");
        Properties pro = new Properties();
        pro.load(is);
        String user = pro.getProperty("username");
        String pwd = pro.getProperty("password");
        resp.getWriter().println(user+":"+pwd);
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
    }
}
username=root
password=123456

访问测试即可

5,HttpServletResponse

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

  • 如果要获取客户端请求过来的参数:找HttpServletRequest

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

1,简单分类

负责向服务器发送数据的方法:

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getwriter() throws IOException;

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

  
    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_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_NOT_FOUND = 404;
    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;
...

2, 常见应用

  1. 向浏览器输出信息

  2. 下载文件

    1. 要获取下载文件的路径

    2. 下载文件的名称

    3. 设置让浏览器能够支持下载我们的东西

    4. 获取下载文件的输入流

    5. 创建缓冲区

    6. 获取OutputStream对象

    7. 将FileOutputStream流写入到缓冲区

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

     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 1. 要获取下载文件的路径
            String realPath = "E:\\ideapro\\javaweb-servlet\\response\\src\\main\\resources\\翻.jpg";
            System.out.println("下载文件的路径:" + realPath);
            // 2. 下载的文件名是啥?
            String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
            // 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码
            resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            // 4. 获取下载文件的输入流
            FileInputStream in = new FileInputStream(realPath);
            // 5. 创建缓冲区
            int len = 0;
            byte[] buffer = new byte[1024];//创建一个数组,存储数据
            // 6. 获取OutputStream对象
            ServletOutputStream out = resp.getOutputStream();
            // 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端!
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
    ​
            in.close();
            out.close();
        }
    }
    ​

注意:使用web下载文件的时候,需要在实例化FileServlet 类的doGet方法里面添加以下设置(web文件头设置)

resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

URLEncoder.encode(fileName, "UTF-8") 转码

  1. 验证码功能

  • 前端实现

  • 后端实现,需要用到java图片类,即生成一个图片

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //浏览器3秒刷新
        resp.setHeader("refresh","3");
        //如何在内存中创建一个图片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D g = (Graphics2D) image.getGraphics();//功能类似画笔
        //设置图片背景色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,80,20);
        //给图片写数据
        g.setColor(Color.BLUE);
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,20);
        //告诉浏览器这个请求用图片方式打开
        resp.setContentType("image/jpeg");
        //网站是存在缓存的,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
​
        //把图片写给浏览器
        boolean write = ImageIO.write(image,"jpg", resp.getOutputStream());
​
    }
​
        //生成随机数
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        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 {
​
    }
}

  1. 实现重定向(重点)

         

(B)一个web资源收到客户端请求后,(B)他会通知客户端(A)去访问另一个web资源(C),这叫做重定向

常见场景:

  • 用户登录

void sendRedirect(String var1) throws IOException;
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        resp.setHeader("Location","/response_war/image2");
        resp.setStatus(302);
        */
​
        resp.sendRedirect("/response_war/image2");//重定向
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
​
    }
}

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

相同点:

页面都会实现跳转

不同点:

请求转发的时候,url不会发生变化 307

重定向的时候,url地址栏会发生变化 302

 

重定向例子

public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入这个请求了");
        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        //重定向一定要注意路径问题,否则出现404
        resp.sendRedirect("/response_war/success.jsp");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

 

6,HttpServletRequest

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

 

1,获取前端传递的参数并且请求转发

 

代码部分:

//requrst
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
​
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbys = req.getParameterValues("hobbys");
        System.out.println("=====================================");
        //后台接收中文乱码问题
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbys));
        System.out.println("=====================================");
​
        System.out.println(req.getContextPath());
        //通过请求转发
        //这里的/代表当前应用
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
​
​
    }
​
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

前端代码(丑,自行重新设计)

<html>
<head>
    <title>登录</title>
</head>
<body>
<h1>登录</h1>
​
<%--这里的表单表示:以post方式提交表单,提交到我们的login请求--%>
    <form action="${pageContext.request.contextPath}/login" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        爱好:
        <input type="checkbox" name="hobbys" value="吃饭">吃饭
        <input type="checkbox" name="hobbys" value="睡觉">睡觉
        <input type="checkbox" name="hobbys" value="旅游">旅游
        <input type="checkbox" name="hobbys" value="打球">打球
​
        <br>
        <input type="submit">
    </form>
</body>
</html>

跳转成功后的代码:

 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值