后端工程师之路(3)web核心

完整博文地址

  • 由于CSDN的图片导入机制的问题,导致在本地编写的md文档中的图片无法上传到CSDN上,因此我把博文push到了gitee上,以下是地址:请点击:我的博文地址

1. web核心简介

  • B/S架构:Browser/Server,浏览器/服务器架构模式,它的特点是:客户端只需要浏览器,应用程序的逻辑和数据集都存储在服务器,浏览器只需要请求服务器,获取WEB资源,服务器把WEB资源发送给浏览器即可
  • 静态资源:HTML、CSS、JavaScript、图片等。负责页面展现
  • 动态资源:Servlet、JSP等,负责逻辑处理
  • 数据库:负责存储数据(持久化)
  • HTTP:定义通信规则
  • WEB服务器:负责解析HTTP协议,解析请求数据,并发送响应数据,如Tomcat

2. HTTP(Hyper Text Transfer Protocol)

2.1 HTTP简介

  • 概念:超文本传输协议,规定了浏览器和服务器之间数据传输的规则
  • 基于TCP协议(三次握手):面向连接,安全
  • 基于请求-响应模型的:一次请求对应一次响应
  • HTTP协议是无状态的协议,对于事务处理没有记忆能力,每次请求-响应都是独立的
    • 缺点:多次请求间不能共享数据,JAVA中使用会话技术(Cookie、Session)来解决这个问题
    • 优点:速度快

2.1 请求数据的格式

  • 请求行:请求数据的第一行,其中GET表示请求方式,/表示请求资源的路径,HTTP/1.1表示协议版本
  • 请求头:第二行开始,格式为key:val形式
  • 请求体:POST请求的最后一部分,存放请求参数
  • 常见的HTTP请求头:
    • Host:表示请求的主机名
    • User-Agent:浏览器版本
    • Accept:表示浏览器能接收的资源类型
    • Accept-Language:表示浏览器偏好的语言,服务器可以根据此返回不同语言的网页
    • Accept-Encoding:表示浏览器可以支持的压缩类型
  • GET请求和POST请求的区别:
    • GET请求参数在请求行中,没有请求体,POST请求参数在请求体中
    • GET请求参数参数大小有限制,而POST请求没有

2.2 响应数据的格式

  • 响应行:响应数据的第一行。其中HTTP/1.1表示协议版本,200表示响应状态码,OK表示状态码描述

  • 响应头:第二行开始,格式为key:val

  • 响应体:最后一部分,存放响应数据

  • 常见的HTTP响应头:

    • Content-Type:表示该响应内容的类型,录入text/html,image/jpeg
    • Content-Length:表示该响应内容的长度(字节数)
    • Content-Encoding:表示该响应压缩算法,例如gzip
    • Cache-Contro:指示客户端应该如何缓存,例如max-age=300表示最多可以缓存300秒

2.3 响应状态码粗分类

状态码分类说明
1xx响应中–临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它
2xx成功–表示请求已经被对方所接受,处理已经完成
3xx重定向–重定向到其他地方,它让客户端再发起一个请求以完成整个处理过程
4xx客户端错误–处理发生的错误,责任在于客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
5xx服务端错误–处理发生的错误,责任在于服务端,如:服务端抛出了异常,路由出错,HTTP版本不支持等等

2.4 常见响应状态码

状态码英文描述解释
200OK客户端请求成功,即处理成功
302Found指示所请求的资源已移动到由Location响应头所给定的URL,浏览器会自动重新访问到这个页面
304Not Modified告诉客户端,你请求的资源自上次取得后,服务端并未更改,直接使用本地缓存即可。隐式重定向
400Bad Request客户端有语法错误,不能被服务器所理解
403Forbidden服务器收到请求,但是拒绝提供服务,比如:没有权限访问相关资源
428Precondition Required服务器要求有条件的请求,告诉客户端想要访问某资源,必须携带特定的请求头
429Too Many Requests太多请求,可以限制客户端请求某个资源的数量,配合Retry-After(多长时间可以请求)响应头一起使用
431Request Header Fields Too Large请求头太大,服务器不愿意处理该请求,因为头部字段太大,请求可以减少请求头域大小偶重新提交该请求
405Method Not Allowed请求方式有误,比如用GET请求方式才能请求到的资源,用了POST
500Internal Server Error服务器发生了不可预期的错误,服务器产生了异常
503Service Unavailable服务器尚未准备好处理请求,服务器刚刚启动,还未初始化好
511Network Authentication Required客户端需要进行身份验证才能获得网络访问权限

