JavaWeb学习

JavaWeb学习

1、什么是JavaWeb

定义:是用Java技术来解决相关web互联网领域的技术栈。

  • 静态Web
  • 动态Web

Web应用程序

定义:可以提供浏览器访问得程序。由多部分组成

  • html,css,js
  • jsp,servlet
  • Java程序
  • jar包
  • 配置文件(Properties)

静态Web

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存失败,源站可能有防盗链机制,建议将图片保存下来直接上传下上传(iuXGypds3VUP-1654181491979)(D:\studys\笔记\资料\JavaWeb\静态Web1.png)(https://gitee.com/elvinw/img/raw/master/mybatis缓存原理.jpg[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SqHQna0T-1654181568567)(!%5B%5D%28https://gitee.com/elvinw/img/raw/master/mybatis%E7%BC%93%E5%AD%98%E5%8E%9F%E7%90%86.jpg%29#pic_center)]
)]

  • 缺点
    • 无法动态更新,所有用户看到的都是同一个页面
    • 无法和数据库交互

动态Web

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KDw2L9Me-1654181491981)(D:\studys\笔记\资料\JavaWeb\动态Web1.png)]

  • 优点
    • 可以动态更新,所有用户看到的不是同一个页面
    • 可以和数据库交互
  • 缺点
    • 加入服务器的动态资源出现了错误,需要重新编写后台程序,停机维护。

2、Web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息。

Tomcat

定义:Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat中得到体现,因为Tomcat技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web应用服务器。适合新手。Tomcat最新版本为10.0.14。

安装
  • 下载地址:https://tomcat.apache.org/download-10.cgi

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzx1ZZCN-1654181491982)(D:\studys\笔记\资料\JavaWeb\tomcat1.png)]

  • 解压

  • 配置Java环境变量

新建:JAVA_HOME:D:\Java\jdk1.7.0_51
新建:CLASS_PATH:.;%JAVA_HOME%\lib
编辑:PATH:在最前面加上 %JAVA_HOME%\bin; 
  • 启动,测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-15Ofp7dJ-1654181491984)(D:\studys\笔记\资料\JavaWeb\tomcat2.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JYxw5imv-1654181491986)(D:\studys\笔记\资料\JavaWeb\tomcat3.png)]

测试:http://localhost:8080/

  • 配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WY1owLyM-1654181491987)(https://gitee.com/elvinw/img/raw/master/image-20220111104949081.png)]

高难度面试题

请你谈谈网站是如何进行访问的!

  • 1、输入一个域名,回车
  • 2、检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射
    • 有:直接返回对应的ip地址
    • 没有:去DNS服务器找,找到的话就返回,找不到就不返回。

3、Http(超文本传输协议)

Http请求

  • 客户端–发送端(Request)–服务器
Request URL: 请求地址
Request Method: GET get方法/put方法
Status Code:200 ok  状态码
Remote(远程)Address:
  • 请求行–get,put
  • 消息头
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式
Accept-Language:语言环境、
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
Host:主机地址

Http响应

服务器–响应–客户端

  • 响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式
Accept-Language:语言环境、
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
Host:主机地址
Refresh:多久刷新一次
Location:让网页重定位
  • 响应状态码
    • 200:请求响应成功
    • 3xx:请求重定向
    • 4xx:找不到资源
    • 5xx:服务器代码错误

4、Servlet

Servlet简介

  • Servlet是sun公司开发动态web的一门技术
  • sun公司在这些API中提供了一个接口:Srevlet。
  • 开发Servlet程序的步骤
    • 编写一个类,实现Srevlet接口
    • 把开发好的java类部署到web服务器中

把实现了Srevlet接口的Java程序叫做:Srevlet

创建HelloSrevlet

1、构建一个普通的Maven项目:javaweb-01-servlet,删除src目录,新建Moudel。这个空的工程就是Maven主工程。

  • 配置pox.xml文件,导入Servlet依赖
<dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
</dependencies>

2、创建Mvaen子工程web项目:servlet-01

  • 配置子项目中的web.xml
<?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>
  • 父项目中会有:
<modules>
    <module>servlet-01</module>
</modules>

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

3、编写一个Srevlet

  • 新建HelloServelt类,继承HttpServelt
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * Author:三木
 * Date:2022-01-22 16:21
 * Description:<测试Servelt>
 */
public class HelloServelt extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter();//响应流
        writer.print("helloServelt");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 添加Servlet映射,web.xml文件
    <!--注册Servelt-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.sanmu.servlet.HelloServelt</servlet-class>
    </servlet>
    <!--Servelt的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  • 配置Tomcat
  • 启动
    http://localhost:8080/s1/
    http://localhost:8080/s1/hello

Servlet原理

Servlet是由Web服务器调用,Web服务器在收到浏览器请求后,会:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKAoV0DO-1654181491989)(D:\studys\笔记\资料\JavaWeb\Servlet原理.png)]

