JavaWeb

JavaWeb

一、基本概念

在Java中,动态web资源开发的技术统称为JavaWeb!

1.web应用程序: 可以提供浏览器访问的程序!

  • a.html,b.html多个web资源,这些web资源可以被外界访问,对外界提供服务!

  • 我们所能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。

  • web应用程序编写完毕后,若想提供给外界访问:需要一个服务器来统一管理

2.Web服务器

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

3.高难度面试题:

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

  1. 输入一个域名(www.longer.com),回车

  2. 检查本机(C:\Windows\System32\drivers\etc)目录下的配置文件hosts配置文件有没有这个域名映射;

  3. 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问

# localhost name resolution is handled within DNS itself.
#    127.0.0.1       localhost
#    ::1             localhost
     127.0.0.1       www.longer.com
  1. 没有:去DNS服务器找,找到的话就返回,找不到就找不到。

image

1.1 HTTP

超文本传输协议(Hyper Text Transfer Protocol,HTTP) 是一个简单的请求-响应协议,

  • 它通常运行在TCP之上。

  • 它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。

  • 请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。

请求方式:

  • GET:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏上显示数据内容,不安全,但高效

  • POST:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏上显示数据内容,安全,但不高效

  • PUT:

  • DELETE:

响应状态码:

  • 2xx : 请求响应成功

  • 3xx : 请求重定向

  • 4xx : 资源不存在

  • 5xx : 服务器内部错误

    • 502 : 网关错误

常见面试题:

当浏览器中的地址栏中输入地址,并回车的一瞬间到页面能够展示回来,经历了什么?

二、Maven

在JavaWeb开发中,我们需要使用大量的jar包,每次都需要手动导入,很麻烦!

如何实现自动导入和配置所需要的jar包,

由此,maven诞生了!

2.1 项目架构管理工具

Apache Maven,是一个软件(特别是Java软件)项目管理自动构建工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。

Maven项目使用项目对象模型(Project Object Model,POM)来配置。

2.2 下载安装maven

image

2.3 配置环境变量

MAVEN_HOME : D:\apache-maven-3.6.2
M2_HOME : D:\apache-maven-3.6.2\bin

配置Path

%MAVEN_HOME%\bin

配置完之后,dos命令检查是否配置成功

mvn -version

image

2.4 修改settings.xml

  1. 本地仓库:
<localRepository>D:\me\repository</localRepository>
  1. 阿里云镜像:(可配置多个)
<mirror>
        <id>nexus-aliyund</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </mirror>

2.5 maven资源导出问题

<!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.xml</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

三、Servlet

3.1 Servlet简介

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。

3.2 ServletContext

3.2.1 共享数据

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

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // this.getInitParameter() 初始化参数
        // this.getServletConfig() servlet配置
        // this.getServletContext() servlet上下文
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("username", "admin");
    }

从servlet中拿数据

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String username = (String) servletContext.getAttribute("username");
        resp.getWriter().println("username:" + username);
    }

3.2.2 获取初始化参数

在配置文件web.xml的配置,可以被读取到!

<!--配置一些web应用初始化参数-->
<context-param>
    <param-name>jdbcDriverUrl</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        String jdbcDriverUrl= servletContext.getInitParamet("jdbcDriverUrl");
        resp.getWriter().println("jdbcDriverUrl:" + jdbcDriverUrl);
    }

3.2.3 请求转发(forward)和重定向(sendRedirect)

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        // 转发的请求路径
        RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/gp");
        // 调用forward()方法,实现请求转发
        requestDispatcher.forward(req, resp);
//        servletContext.getRequestDispatcher("/gp").forward(req, resp);

    }

请求转发: A想访问C,但是又不能直接访问C,只有先访问B,由B访问C,把C的返回结果给B,B在把结果给A。所以请求转发路径不会变!

image

请求重定向: A对B说,我想拿一个资源,但是B没有,B对A说,你去向C拿吧,于是A又去找C拿,C把资源返回给了A。所以请求重定向的路径会改变!
image

void sendRedirect(String var1) throws IOException;
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("/down");
    }

3.2.4 读取资源文件