3. web服务器-Tomcat

3.1 简介

  • web服务器是一个应用程序,对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作,让web开发更加便捷,主要功能是提供网上信息浏览服务
  • Tomcat也称为Web容器,Servlet容器,Servel需要依赖Tomcat才能运行

3.2 Tomcat的配置以及项目部署

  • 修改启动端口号:conf/server.xml
  • 项目部署:将项目放到webapps下,即部署完成
  • 一般JavaWeb项目会被打包成war包,然后将war包放到webapps目录下,Tomcat将会自动解压缩war文件

3.3 Maven Web项目结构

  • Web项目结构

    • Maven Web项目结构:开发中的项目
    • webapps(web项目特有的目录)
      • WEB-INF(web项目核心目录)
        • web.xml(web项目配置文件)
    • 部署的JavaWeb项目结构:开发完成,可以进行部署的项目
      • WEB-INF(WEB项目核心目录)
        • classes(JAVA字节码文件)
        • lib(项目所需jar包)
        • web.xml(web项目配置文件)
  • 创建方式

    • 使用骨架(项目模板)
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aoVBz4rR-1657094983216)(./image/新建mavenWeb项目.png)]

然后检查maven变量是否正确即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAdhVkvG-1657094983217)(./image/新建mavenWeb目录结构.png)]

  • maven的打包方式
    • jar打包(默认)
    • war打包
<packaging>war</packaging>
<packaging>jar</packaging>

4. Servlet

  • Java提供的动态Web资源开发技术

4.1 Servel快速入门

  • 引入依赖
    <!-- servlet依赖 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
      <!--这里要配置为provided(在编译环境和测试环境下是有效的而在运行环境下是无效的)-->
      <!--这是因为 tomcat中已经内置了servlet的jar包了,如果再在运行环境下再去依赖这个jar包就会冲突报错-->
    </dependency>
  • 创建:定义一个类,实现servelt接口,并重写接口中的所有方法,编写service方法
 package com.demo.web;

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

public class ServletDemo implements Servlet {

    public void init(ServletConfig servletConfig) throws ServletException {

    }

    public ServletConfig getServletConfig() {
        return null;
    }

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet hello world!");
    }

    public String getServletInfo() {
        return null;
    }

    public void destroy() {

    }
}

  • 配置:在类上使用@WebServlet注解,配置该Servlet的访问路径
@WebServlet("/hello")
  • 访问:启动tomcat,输入url访问该servlet

4.2 Servlet执行流程与生命周期

  • 执行流程:简单来说就是服务器拿到了我们自己写的Servlet类,然后根据这个类的属性与方法去创建Servlet对象,里面提供service()方法,当有人来访问我们的服务的时候,tomcat拿着这个对象,执行service()方法,就是这样一回事。
  • Servlet对象的生命周期
    • 加载和实例化:默认情况下,当Servlet第一次被访问的时候,由容器来创建Servlet对象
    • 初始化:在Servlet实例化之后,容器将调用Servlet的init()方法来对对象进行初始化,完成一些例如加载配置文件,创建连接等初始化的工作,该方法是只调用一次的
    • 请求处理:每次请求Servlet时,Servlet容器都会调用service()方法对请求进行处理
    • 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destory()方法来完成资源的释放,在destory()方法调用之后,容器就会释放该实例,该随后被JVM的GC所回收
//当loadOnStartup是负整数的时候,第一次访问时创建Servlet
//当是0或者正整数的时候,服务器启动时就创建Servlet对象,数字越小优先级越高
@WebServlet(value = "/hello",loadOnStartup = -1)

4.3 Servlet体系结构

  • htppsServlet
package com.demo.web;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(urlPatterns = "/demo3",loadOnStartup = 1)
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("get..");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("post..");
    }
}
//从浏览器值直接输入url访问的方式是get的方式

        //根据请求方式不同,分发post请求和get请求
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        String method = req.getMethod();
        if("GET".equals(method)){

        }else if("POST".equals(method)){

        }
//实际上就是做请求的分发而已

4.4 urlPettern配置

  • 一个servlet可以配置多个urlPattern