Mapping问题

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

<!--Servelt的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

2、一个Servlet可以指定多个映射路径

<!--Servelt的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>

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

<!--Servelt的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>

4、默认请求路径

<!--Servelt的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

5、指定一些前缀或者后缀

<!--可以自定义后缀实现请求路径
    注意:*前面不能加 / -->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

6、优先级问题

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

ServletContext

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

1、共享数据

在这个Servlet创建的,可以在另一个Servlet中获得。

//设置值
public class HelloSrevlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        this.getInitParameter() 初始化参数
//        this.getServletConfig() Servlet配置
//        this.getServletContext() Servlet上下文
        ServletContext context = this.getServletContext();

        String username="sanmu";
        context.setAttribute("username",username);//将数据保存在ServletContext中
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
//获取值
public class GetServlet extends HelloSrevlet{
    @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");
        resp.setCharacterEncoding("utf-8");
        resp.getWriter().print(username);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
//Servlet注册
 <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.sanmu.servlet.HelloSrevlet</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.sanmu.servlet.GetServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>
2、获取初始化参数
<!--配置一些web应用初始化参数-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/</param-value>
    </context-param>
//读取
public class InitServlet extends HelloSrevlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url=context.getInitParameter("url");
        resp.getWriter().print(url);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
3、请求转发
public class RequestSrevlet extends HelloSrevlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        System.out.println("进入了RequestServlet");
//        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/init");//转发的请求路径
//        requestDispatcher.forward(req,resp);//调用forward()实现请求转发
        context.getRequestDispatcher("/init").forward(req,resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
//注册
 <servlet>
        <servlet-name>res</servlet-name>
        <servlet-class>com.sanmu.servlet.RequestSrevlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>res</servlet-name>
        <url-pattern>/res</url-pattern>
    </servlet-mapping>
4、读取资源文件

Properties

  • 在java目录下新建 .Properties文件
  • 在resources目录下新建 .Properties文件

发现:都被打包在同一个路径下(class路径);class,俗称这个路径为classpath

解决:在pom.xml加入build,并配置resources,来防止资源导出失败问题。

思路:需要一个文件流

public class PropServlet extends HelloSrevlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/dp.properties");
        Properties prop = new Properties();
        prop.load(is);
        String username=prop.getProperty("username");
        String password=prop.getProperty("password");
        resp.getWriter().print(username+":"+password);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
    }
}
<servlet>
        <servlet-name>prop</servlet-name>
        <servlet-class>com.sanmu.servlet.PropServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>prop</servlet-name>
        <url-pattern>/prop</url-pattern>
    </servlet-mapping>

HttpSrevletResponse(响应)

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

  • 如果要获取客户端请求过来的参数:找 HttpServletRequest
  • 如果要给客户端响应一些信息:找 HttpSrevletResponse