Properties:

  • 在java目录下新建properties文件

  • 在resource目录下新建properties文件

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

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/class/db.properties");
        Properties properties = new Properties();
        properties.load(is);
        String name = properties.getProperty("username");
        String pwd = properties.getProperty("password");

        resp.getWriter().println(name + ":" + pwd);

    }
username=root
password=123456

3.3 HttpServletResponse

3.3.1 简单分类

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

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

  • 要给客户端详情一些信息,找HttpServletResponse

负责向浏览器发送数据的方法:

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

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

void setCharacterEncoding(String var1);

void setContentLength(int var1);

void setContentLengthLong(long var1);

void setContentType(String var1);

void setBufferSize(int var1);

void setHeader(String var1, String var2);

void addHeader(String var1, String var2);

void setIntHeader(String var1, int var2);

void addIntHeader(String var1, int var2);

void setStatus(int var1);

响应状态码:

    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;

3.3.2 常见应用

  1. 向浏览器输出消息

  2. 下载文件

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.获取下载文件的路径
        String realPath = "D:\\1.png";
        System.out.println("下载的文件的路径为:" + realPath);
        // 2.获取下载文件的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3.设置让浏览器支持下载,中文文件名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);
        }

        out.close();
        in.close();
    }

3.4 HttpServletRequest

四、Cookie、Session

会话技术!

  • 客户端技术(响应、请求)
  1. 从请求中拿到cookie信息

  2. 服务器响应给客户端cookie

Cookie[] cookies = req.getCookies();  // 获得Cookie
cookies.getName();  // 获得cookies中的key
cookies.getValue();  // 获得cookies中的value
new Cookie("lastLoginTime", System.currentTimeMillis()+"");  // 新建一个cookie
cookie.setMaxAge(24*60*60);  // 设置cookie的有效期
resp.addCookie(cookie);  // 相应给客户端一个cookie

Cookie:一般会保存再本地的用户目录下 appdata

一个网站cookie是否存在上限?

  • 一个Cookie只能保存一个信息

  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie

  • 而浏览器的cookie上限为300个

  • cookie大小有限制,4kb

删除Cookie:

  • 不设置有效期,浏览器关闭,自动失效

  • 设置有限期时间为0

编码、解码

URLEncoder.encode("虚怀若谷", "utf-8");
URLDecoder.encode(cookie.getValue(), "utf-8");

4.2 Session:

  • 服务器技术。利用这个技术,可以保存用户的会话信息,我们可以把信息或者数据放在Session中!

  • 服务器会给每一个用户(浏览器)创建一个Session对象

  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在

  • 用户登录之后,整个网站它都可以访问! 保存用户的信息;保存购物车的信息.....

Cookie和Session的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)

  • Session是把用户的数据写到用户独占Session中,服务端保存(保存重要的信息,减少服务器资源的浪费)

  • Session对象由服务器创建

使用场景:

  • 保存一个登录用户的信息

  • 购物车信息

  • 在整个网站中,经常会使用的数据

// 获取session
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("name");
// 移除session
session.removeAttribute("name");
// 手动注销session
session.invalidate();

会话自动过期,web.xml中配置

<!--设置session默认的失效时间-->
<session-config>
    <!--15分钟后session自动失效,以分钟为单位-->
    <session-timeout>15</session-timeout>
</session-config>

五、JSP

5.1 什么是JSP

Java Server Pages: Java服务端页面,也和Servlet一样,用于动态web技术

最大的优点:

  • 写JSP就像在写HTML

  • 区别:

    • HTML只能给用户提供静态的数据

    • JSP页面可以嵌入Java代码,为用户提供动态数据

5.2 JSP原理

思路:JSP到底怎么执行的!

  • 代码层面没有任何问题

  • 服务器内部工作

    • tomcat中有一个work目录

    • IDEA中使用tomcat的会在IDEA的tomcat中生成一个work目录

在JSP页面中:

只要是Java代码,就原封不动的输出

如果是HTML代码,就会被转换为

out.write("<html>\r\n");

这样的格式,输出到前端!