@WebServlet(urlPatterns = {"/demo1","/demo2"})
  • url配置规则
    • 精确匹配:@WebServlet(urlPatterns = {"/demo1","/demo2"})
    • 目录匹配:@WebServlet(urlPatterns = {"/demo1/*"}),该目录下所有的都访问该servlet
    • 扩展名匹配:@WebServlet(urlPatterns = {"*.do",})
    • 任意匹配:@WebServlet(urlPatterns = {"/"}),@WebServlet(urlPatterns = {"/*"})

5. Request

5.1 Request继承体系

  • ServeltRequest->JAVA提供的请求对象根接口
  • HttpServeltRequest->JAVA提供的对HTTP协议封装的请求对象接口
  • RequestFacade->Tomcat定义的实现类
  • Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中

5.2 Request获取请求数据

  • 请求行
    • GET /RESOURCE_DIR/ HTTP/1.1
String getMethod();//获取请求方式:GET
String getContextPath();//获取虚拟目录(项目访问路径):/request-demo,动态获取
StringBuffer getRequestURL();//获取URL(统一资源定位符)
String getRequestURI();//获取URI
String getQueryString();//获取请求参数(GET方式) 
  • 请求头
String getHeader(String name);//根据请求头名称,获取值
  • 请求体:只有POST才有请求体
ServletInputStream getInputStream();//获取字节输入流
BufferReader getReader();//获取字符输入流
  • 通用方式获取请求参数
String method = this.getMethod();
if("GET".equals(method)){
    params = this.getQueryString();
}else if("POST".equals(methid)){
    BufferedReader reader = this.getReader();
    params = reader.readLine();
}
  • API
Map<String,String[]> getParamterMap();//获取所有参数Map的集合
String[] getParamterValues(String name);//根据名称获取参数值(数组)
String getParamter(String name);//根据名称获取单个数值
        Map<String, String[]> parameterMap = req.getParameterMap();
        for(String key:parameterMap.keySet()){
            System.out.print(key+":");
            for(String string: parameterMap.get(key)){
                System.out.print(string+" ");
            }
            System.out.println();
        }
        //2.根据key获取参数值
        System.out.println(req.getParameterValues("hobby"));
        //3.根据key获取单个参数值
        String userName = req.getParameter("username");
        System.out.println(userName);
  • POST解决中文乱码问题
//POST的底层处理是通过字符输入流来写的,因此如果字符编码不一致的话就会产生乱码
req.setCharacterEncoding("UTF-8");
  • GET解决中文乱码问题
    public String modifiedEncoding(String string){
        byte[] bytes = string.getBytes(StandardCharsets.ISO_8859_1);
        //然后再将bytes数组转换为UTF-8
        return new String(bytes,StandardCharsets.UTF_8);
        //可以写作为 一行
        return new String(string.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
    }

5.3请求转发

  • 请求转发(forward):一种在服务器内部的资源跳转方式,简单来说就是当一个请求,单个资源所不能完全处理的时候,这个请求就会被转发到其他资源,让其他资源来完成这个请求的响应。
req.getRequestDispatcher("资源B路径").forward(req,resp);
  • 请求转发资源间共享数据:使用Request对象
    • void setAttribute(String name,Object o):存储数据到request域中
    • Object getAttribute(String name):根据key值获取值
    • void removeAttribute(String name):根据key,删除该键值对
  • 请求转发的特点
    • 浏览器地址栏路径不发生变化
    • 只能转发到当前服务器内部的资源
    • 一次请求,可以在转发的资源间使用request共享数据

6. Response

  • 使用Response对象来设置响应数据
  • ServletResponse(JAVA提供的请求对象接口)
  • HttpServletResponse(JAVA提供的对Http协议封装的请求对象)
  • ResponseFacade(Tomcat定义的实现类)

6.1 Response设置响应数据功能介绍

  • void setStatus(int sc):设置响应状态码
  • void setHeader(String name,String value):设置响应头键值对
  • PrintWriter getWriter():获取字符输出流
  • ServletOutputStream getOutputStream():获取字节输出流

6.2 Response重定向(Redirect)

  • 重定向:一种资源重定向方式,可以重定向到外部服务器资源

    • 浏览器地址栏会发生变化
    • 可以重定向到任意位置的资源(服务器内部、外部均可)
    • 内部的话写虚拟目录即可,外部则需要完整的HTTPURL
    • 两次请求,不能在多个资源使用request共享数据
  • 示例代码

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("resp1....");
        //重定向
        //1.设置响应状态码
        response.setStatus(302);
        //2.设置头
        response.setHeader("Location","/tomcat-demo/resp2");//要写虚拟目录
        //简化重定向的写法
        response.sendRedirect("/tomcat-demo/resp2");//只需要填入重定向的资源地址即可,
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("resp2....");
    }
  • 关于路径使用的问题
    • 首先明确路径是谁使用的,如果是浏览器使用的,那么就需要加虚拟目录,如果是服务端使用的,则不需要加虚拟目录