简单分类
  • 负责向浏览器发送数据的方法

    //ServletResponse接口
    ServletOutputStream getOutputStream() throws IOException;
    
    PrintWriter getWriter() throws IOException;
    
  • 负责向浏览器发送响应头的方法

    //ServletResponse接口
    void setCharacterEncoding(String var1);
    
    void setContentLength(int var1);
    
    void setContentLengthLong(long var1);
    
    void setContentType(String var1);
    
    void setDateHeader(String var1, long var2);
    
    void addDateHeader(String var1, long var2);
    
    void setHeader(String var1, String var2);
    
    //HttpServletRequest类
    void addHeader(String var1, String var2);
    
    void setIntHeader(String var1, int var2);
    
    void addIntHeader(String var1, int var2);
    
  • 响应状态码

    //HttpServletRequest类
    int SC_CONTINUE = 100;
    int SC_SWITCHING_PROTOCOLS = 101;
    int SC_OK = 200;
    int SC_CREATED = 201;
    int SC_ACCEPTED = 202;
    int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    int SC_NO_CONTENT = 204;
    int SC_RESET_CONTENT = 205;
    int SC_PARTIAL_CONTENT = 206;
    int SC_MULTIPLE_CHOICES = 300;
    int SC_MOVED_PERMANENTLY = 301;
    int SC_MOVED_TEMPORARILY = 302;
    int SC_FOUND = 302;
    int SC_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_USE_PROXY = 305;
    int SC_TEMPORARY_REDIRECT = 307;
    int SC_BAD_REQUEST = 400;
    int SC_UNAUTHORIZED = 401;
    int SC_PAYMENT_REQUIRED = 402;
    int SC_FORBIDDEN = 403;
    int SC_NOT_FOUND = 404;
    int SC_METHOD_NOT_ALLOWED = 405;
    int SC_NOT_ACCEPTABLE = 406;
    int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
    int SC_REQUEST_TIMEOUT = 408;
    int SC_CONFLICT = 409;
    int SC_GONE = 410;
    int SC_LENGTH_REQUIRED = 411;
    int SC_PRECONDITION_FAILED = 412;
    int SC_REQUEST_ENTITY_TOO_LARGE = 413;
    int SC_REQUEST_URI_TOO_LONG = 414;
    int SC_UNSUPPORTED_MEDIA_TYPE = 415;
    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;
    int SC_SERVICE_UNAVAILABLE = 503;
    int SC_GATEWAY_TIMEOUT = 504;
    int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
    
下载文件(步骤)
  • 要获取下载文件的路径
  • 获取下载的文件名
  • 想办法设置让浏览器能够支持下载需要的文件
  • 获取下载文件的输入流
  • 创建buffer缓冲区
  • 获取OutputStream对象
  • 将FileOutputStream流写入到buffer缓冲区
  • 使用OutputStream对象将缓冲区中的数据输出到客户端
public class Response extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //- 要获取下载文件的路径,注意路径问题
        String realPath = "D:\\ProgramFiles\\Java\\Project\\JavaWeb\\javaweb-01-servlet\\response\\src\\main\\resources\\1.png";
        //String realPath=this.getServletContext().getRealPath("/1.png");
        System.out.println("下载文件的路径:"+realPath);
        //- 获取下载的文件名
        String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
        //- 想办法设置让浏览器能够支持下载需要的文件,中文文件名设置编码:URLEncoder.encode(filename,"utf-8")
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
        //- 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        //- 创建buffer缓冲区
        int len=0;
        byte[] buffer=new byte[1024];
        //- 获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
        //- 将FileOutputStream流写入到buffer缓冲区, 使用OutputStream对象将缓冲区中的数据输出到客户端
        while((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        in.close();
        out.close();

    }

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

问题:路径问题;中文文件名乱码,设置编码:URLEncoder.encode(filename,“utf-8”);图片显示不下载,响应头符号,“Content-Disposition”,“attachment;filename=”。

验证码功能
  • 前端实现
  • 后端实现,需要用到 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/jpg");
        //网站存在缓存,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
        //把图片写给浏览器
        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 {
        doGet(req, resp);
    }
}
<servlet>
    <servlet-name>image</servlet-name>
    <servlet-class>com.sanmu.response.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>image</servlet-name>
    <url-pattern>/img</url-pattern>
