JavaWeb学习浅记
文章目录
前言
-
将JavaWeb学习的过程,所记录的笔记整理出来,稍微浅记,大概捋一个顺序(手指上指
看上面目录),具体的还需要一起去细看细学。
仅仅做参考,做个方向指引,回头也能当个搜索栏搜知识点,嘿。 -
JavaWeb主要就实现完整的一个网站,一个个完整的功能功能,能将其存储到数据库(JDBC,Mybatis),将其进行数据处理(Service),再借助Servlet进行连接到客户端,html/css/js(vue/element)等来显示渲染,用Ajax实现数据双向交互(MVVM),让网站更让人舒适。
零、JavaWeb
javaweb技术栈:
主要分为静态资源、动态资源、数据库、HTTP协议、Web服务器这五个部分。
一、MySQL基础
cmd 下mysql命令:
- show databases; // 查看数据库中文件
- create database 数据库名称 // 创建数据库
- drop database 数据库名称 // 删除数据库
- use 数据库名称 //使用数据库
- select database(); //查看当前使用的数据库
- show tables; //查询数据库下所有表的名称
- desc 表名称 //查询表结构
SQL语句分类:
- DDL:操作数据库、表等
- DML:对表中的数据进行增删改等
- DQL:对表中数据进行查询
- DCL:对数据库进行权限控制
二、JDBC
JDBC介绍
-
JDBC(Java DataBase Connectivity)是Java和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。
-
对各种不同类型的数据库都有相应的实现,本文中的代码都是针对MySQL数据库(关系型数据库)实现的。
运行的前置条件
需要进行初始化驱动,通过初始化驱动类com.mysql.jdbc.Driver,该类就在 mysql-connector-java-5.1.48.jar中。将其下载好后,在项目Module根目录下创建一个lib文件夹,将其放入,右键选中,将其加入Library。
JDBC 常用API
1、DriverManager
- 注册驱动
- 获取数据库连接
2、Connection
-
获取执行SQL的对象
- createStatement(普通执行SQL对象) ->Statement
- prepareStatement(预编译SQL的执行SQL对象,防止SQL注入) ->PreparedStatement
- PrepareCall(执行存储过程的对象)) ->CallableStatement
-
管理事务
3、Statement
- 执行SQL语句
- int executeUpdate(sql) : 执行DML、DDL语句 (返回值:DML语句影响行数,或者DDL语句执行后,执行成功也可能返回0)
- ResultSet executeQuery(sql) :执行DQL语句 (返回值:ResultSet结果集对象)
4、ResultSet
- 封装了DQL查询语句的结果
5、PreparedStatement
- 预编译SQL语句并执行:预防SQL注入问题
- SQL注入:SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法
练习所用代码
//注册驱动、连接数据库、获取执行sQL的对象、执行SQL语句的Test
@Test
public void JDBCTest() throws Exception {
String aname = "root";
double money = 100;
int id = 1;
//1.注册驱动
// Class.forName("com.mysql.jdbc.Driver");
//2.获取链接:如果连接的说本机mysql并且端口号是默认的3306 可以简写
String url = "jdbc:mysql://127.0.0.1:3306/maoyuan?userSSL=false";
// String url = "jdbc:mysql:///maoyuan?userSSL=false"; //userSSL=false参数,禁用安全连接方式,解决警告提示
String username = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql = "update account set money = 2000 where id = 1";
//4.获取执行SQL的对象Statement
Statement stmt = conn.createStatement();
//5.执行SQL
int count = stmt.executeUpdate(sql); //输出执行完DML语句后,受影响的行数
//6.处理结果
System.out.println(count);
if (count > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
//7.释放资源
stmt.close();
conn.close();
}
// 事务管理test
@Test
public void JDBCTest2() throws Exception {
//2.获取链接:如果连接的说本机mysql并且端口号是默认的3306 可以简写
String url = "jdbc:mysql:///maoyuan?userSSL=false"; //userSSL=false参数,禁用安全连接方式,解决警告提示
String username = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql1 = "update account set money = 2000 where id = 1";
String sql2 = "Insert into account values(4,3000,\"catalpa\")";
//4.获取执行SQL的对象Statement
Statement stmt = conn.createStatement();
try {
// 开启事务
conn.setAutoCommit(false);
//5.执行SQL
int count = stmt.executeUpdate(sql1); //输出执行完DML语句后,受影响的行数
int count2 = stmt.executeUpdate(sql2); //输出执行完DML语句后,受影响的行数
//6.处理结果
System.out.println(count);
if (count > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
System.out.println(count);
if (count2 > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
//提交事务
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace();
} finally {
//7.释放资源
stmt.close();
conn.close();
}
}
//封装了DQL查询语句的ResultSet
@Test
public void JDBCTest3() throws Exception {
//2.获取链接:如果连接的说本机mysql并且端口号是默认的3306 可以简写
String url = "jdbc:mysql:///maoyuan?userSSL=false"; //userSSL=false参数,禁用安全连接方式,解决警告提示
String username = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义sql
String sql1 = "select * from account";
//4.获取执行SQL的对象Statement
Statement stmt = conn.createStatement();
//5.执行SQL
ResultSet rs = stmt.executeQuery(sql1); //调用Statement对象的executeQuery方法,获取查询后的内容,保存为ResultSet类型
//6.处理结果
List<Account> arr = new ArrayList<>();
while (rs.next()) {
Account account = new Account();
account.setId(rs.getInt(1));
account.setMoney(rs.getDouble(2));
account.setAname(rs.getString(3));
arr.add(account);
}
Iterator iterator = arr.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//7.释放资源
rs.close();
stmt.close();
conn.close();
}
//PreparedStateMent 防SQL注入问题、预编译功能
@Test
public void JDBCTest4() throws Exception {
//2.获取链接:如果连接的说本机mysql并且端口号是默认的3306 可以简写
String url = "jdbc:mysql:///maoyuan?userSSL=false&useServerPrepStmts=true"; //userSSL=false参数,禁用安全连接方式,解决警告提示 useServerPrepStmts=true参数,用于开启PreparedStatement的预编译功能
String username = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, username, password);
//定义sql
String sql1 = "select * from account where money < ? and money > ?";
//1.获取PreparedStatement对象
PreparedStatement pstmt = conn.prepareStatement(sql1);
//2.设置?的值
pstmt.setDouble(1,2000); //第一个参数是?的位置,第二个参数是?的值
pstmt.setDouble(2,200);
//3.执行sql
ResultSet rs = pstmt.executeQuery();
//处理结果
List<Account> arr = new ArrayList<>();
while (rs.next()) {
Account account = new Account();
account.setId(rs.getInt(1));
account.setMoney(rs.getDouble(2));
account.setAname(rs.getString(3));
arr.add(account);
}
Iterator iterator = arr.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//7.释放资源
rs.close();
pstmt.close();
conn.close();
}
配置数据库连接池
创建druid.properties配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///maoyuan?useSSL=false&useServerPrepStmts=true
username=root
password=2019118121
# 连接池大小
initialSize=5
# 最大数量
maxActive=10
# 最长等待时间
maxWait=3000
利用数据库连接池实例
public static void main(String[] args) throws Exception {
// 接收页面提交的参数
String brandName = "格力";
String companyName = "格力公司";
int ordered = 1;
String description = "中国制造,格力造";
int status = 1;
//1. 获取Connection
// 3. 加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("jdbcdemo/src/com/gl/druid.properties"));
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5. 获取数据库连接Connection
Connection conn = dataSource.getConnection();
//2. 定义SQL
String sql = "insert into brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);";
//3. 获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//4. 设置参数
pstmt.setString(1, brandName);
pstmt.setString(2, companyName);
pstmt.setInt(3, ordered);
pstmt.setString(4, description);
pstmt.setInt(5, status);
//5. 执行SQL
int count = pstmt.executeUpdate();
// 影响的行数
// 6. 处理结果
System.out.println(count > 0);
// 7. 释放资源
pstmt.close();
conn.close();
}
三、Maven
Maven的作用
- 标准化的项目结构
- 标准化的构建流程
- 方便的依赖管理
Maven模型
- 项目对象模型(Project Object Model)
- 依赖管理模型(Dependency)
- 插件(Plugin)
Maven坐标
- 什么是坐标?
- Maven中的坐标是资源的唯一标识
- 使用坐标来定义项目或引入项目中需要的依赖
- Maven坐标主要组成
- groupId:定义当前Maven项目隶属组织名称
- artifactId:定义当前Maven项目名称
- version:定义当前项目版本号
jar依赖包如何导入
统一配置jdk版本号
在maven安装目录中的conf/setting.xml中设置,统一各个地方的jdk版本
常用配置,pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<!-- 项目名字,记得修改 -->
<artifactId>project-Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- 编译jdk版本 -->
<properties>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
</properties>
<!-- 依赖 -->
<dependencies>
<!-- 工具包,便捷I/O的操作 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- servlet依赖坐标 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<!-- 添加slf4j日志api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!-- 添加logback-classic依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 添加logback-core依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<!-- 设置端口号,设置path(项目访问路径) -->
<configuration>
<port>8080</port>
<path>/catalpa</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
四、MyBatis
核心配置文件的顶层结构如下:
Mybatis-config.xml
<?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.catalpa.pojo"/>
</typeAliases>
<!--
environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///maoyuan?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///maoyuan?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载sql映射文件-->
<!-- <mapper resource="com/catalpa/mapper/UserMapper.xml"/>-->
<!--Mapper代理方式 使用包扫描的方式简化映射文件的加载-->
<package name="com.catalpa.mapper"/>
</mappers>
</configuration>
BrandMapper.xml
实现SQL语句
<?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.catalpa.mapper.BrandMapper">
<!--
数据库表的字段名称 和 实体类的属性名称不一样,则不能自动封装数据
*起别名:对不一样的列名起别名,让别名和实体类的属性名一样
缺点:每次查询都要定义一次别名
*resultMap:
1.定义<resultMap>标签
2.在<select>标签中,使用resultMap属性替换resultType属性
-->
<!--
以下使用resultMap进行映射,来实现别名的方式来使得成功映射到实体类属性
id: 唯一表示
type:映射的类型,支持别名(写pojo实体类类型)
-->
<!--
1.查询所有
-->
<resultMap id="brandResultMap" type="brand">
<!-- id:完成主键字段的映射
column:表的列名
property:实体类的属性名
result:完成一般字段的映射
column:表的列名
property:实体类的属性名
-->
<result column="brand_name" property="brandName"/>
<result column="company_name" property="companyName"/>
</resultMap>
<select id="selectAll" resultMap="brandResultMap">
select *
from tb_brand;
</select>
<!-- 以下使用在sql语句上取别名的方式来使得成功映射到实体类属性,可以直接写或用sql片段将其封装出来,便于重写,但仍然不够灵活 -->
<!--
sql片段
-->
<!-- <sql id="brand_column">-->
<!-- id, brand_name as brandName, company_name as companyName, ordered, description, status-->
<!-- </sql>-->
<!-- <select id="selectAll" resultType="brand">-->
<!-- select-->
<!-- <include refid="brand_column"></include>-->
<!-- from tb_brand;-->
<!-- </select>-->
<!-- 以下该方法必须保证列名和实体类的属性名保持一致,否则不能自动封装数据 -->
<!-- <select id="selectAll" resultType="brand">-->
<!-- select *-->
<!-- from tb_brand;-->
<!-- </select>-->
<!--
2.查询详情
-->
<!--
* 参数占位符
1.#{}:会将其替换成?,为了f防止SQL注入
2.${}:拼接sQL。 会存在sQL注入问题
3.使用时机:
*参数传递的时候:#{}
*表名或列名不固定的情况下:${}, 还是会存在SQL注入问题
*参数类型:parameterType参数,声明传入参数的类型,可以省略,一般不写
*特殊字符处理:
1.转移字符: < ( < )
2.CDATA区:
-->
<!-- <select id="selectById" parameterType="int" resultMap="brandResultMap">-->
<!-- select *-->
<!-- from tb_brand-->
<!-- where id = #{id};-->
<!-- </select>-->
<!-- <select id="selectById" parameterType="int" resultMap="brandResultMap">-->
<!-- select *-->
<!-- from tb_brand-->
<!-- where id < #{id};-->
<!-- </select>-->
<select id="selectById" parameterType="int" resultMap="brandResultMap">
select *
from tb_brand
where id
<![CDATA[
<
]]>
#{id};
</select>
<!--
3.条件查询
-->
<!-- <select id="selectByCondition" resultMap="brandResultMap">-->
<!-- select *-->
<!-- from tb_brand-->
<!-- where status = #{status}-->
<!-- and company_name like #{companyName}-->
<!-- and brand_name like #{brandName};-->
<!-- </select>-->
<!--
4.动态条件查询
*if: 条件判断
*test:逻辑表达式
*出现字符串拼接逻辑错误问题(如第一个条件不需要逻辑运算符and),解决方法:
*用恒等式解决 (从而保证每一个分支的格式都是一样的)
*<where>替换where关键字
-->
<select id="selectByCondition" resultMap="brandResultMap">
select *
from tb_brand
<where>
<if test="status != null">
and status = #{status}
</if>
<if test="companyName != null and companyName !='' ">
and company_name like #{companyName}
</if>
<if test="brandName != null and brandName !='' ">
and brand_name like #{brandName};
</if>
</where>
</select>
<!--
5.单条件查询(动态)
-->
<!-- <select id="selectByCondition" resultMap="brandResultMap">-->
<!-- select *-->
<!-- from tb_brand-->
<!-- where 1 = 1-->
<!-- <if test="status != null">-->
<!-- and status = #{status}-->
<!-- </if>-->
<!-- <if test="companyName != null and companyName !='' ">-->
<!-- and company_name like #{companyName}-->
<!-- </if>-->
<!-- <if test="brandName != null and brandName !='' ">-->
<!-- and brand_name like #{brandName};-->
<!-- </if>-->
<!-- </select>-->
<select id="selectByConditionSingle" resultMap="brandResultMap">
select *
from tb_brand
where
<choose><!--相当于switch-->
<when test="status!=null"><!-- 相当于case-->
status = #{status}
</when>
<when test="compangName!=null and companyName ! = '' "><!-- 相当于case-->
company_name like #{companyName}
</when>
<when test="brandName!=null and brandName != '' "><!-- 相当于case-->
brand_Name like #{brandName}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</select>
<!-- <select id="selectByConditionSingle" resultMap="brandResultMap">-->
<!-- select *-->
<!-- from tb_brand-->
<!-- <where>-->
<!-- <choose><!–相当于switch–>-->
<!-- <when test="status!=null"><!– 相当于case–>-->
<!-- status = #{status}-->
<!-- </when>-->
<!-- <when test="compangName!=null and companyName ! = '' "><!– 相当于case–>-->
<!-- company_name like #{companyName}-->
<!-- </when>-->
<!-- <when test="brandName!=null and brandName != '' "><!– 相当于case–>-->
<!-- brand_Name like #{brandName}-->
<!-- </when>-->
<!-- </choose>-->
<!-- </where>-->
<!-- </select>-->
<!--
6.添加
-->
<!-- <insert id="add">-->
<!-- insert into tb_brand (brand_name, company_name, ordered, description, status)-->
<!-- values (#{brandName},#{companyName},#{ordered},#{description},#{status});-->
<!-- </insert>-->
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into tb_brand (brand_name, company_name, ordered, description, status)
values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
<!--
7.修改
-->
<!-- 修改所有字段 -->
<!-- <update id="update">-->
<!-- update tb_brand-->
<!-- set-->
<!-- brand_name = #{brandName},-->
<!-- company_name = #{companyName},-->
<!-- ordered = #{ordered},-->
<!-- description = #{description},-->
<!-- status = #{status}-->
<!-- where-->
<!-- id = #{id};-->
<!-- </update>-->
<!-- -->
<!-- 修改动态字段-->
<update id="update">
update tb_brand
<set>
<if test="brandName != null and brandName != '' ">
brand_name = #{brandName},
</if>
<if test="companyName != null and companyName != '' ">
company_name = #{companyName},
</if>
<if test="ordered != null and ordered != '' ">
ordered = #{ordered},
</if>
<if test="description != null and description != '' ">
description = #{description},
</if>
<if test="status != null and status != '' ">
status = #{status},
</if>
</set>
where id = #{id};
</update>
<!--
8.删除
-->
<!-- 删除一个 -->
<delete id="deleteById">
delete
from tb_brand
where id = #{id};
</delete>
<!-- 批量删除 -->
<!--
<foreach> 是mybatis提供的一个实现循环输出的功能的标签, collection参数指传入的数组参数,separator参数指各个元素之间的分隔符,
open参数用于在开始之前拼接字符,close用于在结束后拼接字符,
-->
<!--
mybatis会将数组参数,封装成一个map集合
* 默认:array = 数组 (等价于 Key = value)
* 可以使用@Param注解来改变map集合的默认key的名称(在BrandMapper接口中的抽象方法中加注解)
-->
<delete id="deleteByIds">
delete
from tb_brand
where id
in
<foreach collection="ids" item="id" separator="," open="(" close=");">
#{id}
</foreach>
</delete>
</mapper>
BrandMapper.java
与BrandMapper.xml同名称目录下的接口文件
package com.catalpa.mapper;
import com.catalpa.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* @Author CatalpaHao
* @Date 2022/8/1 11:11
* @PackageName: com.catalpa.mapper
* @ClassName: BrandMapper
* @Version 1.0
*/
public interface BrandMapper {
/**
* 查询所有
*/
List<Brand> selectAll();
/**
* 查看详情:根据Id查询
*/
Brand selectById(int id);
/**
* 条件查询
* *参数接收
* 1.散装参数:如果方法中有多个参数,需要使用注解@Param(“SQL参数占位符名称”)
* 2.对象参数:对象的属性名称要和参数占位符名称一致
* 3.map集合参数
*
*/
List<Brand> selectByCondition(@Param("status") int status,@Param("companyName") String companyName,@Param("brandName") String brandName);
List<Brand> selectByCondition(Brand brand);
List<Brand> selectByCondition(Map map);
/**
* 单条件动态查询
*
* @param brand
* @return
*/
List<Brand> selectByConditionSingle(Brand brand);
/**
* 添加
*/
void add(Brand brand);
/**
* 修改
*/
int update(Brand brand);
/**
* 根据Id删除
*/
void deleteById(int id);
/**
* 批量删除(多个id)
*/
void deleteByIds(@Param("ids") int[] ids);
}
实例调用mapper接口方法
public static void main(String[] args) throws IOException {
//1.加载核心配置文件,获取SqlSessionFactory 对象
String resource = "mybatis-config.xml"; //配置文件的路径
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.执行sql
// List<User> users = sqlSession.selectList("test.selectAll");
//3.1 获取UserMapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//3.2 调用sql方法
List<User> users = userMapper.selectAll();
System.out.println(users);
//4.释放资源
sqlSession.close();
}
Mybatis实操散记
学习使用过程中所需要的细节点,截图散记
五、HTTP
介绍
HyperText Transfer Protocol ,超文本传输协议,规定了游览器和服务器之间数据传输的规则
HTTP协议特点
- 基于TCP协议:面向连接,安全性高
- 基于请求-响应模型的:一次请求对应一次响应
- HTTP协议是无状态的协议:对于事务处理没有记忆功能。每次请求-响应都是独立的
- 缺点:多次请求间不能共享数据,Java中使用会话技术,从而来解决该问题。
- 优点:速度快。
HTTP请求数据格式
请求方式有七种多,主要重点掌握 GET请求方式和POST请求方式
请求数据分为三部分: 请求行,请求头,请求体(GET方法不存在请求体)。
HTTP响应数据格式
响应数据格式分为三部分: 响应行,响应头,响应体。
状态码的详情地址为:https://cloud.tencent.com/developer/chapter/13553
常用的状态码为:
- 200 :(OK)客户端请求成功,即处理成功,这是我们最想看到的状态码
- 400 : (Bad Request)客户端请求有语法错误,不能被服务器所理解
- 403 :(Forbidden)服务器收到请求,但是拒接提供服务,比如:没有权限访问相关资源
- 404 :(Not Found)请求资源不存在,一般是URL输入有误,或者网站资源已经被删除了
- 405 :(Method Not Allowed)请求方式有误,比如应该用GET请求方式的资源,用了POST
- 500 :(Internal Server Error)服务器发生不可预期的错误。 如服务器出异常了
- 503 :(Service Unavailable)服务器尚未准备好处理请求,如服务器刚刚启动,还未初始化好
- 511 :(Network Authentication Required)客户端需要进行身份验证才能获得网络访问权限
六、Servlet
Servlet介绍
Servlet执行流程
Servlet生命周期
Servlet方法介绍
Servlet体系结构
- HttpServlet较之于Servlet提高了代码的重用性,封装了“判断调用方式”的过程
Servlet urlPattern配置
XML配置方法编写Servlet
七、Request&Response
- Request:获取请求数据
- Response:设置响应数据
(一)Request
Request的继承体系
- ServletRequest 是java提供的请求对象根接口
- HttpServletRequest 是java提供的对Http协议封装的请求对像接口
- RequestFacade 是Tomcat定义的实现类
Request获取请求数据
Request通用方式获取请求参数
GET方式:String getQueryString()
POST方式: BufferedReader getReader()
提供了三个通用方式来获取请求参数
Request请求参数中文乱码-POST/GET解决方案
- 一个只能POST 一个为通用(GET/POST都能用)
Request转发
(一种资源跳转方式)
在服务器内部,同一个服务器中,将两个资源(两个文件)之间进行传递数据、共享数据,
数据封装在Request对象中进行。
(二)Response
Response设置响应数据的功能介绍
资源路径问题
什么时候需要加虚拟目录(项目访问路径),什么时候不需要加
Response响应字符数据
Response响应字节数据(如视频文件)
Response重定向
(一种资源跳转方式)
与Request转发的特点截然相反,response是可以在不同服务器之间进行重定向跳转的,地址栏的路径也会发生改变,发生的是两次请求,不能使用request进行共享数据
八、JSP(目前基本淘汰不用了)
JSP介绍
JSP快速入门,基本使用
JSP原理
JSP脚本,如何定义java代码到JSP页面
JSP缺点
EL表达式 (获取数据,简化java代码)
JSTL快速入门(JSTL是一个标签库,方便java的代码嵌入)
JSTL标签(此处只有其中的forEach的使用)
九、会话技术
会话跟踪技术介绍
-
Cookie:保存在客户端(游览器)中
-
Session:保存在服务器中
主要用于一次会话内多次请求之间的数据共享
Cookie基本使用
Cookie原理
Cookie使用细节
Cookie本身不可传中文,需要编码处理后才可传中文
Session基本使用
Session可以传递中文,可以传递任何对象,参数类型是Object
Session使用原理
基于Cookie
Session使用细节
Cookie 和 Session的区别,注意区分什么时候使用合适
十、Filter&Listener
(一)Filter
filter介绍
filter 快速入门
filter执行流程
filter拦截路径配置
分为四种:
- 拦截具体的资源 /index.jsp
- 目录拦截 /user/*
- 后缀名拦截 *.jsp
- 拦截所有 /*
filter过滤器链
注解配置的Filter,优秀奖按照过滤器类名(字符串)的自然排序(目录里的排序,一般是按类名升序)
filter案例,做一个登录身份验证
(二)Listener
概述
- Listener 表示监听器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
- 监听器可以监听就是在 application , session , request 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。(request 和 session 我们学习过。而 application 是 ServletContext 类型的对象。)
- ServletContext 代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。
分类
十一、AJAX & Axios
AJAX概述以及作用
同步异步图解
小案例—实现最简单的AJAX请求与响应
Axios概述
Axios快速入门
Axios请求方式别名
十二 、JSON
JSON概述
JSON基本语法
JSON数据和Java对象转换(包括实现的方法)
案例细节
- 将json从前端传回后端Servlet、后端接收json数据
- 将json从后端封装后发送到前端,前端html接收json
十三、MVC模式
- M 模型层
- V 视图层
- C 控制层
MVC 模式中三个组件的详细介绍如下:
模型(Model):用于封装与应用程序业务逻辑相关的数据以及对数据的处理方法。Model 有对数据直接访问的权力,例如对数据库的访问。Model 不依赖 View 和 Controller,也就是说, Model 不关心它会被如何显示或是如何被操作。但是 Model 中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此 Model 的 View 必须事先在此 Model 上注册,由此,View 可以了解在数据 Model 上发生的改变。(如,软件设计模式中的“观察者模式”);
视图(View):能够实现数据有目的的显示(理论上,这不是必需的)。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(即 Model),因此应该事先在被它监视的数据那里注册;
控制器(Controller):起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。
十四、三层架构
-
数据访问层(DAL) :对数据库的CRUD基本操作。(service)
-
业务逻辑层(BLL) :对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能(dao/mapper)
-
表现层(UI):接收请求,封装数据,调用业务逻辑层,响应数据。(web/controller)
三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构, 各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。
MVC和三层架构两者联系
十五 、前端额外—Vue&Element
(一)Vue
Vue介绍
Vue快速入门
Vue采用指令
Vue生命周期
(二)Element
Element介绍
Element快速入门
Element布局
总结
-
以上的内容是在做黑马的课程中学习Javaweb的记录,为方便自己后续使用方便,作为Javaweb的知识点索引用,包含的内容不深入,也存在查漏。总体来说,希望能有所帮助吧,对myself对everybody。
-
时间不足,笔记有所差缺,很赶很急,没有细细写了,后续会对每个模块再进一步学习的。冲~
就这样,老规矩,不秃头 日志,以上为个人笔记,也作为经验分享,大家可以参考使用,有问题也可以提出。