6.3 Response响应字符数据

  • 通过PrintWriter getWriter()来获取字符输出流,直接写入字符即可,tomcat将直接将该数据传入响应体的位置

  •         System.out.println("resp3....");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            response.setHeader("content-type","text/html");
            writer.write("<h1>你好<h1>");//流的默认编码字符是ISO-8859-1
    

6.4 Response响应字节数据

        System.out.println("resp4....");
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write("<h1>你好<h1>".getBytes(StandardCharsets.UTF_8));
        response.setHeader("content-type","text/html");

7. 登录注册案例练习

  • 准备数据库
/*1.创建数据库*/
create database db1;
/*2.进入数据库,创建user表*/
use db1;
create table user(
    id int primary key auto_increment,
    username varchar(15),
    password varchar(15)
);
/*3.手动添加数据*/
insert into user(username,password) values ("张三","123456"),("李四","123456");
/*4.校验数据*/
select * from user;
/*这里不小心忘记了设置了唯一索引*/
alter table user add unique (username);

desc user;
  • 准备mybatis文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.demo.web.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/db1?serverTimezone=GMT&amp;useSSL=false&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.demo.web.Mapper"/>
    </mappers>

</configuration>
  • 创建映射文件
  • UserMapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.web.mapper.UserMapper">

</mapper>
package com.demo.web.mapper;

public interface UserMapper {
    @Select("select * from user where username = #{username} and password =#{password}")
    User selectByNameAndPassword(@Param("username") String username, @Param("password") String password);
}

  • 编写servelt代码
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.接收用户名和密码
        String username = new String(request.getParameter("username").getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8.toString());
        String password = new String(request.getParameter("password").getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8.toString());
        System.out.println("username:"+username+",password:"+password);
        //2.调用数据库
        String resource  = "mybatis-config.xml";
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.selectByNameAndPassword(username,password);
        sqlSession.close();

        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        if(user != null){
            writer.write("登录成功");
        }else{
            writer.write("登录失败");
        }
    }
  • 编写注册的代码
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.接收用户名和密码
        String username = new String(request.getParameter("username").getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8.toString());
        String password = new String(request.getParameter("password").getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8.toString());
        System.out.println("username:"+username+",password:"+password);
        //2.调用数据库
        String resource  = "mybatis-config.xml";
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.selectByName(username);

        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        if(user != null){
            writer.write("当前用户已经存在了,不让注册");
        }else{//用户不存在
            User newUser = new User();
            newUser.setUsername(username);
            newUser.setPassword(password);
            mapper.addUser(newUser);
            sqlSession.commit();
            writer.write("注册成功");
        }
        sqlSession.close();
    }
  • 工具类抽取
package com.demo.web.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactoryUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource  = "mybatis-config.xml";
            InputStream resourceAsStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }

}

8. JSP(Java Server Pages)JAVA服务端页面

8.1 快速入门

<html>
<body>
 <h1>hello jsp</h1>
<%
    System.out.println("hello jsp");
%>
</body>
</html>

8.2 JSP原理

  • JSP本质上就是一个servlet

  • .jsp->servlet->(编译)class->响应请求

  • jsp在被访问时,由JSP容器(Tomcat)将其转化为JAVA文件(Servlet),在由JSP容器(Tomcat)将其编译时,最终对外提供服务的就是这个字节码文件

8.3 JSP缺点

总之就是很多缺点,做下了解就好了,不用深入学

  • 替代方案:HTML+AJAX