</servlet-mapping>
实现重定向

一个Web资源B收到客户端A的请求后,B会通知A客户端去访问另一个Web资源C,这个过程就是重定向。

常见场景:

  • 用户登入

    //HttpServletResponse类
    void sendRedirect(String var1) throws IOException;
    
  • 测试

    public class Redirect extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            /**原理
             *resp.setHeader("Location","/r/img");
             *resp.setStatus(302);
             */
            resp.sendRedirect("/r/img");//重定向 
        }
    
        @Override
        protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           doGet(req, resp);
        }
    }
    
面试题:转发和重定向的区别
  • 相同点:页面都实现转发
  • 不同点:
    • 请求转发的时候,url不会发生变化;307
    • 重定向时,url地址栏会发生改变;302
用户登入案例
public class RequestText extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        if (username.equals("admin")&&password.equals("123456")){
            resp.sendRedirect("/r/success.jsp");
        }else{
            resp.sendRedirect("/r/404.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
    }
}
//index.jsp
<html>
<body>
<h2>Hello World!</h2>
<%--提交的路径为项目路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<form action="${pageContext.request.contextPath}/login" method="get">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit">
</form>
</body>
</html>
<servlet>
    <servlet-name>RequestText</servlet-name>
    <servlet-class>com.sanmu.response.RequestText</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RequestText</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

HttpServletRequest(请求)

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

获取传递的参数,请求转发

两个方法:

//ServletRequest接口
tring getParameter(String var1);
String[] getParameterValues(String var1);

测试

public class RequestTest 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");
        //通过请求转发,"/"代表当前应用
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登入页面</title>
</head>
<body>
<div>
    <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="音乐">音乐
        <br>
        <input type="submit">
    </form>
</div>
</body>
</html>
<servlet>
    <servlet-name>RequestTest</servlet-name>
    <servlet-class>com.sanmu.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RequestTest</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

5、Cookie、Session

Cookie:有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。

Session:“会话控制“。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。

会话

当用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器。这个过程称为会话。

保存会话的两种技术

  • Cookie:客户端技术(响应、请求)

  • Session:服务器技术。把用户的会话信息保存在Session对象中。

/**
 * Author:三木
 * Date:2022-03-31 16:08
 * Description:<保存用户上一次访问的时间>
 */
public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        PrintWriter out = resp.getWriter();
        //Cookie,服务器端从客户端获取
        Cookie[] cookies = req.getCookies();

        //判断Cookie是否存在
        if(cookies!=null){
            out.write("上一次访问时间:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //判断cookie的key
                if(cookie.getName().equals("lastloginTime")){
                    //获取cookie的值
                    long l = Long.parseLong(cookie.getValue());
                    Date date=new Date(l);
                    out.write(date.toLocaleString());
                }
            }
        }else{
            out.write("第一次访问本站");
        }
        //服务器给客户端响应一个cookie
        Cookie lastloginTime = new Cookie("lastloginTime", System.currentTimeMillis() + "");
        //lastloginTime.setMaxAge(0);//有效期一天,秒
        resp.addCookie(lastloginTime);
    }

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

乱码问题

//编码
URLDecoder.decode("你好","utf-8")
//解码
URLDecoder.decode("你好","utf-8")

Session

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session对象独占一个浏览器,只要浏览器没有关闭,这个Session就存在
Session和Cookie的区别
  • Cookie是把用户的数据写给用户浏览器,浏览器保存
  • Session把用户的数据写到用户独占的Session中,服务器端保存
  • Session对象由服务创建