5.3 JSP九大内置对象

  1. PageContext // 保存的数据只在一个页面中有效

  2. Request // 保存的数据只在一次请求中有效,请求转发会携带这个数据

  3. Response

  4. Session // 保存的数据只在一次会话中有效,从浏览器打开到浏览器关闭

  5. Application(ServletContext) // 保存的数据只在服务器中有效,从打开服务器到关闭服务器

  6. config(ServletConfig)

  7. out

  8. page

  9. exception

pageContext.setAttribute("name", "jack1");  // 保存的数据只在一个页面中有效
request.setAttribute("name", "jack2");  // 保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name", "jack3");  // 保存的数据只在一次会话中有效,从浏览器打开到浏览器关闭
application.setAttribute("name", "jack4");  // 保存的数据只在服务器中有效,从打开服务器到关闭服务器

request: 客户端向服务端发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的

session: 客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车

application: 客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据

六、MVC三层架构

什么是MVC: Model、View、Controller , 模型、视图、控制器

Model:

  • 业务处理:业务逻辑(Service)

  • 数据持久层:CRUD(Dao)

View:

  • 展示数据

  • 提供链接发起Servlet请求

Controller(Servlet):

  • 接收用户的请求:(req:请求参数、Session信息...)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

七、过滤器Filter (重点)

Filter: 过滤器,用来过滤网站的数据!

  • 处理中文乱码

  • 登录验证

image

7.1 编写过滤器的步骤

  1. 导包
    <dependencies>
        <!--Servlet依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <!--JSP依赖-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <!--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>
        <!--连接数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
    </dependencies>
  1. 编写过滤器类
package cn.com.longer.filter;

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

public class CharacterEncodingFilter implements Filter {
    /*
    初始化:web服务器启动,就会走此init()方法,随时等待过滤对象出现!
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter进入过滤器init()方法......");
    }

    /*
    chain : 链
    1.过滤器中的所有代码,在过滤特定请求的时候都会执行
    2.必须要让过滤器继续前行:chain.doFilter(request, response);
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        System.out.println("CharacterEncodingFilter中的doFilter()方法执行前...");
        chain.doFilter(request, response);  // 让我们的请求继续走,如果不写,程序到这就会被拦截停止!!!
        System.out.println("CharacterEncodingFilter中的doFilter()方法执行后...");
    }

    /*
    销毁:web服务器关闭的时候,过滤器才会销毁
     */
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter进入过滤器destroy()方法......");
    }
}
  1. 编写Servlet
package cn.com.longer.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("大风起兮云飞扬,安得猛士兮走四方!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 在web.xml中配置servlet、filter
<?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">

    <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>cn.com.longer.servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show/servlet</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet</url-pattern>
    </servlet-mapping>

    <!--servlet类写servlet,过滤器类也要写servlet-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>cn.com.longer.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--/user/* : 代表/user路径下的所有请求,都要被过滤-->
        <url-pattern>/show/*</url-pattern>
    </filter-mapping>
</web-app>

八、监听器Listener

8.1 实现监听器步骤

  1. 编写监听器类
package cn.com.longer.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnlineCountListener implements HttpSessionListener {
    /*
    创建session监听
    一旦创建session,就会触发一次这个事件
     */
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount == null){
            onlineCount = new Integer(1);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count + 1);
        }
        ctx.setAttribute("OnlineCount", onlineCount);
    }

    /*
    销毁session监听
    一旦销毁session,就会触发一次这个事件!
    session销毁:
    1.手动销毁:getSession.invalidate();
    2.自动销毁:web.xml中配置
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();
        se.getSession().invalidate();

        Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
        if (onlineCount == null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count - 1);
        }
        ctx.setAttribute("OnlineCount", onlineCount);
    }
}
  1. 页面输出
<h1>当前有 <span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%>  </span> 人在线</h1>
  1. 配置web.xml
    <!--注册监听器-->
    <!--listener-class只注册此即可-->
    <listener>
        <listener-class>cn.com.longer.listener.OnlineCountListener</listener-class>
    </listener>
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

九、过滤器、监听器常见应用

监听器: GUI编程中经常使用

用户登录之后才能进入主页!用户注销后就不能进入主页了!

  1. 用户登录之后,向Session中放入用户的数据

  2. 进入主页的时候要判断用户是否已经登录,要求在过滤器中实现

posted @   zlonger  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示