9.MVC模式和三层架构

  • MVC是一种分层开发的模式,其中:
    • M:Model,业务模型,处理业务,在JAVA中不单指pojo,而是指java-bean
    • V:View,视图,页面显示
    • C:Controller,控制器,处理请求,调用模型和视图
  • 三层架构
    • 表现层:接收请求,封装数据,调用业务层逻辑,响应数据(controller)
    • 业务逻辑层:对业务逻辑进行封装,组合数据访问层中基本功能,形成复杂的业务逻辑功能(service)
    • 数据访问层:对数据库进行CRUD的操作(mapper(mybatis)/dao)

10. 会话跟踪技术

10.1 会话技术简介

  • 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束,在一次会话中可以包含多次请求和响应

  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一服务器,以便在同一次会话的多次请求间共享数据

  • HTTP协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话内数据共享

  • 实现方法

    • 客户端会话跟踪技术:Cookie
    • 服务端会话跟踪技术:Session

10.2 Cookie

10.2.1 Cookie基本使用

  • cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问

  • Cokkie的基本使用

    • 发送Cookie
    //1.创建cookie对象,设置数据
    Cookie cookie = new Cookie("key","value");
    //2.发送cookie到客户端,使用response对象 
    response.addCookie(cookie);
    
    • 获取Cookie

              //1.获取cookie
              Cookie[] cookies = request.getCookies();
              for(Cookie cookie:cookies){
                  System.out.println(cookie.getName()+" :"+cookie.getValue());
              }
      

10.2.2 Cookie原理

  • Cookie是基于HTTP协议的
    • 响应头:set-cookie,当服务端需要为客户端建立cookie时,写入cookie,通过HTTP协议发送给服务端
    • 请求头:cookie,当客户端给服务端发送请求时,自动携带该请求头,携带cookie供其使用
  • cookie存活时间
    • 默认情况下,Cookie存储在浏览器内存中,当浏览器关闭时,内存释放,则Cookie就被销毁
    • 为了解决默认情况下的问题,要做持久化
    • setMaxAge(int seconds):设置cookie的存活时间
      • 正数:将cookie写入浏览器所在电脑的硬盘中,持久化存储,到时间则自动销毁
      • 负数:默认值,cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
      • 零:删除对应的cookie
  • cookie存储中文
    • Cookie不能直接存储中文
    • 如需要存储,则使用URL编码URLEncoder

10.3 Session

10.3.1 Session基本使用

  • Session:服务端会话跟踪技术,将数据保存到服务端
  • JAVAEE提供了HttpSession接口,来实现一次会话多次请求间数据共享功能
  • 其主要功能就是保存上一次请求的数据到服务端,在服务端可以直接调用服务器的session,注意:其调用的session是一次会话中的

10.3.2 Session原理

  • Session的实现是基于cookie的

  • 实现细节

    • 服务端内部有一个session池,每一个session有一个唯一标识的sessionId
    • 每次客户端请求的时候,会发送set-cookie:JESSIONID给服务端
    • 服务端根据SessionId来识别会话是否是同一次的,若是同一次会话,则返回指定的Session对象供其使用
    • 以此保证一次会话,对应唯一的一个session
  • session钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘

  • session活化:再次启动服务器后,从文件中加载数据到Session

  • session销毁

    • 默认情况下,无操作,则在30min内销毁
    • 调用invalidate()

11. Filter

11.1 简介

  • 概念:Filter表示过滤器,是java-web三大组件(Servlet、Filter、Listener)之一
  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
  • 过滤器一般完成一些通用的操作:权限控制统一编码处理敏感字符处理

11.2 快速入门

package com.demo.web.filter;


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")//拦截所有资源
public class FilterDemo implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //1.编写放行前逻辑
        System.out.println("正在拦截资源");
        //2.执行放行
        filterChain.doFilter(servletRequest,servletResponse);
        //3.编写放行后逻辑
    }

    @Override
    public void destroy() {

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3uTvqFCO-1657094983218)(./image/Filter原理.png)]