使用场景
  • 保存用户登入信息
  • 购物车信息
  • 网站中经常使用的数据
测试
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Author:三木
 * Date:2022-04-05 15:48
 * Description:<描述>
 */
public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //得到Session
        HttpSession session = req.getSession();
        //给Session存东西
        session.setAttribute("name",new Person("三木",1));
        //获得Session的ID
        String id = session.getId();
        //判断Session是不是新创建
        if(session.isNew()){
            resp.getWriter().write("Session创建成功,ID:"+id);
        }else{
            resp.getWriter().write("Session已经存在,ID:"+id);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
        <servlet-name>SessionDemo01</servlet-name>
        <servlet-class>com.sanmu.servlet.SessionDemo01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SessionDemo01</servlet-name>
        <url-pattern>/s1</url-pattern>
    </servlet-mapping>
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Author:三木
 * Date:2022-04-05 16:07
 * Description:<描述>
 */
public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决乱码
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //得到Session
        HttpSession session = req.getSession();
        //给Session存东西
        Person person = (Person) session.getAttribute("name");
        System.out.println(person.toString());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
        <servlet-name>SessionDemo02</servlet-name>
        <servlet-class>com.sanmu.servlet.SessionDemo02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SessionDemo02</servlet-name>
        <url-pattern>/s2</url-pattern>
    </servlet-mapping>
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Author:三木
 * Date:2022-04-05 16:27
 * Description:<注销Session>
 */
public class SessionDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.removeAttribute("name");
        session.invalidate();//注销ID
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
        <servlet-name>SessionDemo03</servlet-name>
        <servlet-class>com.sanmu.servlet.SessionDemo03</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SessionDemo03</servlet-name>
        <url-pattern>/s3</url-pattern>
    </servlet-mapping>

设置Session自动失效

<!--web.xml-->
<!--设置Session失效时间,单位:分钟-->
<session-config>
    <session-timeout>15</session-timeout>
</session-config>

6、JSP

JSP原理

Java Server Pages,JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。

JSP是如何执行的

  • 服务器内部
    • Tomcat中有一个work目录
    • IDEA使用Tomcat会在IDEA中生成tomcat文件夹。页面会转变成Java程序。
  • JSP本质上 就是一个Servlet

JSP基础语法

jsp表达式
<%-- JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
jsp脚本片段
<%-- JSP脚本片段 --%>
<%
int sum=0;
for (int i = 1; i < 10; i++) {
    sum+=i;
}
out.println("<h1>sum="+sum+"</h1>");
%>
jsp声明
<%!
    static {
    System.out.println("静态代码块");
}
private int t=0;
public void st(){
    System.out.println(t);
}
%>
定制错误页面
  • 方法一

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%--定制错误页面--%>
    <%@ page errorPage="error/500.jsp" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <%
        int x=1/0;
    %>
    
  • 方法二

<!--web.xml-->
<?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">
    <error-page>
        <error-code>404</error-code>
        <location>/error/404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/error/500.jsp</location>
    </error-page>
</web-app>
jsp指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--包含文件
@include:将两个文件合二为一
--%>
<%@include file="common/header.jsp"%>
<h1>主体</h1>
<%@include file="common/footer.jsp"%>

<hr>
<%--jsp标签--%>
<jsp:include page="/common/header.jsp"/>
<h1>主体</h1>
<jsp:include page="/common/footer.jsp"/>
</body>
</html>
9大内置对象
  • PageContext

  • Request

  • Response

  • Session

  • Application

  • config

  • out

  • page

  • exception

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
    <%--内置对象--%>
    <%
        pageContext.setAttribute("name1","01");//保存的数据只在一个页面中有效
        request.setAttribute("name2","02");//保存的数据只在一次请求中有效,请求转发会携带这个数据
        session.setAttribute("name3","03");//保存的数据只在一次会话中有效,从浏览器打开到关闭
        application.setAttribute("name4","04");//保存的数据只在服务器中有效
    %>
    <%
        //从pageContext取出值,通过findAttribute寻找方式
        String name1 = (String) pageContext.findAttribute("name1");
        String name2 = (String) pageContext.findAttribute("name2");
        String name3 = (String) pageContext.findAttribute("name3");
        String name4 = (String) pageContext.findAttribute("name4");
        String name5 = (String) pageContext.findAttribute("name5");//不存在
    %>
    <%--使用EL表达式输出--%>
    <h1>取出的值</h1>
    <h3>${name1}</h3>
    <h3>${name2}</h3>
    <h3>${name3}</h3>
    <h3>${name4}</h3>
    <%--通过EL表达式输出,name5不会显示在客户端--%>
    <h3>${name5}</h3>
    </body>
    </html>
    
JSP标签、JSTL标签、EL表达式

导入jar包

<!-- jstl 表达式依赖 -->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!-- standard 标签库 依赖 -->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

JSP标签

<%--页面跳转--%>
<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="sanmu"/>
    <jsp:param name="age" value="12"/>
</jsp:forward>

JSTL标签

JSTL标签库的使用是为了弥补HTML标签的不足,自定义了许多标签。

使用需要引用标签库

  • 核心标签

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AuMIhfPF-1654181491993)(D:\studys\笔记\资料\JavaWeb\JSTL核心标签.png)]

EL表达式:${}

  • 获取数据

  • 执行运算

  • 获取web开发的常用对象

<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入核心标签库--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>if测试</h1>
<form action="jstlDemo.jsp" method="get">
    <%--EL表达式获取表单中的数据:${param.参数名}--%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登入">
</form>
<%--判断提交的用户名是否是管理员,是则登入--%>
<c:if test="${param.username=='admin'}" var="isadmin">
    <c:out value="管理员登入"/>
</c:if>
<c:out value="${isadmin}"/>

<hr>
<h1>choose测试</h1>
<%--定义变量score--%>
<c:set var="score" value="87"/>
<c:choose>
    <c:when test="${score>=90}">
        成绩优秀
    </c:when>
    <c:when test="${score>=70}">
        成绩良好
    </c:when>
    <c:when test="${score<=60}">
        成绩不及格
    </c:when>
</c:choose>
<hr>
<h1>forEach测试</h1>
<%
    ArrayList<String> list=new ArrayList<>();
    list.add("01");
    list.add("02");
    list.add("03");
    list.add("04");
    request.setAttribute("list",list);
%>
<%--
var:每一次遍历出来的变量
items:要遍历的对象
begin:开始位置
end:结束位置
step:步长
--%>
<c:forEach var="list" items="${list}">
    <c:out value="${list}"/><br>
</c:forEach>
<hr>
<c:forEach var="list" items="${list}" begin="1" end="3" step="2">
    <c:out valu e="${list}"/><br>
</c:forEach>
</body>
</html>
JavaBean

JavaBean是一种Java语言写成的可重用组件。 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。

JavaBean有特定的写法

  • 必须有一个无参构造
  • 属性必须是私有化
  • 必须有对应的set、get方法

7、MVC三层构架

MVC模式代表:Model-View-Controller(模型-视图-控制器)模式。

  • Model:业务模型,处理业务
  • View:视图,界面展示
  • Controller:控制器,处理请求,调用模型和视图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A3N3du6U-1654181491995)(D:\studys\笔记\资料\JavaWeb\mvc三层架构.png)]

三层构架

三层构架是将项目分成了三个层面:表现层、业务逻辑层、数据访问层。

作用:

  • 职责单一,互不影响
  • 有利于分工协作
  • 有利于组件重用
  • 表现层:接收请求,封装数据,调用业务逻辑层、响应数据。
  • 业务逻辑层:对业务逻辑进行封装、组合数据访问层中基本功能,形成复杂的业务逻辑功能。
  • 数据访问层:对数据库的CRUD基本操作。