11.3 Filter拦截路径配置

  • 拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
  • 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
  • 后缀名拦截:*.jsp,访问后缀名为jsp的资源,都会被拦截
  • 拦截所有:/*:访问所有资源,都会被拦截
  • 一个web应用,可以配置多个过滤器,这多个过滤器称为过滤器链
  • 注解配置的Filter,优先级按照过滤器类名(字符串)的自然排序

12. Listener

  • 概念:Listener表示监听器,是JAVAWeb三大组件之一
  • 监听器可以监听在application、session、request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件
  • Listener分类
监听器分类监听器名称作用
ServletContext监听ServletContextListener用于对SerlvetContext对象进行监听(创建、销毁)
ServletContextAttributeListener对ServletContext对象中的属性进行监听(增删改属性)
Session监听HttpSessionListener用于对Session对象的整体状态进行监听(创建、销毁)
HttpSessionAttributeListener对Session对象中的属性进行监听(增删改属性)
HttpSessionBindingListener监听对象于Session的绑定和解除
HttpSessionActivationListener对Session数据的钝化和活化的监听
Request监听ServletRequestListener对Request对象进行监听(创建、销毁)
ServletRequestAttributeListener对Request对象中的属性进行监听(增删改属性)
  • 快速入门代码
package com.demo.web.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener //启动该监听器
public class ContextLoaderListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //加载资源
        System.out.println("contextInitialized");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //释放资源

    }
}

13. AJAX

13.1 简介

  • 概念:AJAX(Asynchronous JavaScript And XML):异步的JavaScript和XML
  • 作用
    • 与服务器进行数据交换,通过AJAX可以给服务器发送请求,并获取服务器响应的数据
    • 使用AJAX和服务器进行通信,就可以使用HTML+AJAX来替换JSP页面了
    • 异步交互:可以在不加载整个页面的情况下,与服务器交换数据并更新部分网页的技术

13.2 快速入门

    //1.创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //2.发送请求
    xhttp.open("GET", "http://localhost:8890/ajax-demo/ajaxServlet", true);//异步交互路径写全路径
    xhttp.send();
    //3.获取响应
    xhttp.onreadystatechange = function (){//不断监听该属性,当属性发生变化时执行function()
        if(this.readyState == 4 && this.status == 200){
            alert(this.responseText);
        }
    }

13.3 axios异步框架

  • 简单来说就是对ajax进行了封装
<!--引入axios源码-->
<script src="js/axios-0.18.0.js"></script>
<script>
    //1.get请求编写实例
    //传入一个js对象
    //注意是url-get传参
    //.then()接收一个回调函数
    axios({
        method :"get",
        url:"http://localhost:8890/ajax-demo/axiosServlet?username=zhangsan"
    }).then(function (resp) {//原理也是不断监听响应的情况
        alert(resp.data)
    })
    //2.post请求编写实例
    axios({
        method: "post",
        url: "http://localhost:8890/ajax-demo/axiosServlet",
        data:zhangsan
    }).then(function (resp){
        alert(resp.data)
    })
    //3.更加简化的有
    axios.get("http://localhost:8890/ajax-demo/axiosServlet?username=zhangsan").then(function (resp) {
        alert(resp.data);
    })
    //4.更加简化的有
    axios.get("http://localhost:8890/ajax-demo/axiosServlet","username=zhangsan ").then(function (resp) {
        alert(resp.data);
    })


</script>

14.Json

14.1 简介

  • JSON:JavaScript Obejct Notaion,JavaScript对象表示法
var 变量名 = {
    "key1":value1,
    "key2":value2
    ...
}
//获取数据
变量名.key
json.name

14.2 API

  • JSON.toJSONString(user)
  • JSON.parseObject(jsonStr,Object.class)

15. Vue

15.1 Vue简介

  • Vue是一套前端框架,免除原生JavaScript中的DOM操作,简化书写
  • 基于MVVM(Model-view-view-Model),实现数据的双向绑定,将编程的关注点放在数据上

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YUA7kDto-1657094983219)(./image/MVVM.png)]

  • 使用这个框架的最大好处是,之前通过MVC框架可知,并没有直接的通道可以实现模型和视图层的双向绑定,而通过该模型就可以实现模型和视图层的双向绑定,视图变则模型变,模型变则视图变

15.2 Vue常用指令操作

  • v-bind:为HTML标签绑定属性值,如设置href,css样式等
  • v-model:为表单元素创建双向数据绑定
  • v-on:为HTML标签绑定事件
  • v-for:列表渲染,遍历容器的元素或者对象的属性
    <!-- vue核心控制id为app的组件,将代码写在这个区域里面就起作用-->
    <input name = "username" v-model="username">
    {{username}}
    <!--插值表达式-->
    <div v-if="count == 1">count = 1</div>
    <div v-else-if="count == 2">count = 2</div>
    <div v-else>count!=1&&count!=2</div>
    <div v-show="count == 3">count= 3</div>
    <hr>
    <div v-for="addr in addrs">
        {{addr}}<br>
    </div>
    <hr>
    <div v-for="(addr,i) in addrs">
        {{i+1}}--{{addr}}<br>
    </div>

15.3 Vue生命周期

  • 生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法(钩子)
状态阶段周期
beforeCreate创建前
created创建后
beforeMount载入前
mounted挂载完成(挂载完成,Vue初始化成功,HTML页面渲染成功)
beforeUpdate更新前
updated更新后
beforeDestory销毁前
destoryed销毁后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uJrIx2sA-1657094983220)(./image/Vue生命周期.png)]

16. Element

16.1 快速入门

  • 基于Vue的网站组件库,用于快速构建网页
  • 组件:组成网页的部件,例如超链接,按钮,图片,表格等
<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script><!--引入index.js-->
<link rel = "stylesheet" href="element-ui/lib/theme-chalk/index.css">

<script>
    new Vue({
       el:"#app"
    });
</script>

16.2 Element布局

  • Layout布局:通过基础的24分栏,迅速简便地创建布局
  • Container:用于布局的容器组件,方便快速搭建页面的基本结构

16.3 页面搭建案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>品牌管理后台</title>

    <style>
        .el-table .warning-row {
            background: oldlace;
        }

        .el-table .success-row {
            background: #f0f9eb;
        }
    </style>


</head>
<body>

<div id="app">
    <!--搜索框-->
    <el-form :inline="true" :model="brand" class="demo-form-inline">
        <el-form-item label="当前状态">
            <el-select v-model="brand.status" placeholder="当前状态">
                <el-option label="启用" value="1"></el-option>
                <el-option label="禁用" value="0"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item label="企业名称">
            <el-input v-model="brand.companyName" placeholder="企业名称"></el-input>
        </el-form-item>
        </el-form-item>
        <el-form-item label="品牌名称">
            <el-input v-model="brand.brandName" placeholder="品牌名称"></el-input>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
    </el-form>

    <!--新增与批量删除-->
    <el-row>
        <el-button type="danger" plain >批量删除</el-button>
        <el-button type="primary" plain @click="dialogVisible = true">新增</el-button>
    </el-row>

    <!--添加数据的对话框表单-->
    <el-dialog
            title="编辑品牌"
            :visible.sync="dialogVisible"
            width="40%">
        <el-form ref="form" :model="brand" label-width="80px">
            <el-form-item label="品牌名称">
                <el-input v-model="brand.brandNamename"></el-input>
            </el-form-item>
            <el-form-item label="企业名称">
                <el-input v-model="brand.companyName"></el-input>
            </el-form-item>
            <el-form-item label="排序">
                <el-input v-model="brand.ordered"></el-input>
            </el-form-item>
            <el-form-item label="备注">
                <el-input type="textarea" v-model="brand.description"></el-input>
            </el-form-item>
            <el-form-item label="状态">
                <el-switch v-model="brand.status"active-value="1" inactive-value="0" ></el-switch>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="addBrand()">立即创建</el-button>
                <el-button @click="dialogVisible = false">取消</el-button>
            </el-form-item>
        </el-form>
    </el-dialog>


    <!--表格-->
    <template>
        <el-table
                :data="tableData"
                style="width: 100%"
                :row-class-name="tableRowClassName"
                @selection-change="handleSelectionChange">
            <el-table-column
                    type="selection"
                    width="55">
            </el-table-column>
            <el-table-column
                    label="序号"
                    type="index"
                    width="50">
            </el-table-column>
            <el-table-column
                    prop="brandName"
                    label="品牌名称"
                    align="center">
            </el-table-column>
            <el-table-column
                    prop="companyName"
                    label="企业名称"
                    align="center">
            </el-table-column>
            <el-table-column
                    prop="ordered"
                    align="center"
                    label="排序">
            </el-table-column>
            <el-table-column
                    prop="status"
                    align="center"
                    label="当前状态">
            </el-table-column>
            <el-table-column
                    align="center"
                    label="操作">
                <el-row>
                    <el-button type="primary" round>修改</el-button>
                    <el-button type="danger"  round>删除</el-button>
                </el-row>
            </el-table-column>
        </el-table>
    </template>

    <div class="block">
        <span class="demonstration"></span>
        <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="currentPage"
                :page-sizes="[5, 10 ,15, 20, 100]"
                :page-size="100"
                layout="total, sizes, prev, pager, next, jumper"
                :total="400">
        </el-pagination>
    </div>


</div>



<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script><!--引入index.js-->
<link rel = "stylesheet" href="element-ui/lib/theme-chalk/index.css">

<script>
    new Vue({
       el:"#app",
        methods: {
            tableRowClassName({row, rowIndex}) {
                if (rowIndex === 1) {
                    return 'warning-row';
                } else if (rowIndex === 3) {
                    return 'success-row';
                }
                return '';
            },
            handleSelectionChange(val) {
                this.multipleSelection = val;
                console.log(this.multipleSelection)
            },
            onSubmit() {
                console.log(this.brand);
            },
            //添加数据
            addBrand() {
                console.log(this.brand);
            },
            handleSizeChange(val) {
                console.log(`每页 ${val} 条`);
            },
            handleCurrentChange(val) {
                console.log(`当前页: ${val}`);
            }
        },
        data() {
            return {
                tableData: [{
                    brandName: '花为',
                    companyName: '化为优先公司',
                    ordered: '100',
                    status:"1",
                }, {
                    brandName: '花为',
                    companyName: '化为优先公司',
                    ordered: '100',
                    status:"1",
                }, {
                    brandName: '花为',
                    companyName: '化为优先公司',
                    ordered: '100',
                    status:"1",
                }, {
                    brandName: '花为',
                    companyName: '化为优先公司',
                    ordered: '100',
                    status:"1",
                }],
                multipleSelection: [],
                brand: {
                    brandName: '',
                    companyName: '',
                    status:'',
                    id:'',
                    ordered:'',
                    description:''
                },
                dialogVisible : false,
                currentPage: 4
            }
        }
    });
</script>

</body>
</html>

},
data() {
return {
tableData: [{
brandName: ‘花为’,
companyName: ‘化为优先公司’,
ordered: ‘100’,
status:“1”,
}, {
brandName: ‘花为’,
companyName: ‘化为优先公司’,
ordered: ‘100’,
status:“1”,
}, {
brandName: ‘花为’,
companyName: ‘化为优先公司’,
ordered: ‘100’,
status:“1”,
}, {
brandName: ‘花为’,
companyName: ‘化为优先公司’,
ordered: ‘100’,
status:“1”,
}],
multipleSelection: [],
brand: {
brandName: ‘’,
companyName: ‘’,
status:‘’,
id:‘’,
ordered:‘’,
description:‘’
},
dialogVisible : false,
currentPage: 4
}
}
});

```
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,作为一名 Golang 后端工程师,以下是我推荐的学习路线: 1.了解基本概念和语法:首先,你需要了解 Golang 的基本概念和语法,包括变量、函数、数据类型、控制流、指针等等。可以参考官方文档或者一些入门教程。 2.深入学习 Golang 标准库:Golang 标准库是 Golang 的一个核心部分,包括了很多有用的库,比如 net、http、json、database/sql 等等。了解这些库的使用方法和原理对于开发者来说非常重要。可以通过阅读官方文档、书籍或者一些开源项目来学习。 3.学习常用框架:当你掌握了 Golang 基础知识和标准库之后,可以开始学习一些常用的框架,比如 Gin、Beego、Echo 等等。这些框架可以帮助你快速搭建 Web 应用程序。 4.学习数据库:Golang 支持多种数据库,包括 MySQL、PostgreSQL、MongoDB 等等。学习数据库的使用方法和原理对于后端工程师来说也非常重要。可以通过阅读官方文档或者一些开源项目来学习。 5.学习分布式系统:Golang 是一门非常适合构建分布式系统的语言,因此学习分布式系统是非常有必要的。可以学习一些常用的分布式系统框架,比如 etcd、Consul、Zookeeper 等等。 6.了解常用的工具和技术:作为一名后端工程师,你还需要了解一些常用的工具和技术,比如 Docker、Kubernetes、CI/CD 等等。这些工具和技术可以帮助你更好地管理和部署应用程序。 以上就是我推荐的 Golang 后端工程师学习路线,希望对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值