MVC和三层架构的区别和联系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pv6S25oM-1654181491996)(D:\studys\笔记\资料\JavaWeb\三次架构.png)]

8、Filter-过滤器

filter过滤器,可以拦截所有访问web资源的请求和响应操作。

在Filter的doFilter方法内如果没有执行chain.doFilter(request,response)那么资源是不会被访问到的。

Filter开发步骤

  • 导入jar包

    <dependencies>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>javax.servlet.jsp-api</artifactId>
          <version>2.3.1</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp.jstl</groupId>
          <artifactId>jstl-api</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>taglibs</groupId>
          <artifactId>standard</artifactId>
          <version>1.1.2</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.23</version>
        </dependency>
      </dependencies>
    
  • 编写代码

    import javax.servlet.*;
    import java.io.IOException;
    
    /**
     * Author:三木
     * Date:2022-04-19 14:47
     * Description:<过滤器解决乱码问题>
     */
    public class CharacterEncodingFilter implements Filter {
        @Override
        //初始化,web服务器启动,就已经初始化了,随时等待过滤对象出现
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("CharacterEncodingFilter初始化");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            servletRequest.setCharacterEncoding("utf-8");
            servletResponse.setCharacterEncoding("utf-8");
            servletResponse.setContentType("text/html;charset=utf-8");
            //filterChain:链
            /*
            1、过滤中的所有代码,在代码特定请求的时候都会执行
            2、必须要让过滤器继续执行
             */
            filterChain.doFilter(servletRequest,servletResponse);//让请求继续走,如果不写,程序到这里就被拦截停止
        }
    
        @Override
        //注销,web服务器关闭的时候,过滤会注销
        public void destroy() {
            System.out.println("CharacterEncodingFilter注销");
        }
    }
    
  • 添加依赖

    <?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">
    
      <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.sanmu.servlet.ShowServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
      </servlet-mapping>
      <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
      </servlet-mapping>
      
      <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.sanmu.filter.CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是 /servlet路径下的任何请求,都会经过过滤器filter-->
        <url-pattern>/servlet/*</url-pattern>
      </filter-mapping>
    </web-app>
    

9、Listener-监听器

作用:监听某个事件的发生,状态的改变

实现监听

  • 实现监听器的接口

    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    /**
     * Author:三木
     * Date:2022-04-19 16:11
     * Description:<监听器。统计网站在线人数,即统计session>
     */
    public class OnlineCountListener implements HttpSessionListener {
        @Override
        //创建session监听
        //一旦创建Session就会触发一次这个事件
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext sessionContext = se.getSession().getServletContext();
            Integer onlineCount = (Integer) sessionContext.getAttribute("onlineCount");
            if(onlineCount==null){
                onlineCount=new Integer(1);
            }else{
                int count=onlineCount.intValue();//类型转换
                onlineCount=new Integer(count++);
            }
            sessionContext.setAttribute("onlineCount",onlineCount);
        }
    
        @Override
        //销毁session监听
        //一旦销毁Session就会触发一次这个事件
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext sessionContext = se.getSession().getServletContext();
            Integer onlineCount = (Integer) sessionContext.getAttribute("onlineCount");
            if(onlineCount==null){
                onlineCount=new Integer(0);
            }else{
                int count=onlineCount.intValue();//类型转换
                onlineCount=new Integer(count--);
            }
            sessionContext.setAttribute("onlineCount",onlineCount);
        }
    }
    
  • index.jsp页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <body>
    <h2>当前有<span><%=request.getServletContext().getAttribute("onlineCount")%></span>人在线</h2>
    </body>
    </html>
    
  • web.xml中注册监听器

    <!--注销监听器-->
      <listener>
        <listener-class>com.sanmu.listener.OnlineCountListener</listener-class>
      </listener>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值