JavaWeb

本文最后更新于:6 个月前

JavaWeb (for next part)

JavaWeb

用Java技术来解决相关web互联网领域的技术栈

MySQL

关系型数据库/非关系型数据库

关系型数据库是建立在关系模型基础上的数据库

简单说,关系型数据库是由多张能互相连接的二维表组成的数据库

安装mysql

管理员cmd

mysql -uxxx -pxxx

SQL语法—mysql不区分大小写

show databases;

--注释 /# 注释

/* 注释 */

SQL语法–操作数据库

1、查询
show databases;

2、创建
创建数据库
create database 数据库名称;
create database if not exists 数据库名称;

3、删除
drop database 数据库名称;

4、使用数据库
查看当前使用的数据库
select database();

使用数据库
use 数据库名称;

SQL语法–操作表

1、查询表
查询当前数据库下所有表的名称
show tables;

查询表结构
desc 表名称;

2、创建表
create table 表名(
    字段名 数据类型
    ...
);

3、删除表
drop table 表名;
drop table if exists 表名;

4、修改表
(1)修改表名
alter table 表名 rename to 新的表名;

(2)添加一列
alter table 表名 add 列名 数据类型;

(3)修改数据类型
alter table 表名 modify 列名 新数据类型;

(4)修改列名和数据类型
alter table 表名 change 列名 新列名 新数据类型;

(5)删除列
alter table 表名 drop 列名;

SQL语法–操作数据

1、添加数据
给指定的列添加数据
insert into 表名(列名1,列名2,...) values(值1,值2,...);

给全部的列添加数据/给表添加一条数据
insert into 表名 values(值1,值2,...);

批量添加数据
insert into 表名(列名1,列名2,...) values (值1,值2,...),(值1,值2,...),...;

insert into 表名 values (值1,值2,...),(值1,值2,...),...;


2、修改数据
update 表名 set 列名1=值1,列名2=值2,...[where条件];

3、删除数据
delete from 表名 [where条件];

SQL语法–查询数据

基础查询

1、查询多个字段
select * from 表名;

2、去除重复记录
select distinct 字段列表 from 表名;

3、起别名
as:

条件查询

select 字段列表 from 表名 where 条件列表;

排序查询

select 字段列表 from 表名 order by 排序字段名1[排序方式1],排序字段名2[排序方式2],...;

分组查询

聚合函数
select 聚合函数名(列名) from 表;

select 字段列表 from 表名 [where 分组前条件限定] group by 分组字段名 [having 分组后条件过滤];

分页查询

select 字段列表 from 表名 limit 起始索引, 查询条目数;

where和having的区别

执行时间不一样:where是分组之前进行限定,不满足where条件,则不参与分组,而having是分组之后对结果进行过滤

可判断的条件不一样:where不能对聚合函数进行判断,having可以

SQL语法–约束

SQL语法–数据库设计

SQL语法–多表查询

SQL语法–事务

JDBC

JDBC就是使用Java语言操作关系型数据库的一套API

java数据库连接

JDBC本质

官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口

各个数据库厂商去实现这套接口,提供数据库驱动jar包

可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类

JDBC好处

各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发

可随时替换底层数据库,访问数据库的Java代码基本不变

JDBC 使用步骤

mysql-connector-java-5.1.48.jar    

1.导入相应jar包
2.将jar包添加到库

3.
public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1.注册驱动  抛出异常
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接j
        String url="jdbc:mysql://127.0.0.1:3306/forjavaweb?useSSL=false";
        String username="***";
        String password="***";
        Connection conn = DriverManager.getConnection(url,username,password);

        //3.定义sql语句
        String sql="update javasum set sum=999 where 1=1";

        //4.获取执行sql的对象 Statement
        Statement st = conn.createStatement();

        //5.执行sql
        int i = st.executeUpdate(sql); //受影响的行数

        //6.处理结果
        System.out.println("影响的行数:"+i);

        //7.释放资源
        st.close();
        conn.close();
    }
}

JDBC API – DriverManger

1.注册驱动

2.获取数据库连接

注册驱动

可省略注册驱动的步骤

//Class.forName("com.mysql.jdbc.Driver");

-----------------

获取数据库连接

static Connection 

getConnection(String url, String user, String password)

url:连接路径
jdbc:mysql//127.0.0.1/3306/数据库名称?参数键值...
useSSL=false

本机连接可简写
jdbc:mysql://127.0.0.1:3306/forjavaweb?useSSL=false

jdbc:mysql:///forjavaweb?useSSL=false

JDBC API – Connection

1.获取执行sql的对象

2.管理事务

获取执行sql的对象

Statement createStatement()

预编译sql的执行sql对象:防止sql注入

PreparedStatement prepareStatement(sql)

-------------

事务管理

开启事务
setAutoCommit(boolean autoCommit):true为自动提交事务; false为手动提交事务,即为开启事务

提交事务
commit()

回滚事务
rollback()    

JDBC API – Statement

执行sql语句

int executeUpdate(sql) 执行增删改语句
返回值为影响的行数

ResultSet executeQuery(sql) 执行查询语句
返回值为 ResultSet 结果集对象

JDBC API – ResultSet

结果集对象

封装了数据查询语句的结果

获取查询结果

ResultSet stmt.executeQuery(sql)
执行sql语句,返回ResultSet对象

获取查询结果

boolean next()
1.将光标从当前位置向前移动一行
2.判断当前行是否为有效行
返回值:
true 有效行 当前行有数据
false 无效行 当前行没有数据    

xxx getXxx(参数) 获取数据
xxx 数据类型 如:int getInt(参数)

使用步骤

//循环判断游标是否是最后一行末尾
while(rs.next()){
    //获取数据
    rs.getXxx(参数);
}

int 列的编号 
String 列的名称

输出:

while(rs.next())
    {
        int i = rs.getInt(1);
        int i2 = rs.getInt(2);

        System.out.println(i);
        System.out.println(i2);
    }
封装

数据类

public class javasum {
    private int id;
    private int sum;
}

// Alt + Insert --->     Getter和Setter

--- getId()、setId()、getSum()、setSum()

// Alt + Insert --->     toString()

public String toString() {}

使用

//创建集合
List<javasum> list = new ArrayList<>();

//处理结果
while(rs.next())
{
     javasum test = new javasum();

     int id = rs.getInt("id");
     int sum = rs.getInt("sum");

     test.setId(id);
     test.setSum(sum);

     list.add(test);
 }

 System.out.println(list);

JDBC API – PreparedStatement

预编译sql语句并执行

预防sql注入

使用

1、获取PreparedStatement对象

//sql语句中的参数值用 ? 占位符替代
String sql="select * from users where id = ? and password = ?;";
PreparedStatement pstmt = conn.PreparedStatement(sql);

2、设置参数值

setXxx(参数1,参数2) 给 ? 赋值
参数1:? 的位置
参数2:? 的值

3、执行sql

executeUpdate()/executeQuery()
    

    //3.定义sql语句
     String sql="select sum from javasum where id =?";

    //4.获取执行sql的对象 Statement
     PreparedStatement ptmt=conn.prepareStatement(sql);

    ptmt.setInt(1,1);
    //5.执行sql
    ResultSet rs = ptmt.executeQuery();

    //6.处理结果
    while(rs.next())
    {
        int sum = rs.getInt(1);
        System.out.println(sum);
    }

数据库连接池

标准接口 : DataSource

getConnection

Druid

配置文件

//加载配置文件
    Properties prop = new Properties();
    prop.load(new FileInputStream(""));

    //获取连接池对象
    DataSource datasource = DruidDataSourceFactory.createDataSource(prop);

    //获取连接池对象
    Connection conn = datasource.getConnection();

Maven

简介

Maven是专门用于管理和构建Java项目的工具

提供了一套标准的项目结构

提供了一套标准化的构造流程(编译,测试,打包,发布……)

Maven提供了一套简单的命令来完成项目构建

提供了一套依赖管理机制

依赖管理其实就是管理项目所依赖的第三方资源(jar包、插件…)

手动导入—>坐标管理配置

仓库

本地仓库—中央仓库—远程仓库(私服)

安装配置

  • 安装包
  • 配置环境变量
  • 配置本地仓库
  • 修改conf/settings.xml中的为一个指定目录
  • 配置阿里云私服

基本使用

IDEA 配置 Maven

Setting—Maven

IDEA 创建 Maven项目

构建系统–Maven

IDEA 导入 Maven项目

导入其pml文件

依赖范围

通过设置坐标的依赖范围(scope),可以设置对应jar包的作用范围:

编译环境、测试环境、运行环境

Maven 坐标

Maven中的坐标是资源的唯一标识

使用坐标来定义项目或引入项目中需要的依赖

Maven 坐标 组成

  • groupld:定义当前Maven项目隶属组织名称

  • artifactld:定义当前Maven项目名称

  • version:定义当前项目版本号

    mysql mysql-connector-java 5.1.46

Alt–Insert–dependencies–搜索

MyBatis

MyBatis是一款优秀的持久层框架,用于简化JDBC开发

持久层

负责将数据到保存到数据库的那一层代码

JavaEE三层架构:表现层、业务层、持久层

框架

框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型

在框架的基础之上构建软件编写更加高效、规范、通用、可扩展

JDBC 缺点

1、硬编码

注册驱动,获取连接

SQL语句

2、操作繁琐

手动设置参数

手动封装结果集

MyBatis 简化

1、硬编码—>配置文件

2、操作繁琐—>自动完成

MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作

MyBatis 基础步骤

MyBatis 快速入门
https://mybatis.org/mybatis-3/zh/getting-started.html

创建模块,导入坐标

编写配置文件

编写SQL映射文件

编码

1、定义pojo类
2、加载核心配置文件,获取SqlSessionFactory 对象
3、获取SqISession对象,执行SQL语句
4、释放资源

IDEA 连接 mysql数据库

Mapper代理开发

目的:

解决原生方式中的硬编码

简化后期执行SQL

使用

1、定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
2、设置SQL映射文件的namespace属性为Mapper接口全限定名
3、在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
4、编码 ——-
通过SqIlSession的 getMapper方法获取 Mapper接口的代理对象调用对应方法完成sql的执行

//获取mapper的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.selectAll();

sqlSession.close() 

创建目录—–com.opn—>com/opn

如果Mapper接口名称和sql映射文件名称相同,并在同一目录下,可以用包扫描的方式简化sql映射文件的加载

<mappers>

    //<mapper resource="com/opn/mapper/UserMapper.xml"/>

    <package name="com.opn">

</mappers>

Mybatis核心配置文件

environments:
配置数据库连按环境信息。可以配置多个environment,通过defqult属性切换不同的environment

配置文件开发

注解开发

@Select()

@Insert()

@Update()

@Delete()


@Param

为SQL语句中参数赋值

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

    @Select("select * from tb_user where username = #{username}")
    User selectUsername(String username);

    @Insert("insert into tb_user values (null,#{username},#{password})")
    void add(@Param("username") String username, @Param("password") String password);
}

Tomcat

Apache Tomcat

开源免费轻量级的 web 服务器

tomcat.apache.org

Tomcat 基本使用

bin/startup.bat 启动

webapps 运行目录、部署项目

conf/server.xml    修改启动端口号
<Connector port="8080">


java包压缩成war包--在webapps目录下自动解压

在IDEA中创建 Maven Web项目

web项目结构

1、Maven Web项目结构:开发中的项目

2、部署的JavaWeb项目结构:开发完成、可部署的项目

WEB-INF — classes

编译后的java字节码文件和resources的资源文件

WEB-INF — lib

pom.xml中依赖坐标对应的jar包

3、打包 package

webapp中的内容,web项目打包

在target目录下生成打包文件

打包的方式

pom.xml

war

IDEA中创建Maven Web项目

  • 一、使用骨架

1、选择web项目骨架,创建项目

Maven - Create from archetype

maven-archetype-webapp

2、删除pom.xml中多余的坐标

3、补齐缺失的目录结构main下的java和resources

main-新建-目录-java,resources

  • 二、不使用骨架

1、选择Maven,创建项目

2、pom.xml中添加打包方式为war

3、补齐缺失的目录结构:webapp

项目结构-Facets-爆红-补webapp-+-web.xml-补齐xml目录src/mian/webapp/WEB-INF/web.xml

https://www.bilibili.com/video/BV1Qf4y1T7Hx?p=91

https://www.bilibili.com/video/BV1Qf4y1T7Hx?p=118

IDEA中使用Tomcat

将本地Tomcat集成到IDEA中,然后进行项目部署

使用Tomcat的 Maven 插件

<plugin>
    <groupld>org.apache.tomcat.maven</groupld>
    <artifactld>tomcat7-maven-plugin</artifactld>
    <version>2.2</version>
</plugin>

使用Maven Helper插件快速启动项目,选中项目,右键–> Run Maven –> tomcat7:run

Servlet 动态web资源

Servlet是Java提供的一门动态web资源开发技术

Servlet是JavaEE 规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet

快速入门

基础方法

  • init 初始化时调用
  • service 提供服务
  • destory 销毁时调用
  • getServletConfig 获取ServletConfig对象
  • getServletinfo 获取Servlet信息

体系结构

HttpServlet

区分请求方式

对servlet方法进行封装

doGet — doPost

使用

声明类,继承HttpServlet

复写doGet和doPost方法

urlPattern 配置

路径

一个servlet可配置多个urlPattern

  • 匹配规则
  • 精确匹配
  • 目录匹配
  • 扩展名匹配
  • 任意匹配

XML配置Servlet

Request&Response

请求&响应

doGet

//使用request对象, 获取请求数据
String name = request.getParameter("name")
//————>url?name=xxx

//使用response对象, 设置响应数据
response.setHeader("","");
response.getWriter.write("<h1>"+name+"</h1>")

效果

get请求?name=xxx
返回界面 xxx

Get/Post 获取数据

get获取字符串  
.toString()


post获取字符流  
Buffer  
toLine  

Request通用方式获取请求参数

Map集合  
<String(参数),String[](值)>

getParameterMap()
获取所有参数 Map集合

getParameterValues()  
根据名称获取参数值(数组)

getParameter()  
根据名称获取参数值(单个值)

POST中文乱码

request.setCharacterEncoding("UTF-8");

GET中文乱码

//tomcat7为ISO形成乱码,tomcat8+不存在
username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);

请求转发

在服务器内部 资源跳转的方式

req.getRequestDispatcher("资源B路径").forward(req,resp);

请求转发资源间共享数据:使用Request对象

setAttribute(String name,Object o)
存储数据到Request域中

getAttribute(String name)
根据key,获取值

removeAttribute(String name)
根据key,删除该键值对

特点

  • 地址栏不发生变化
  • 仅服务器内部资源
  • 发生一次请求

Response完成重定向

资源跳转方式

resp.setStatus(302);
resp.setHeader("location","资源路径B");

//简化
resp.sendRedirect("资源路径");

特点

  • url变化
  • 可重定向到任意位置资源
  • 两次请求

Response响应字符数据

PrintWriter对象/字符输出流

//设置响应数据格式
response.setContentType("text/html;charset=utf-8");

//获取流
PrintWriter write = resp.getWriter();

//头信息
response.setHeader("content-type","text/html");

//响应数据
write.write("aaa");

流不需要关闭,随response对象自动销毁

Response响应字节数据

图片/数据/音频

//1.读取文件
FileInputStream fis = new FileInputStream("文件路径");

//2.获取response字节输出流
ServletOutStream os = response.getOutputStream();

//3.完成流的copy
byte[] buff = new byte[1024];
int len = 0;
while((len=fis.read(buff))!=-1)
{
    os.write(buff,0,len)
}

//3.流的对拷    commons-io 2.6 工具类
IOUtils.copy(fis,os);

fis.close();

登录示例

流程:
1.前端界面
2.LoginServlet
3.UserMapper接口
4.Mysql数据库

准备工作:
1.静态界面
2.Mysql tb_user表
3.创建User实体类 — com.opn.pojo 下的user实体类
3.导入MyBatis坐标 — resources 下的 mybatis-config.xml
4.UserMapper.xml 映射文件 — resources com.opn.mapper 下UserMapper.xml
5.UserMapper接口

目录结构

UserMapper接口

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

    @Select("select * from tb_user where username = #{username}")
    User selectUsername(String username);

    @Insert("insert into tb_user values (null,#{username},#{password})")
    void add(@Param("username") String username, @Param("password") String password);
}


loginServlet - Servlet

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("loginServlet...");
        //接受用户名-密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //调用Mybatis完成查询
        //获取SqlSessionFactory对象
        String resource="mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //获取SqlSession对象
        SqlSession sqlSession= sqlSessionFactory.openSession();

        //获取Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        //调用方法
        User user = userMapper.select(username,password);

        sqlSession.close();

        //设置响应数据格式
        response.setContentType("text/html;charset=utf-8");
        //获取流
        PrintWriter write = response.getWriter();
        //头信息
        response.setHeader("content-type","text/html");

        //判断user是否为null
        if (user!=null)write.write("登录成功");
            else write.write("登录失败");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws     ServletException, IOException {
        this.doGet(request,response);
    }
}

注册示例

RegisterServlet

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //接受用户名-密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //调用Mybatis完成查询
        //获取SqlSessionFactory对象
        String resource="mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //获取SqlSession对象
        SqlSession sqlSession= sqlSessionFactory.openSession();

        //获取Mapper
           UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        //调用方法
        User user = userMapper.selectUsername(username);

        //设置响应数据格式
        response.setContentType("text/html;charset=utf-8");
        //获取流
        PrintWriter write = response.getWriter();
        //头信息
        response.setHeader("content-type","text/html");

        //判断user是否为null
        if (user==null)
        {
            userMapper.add(username,password);
            //提交事务
            sqlSession.commit();
            write.write("注册成功");
        }
        else write.write("注册失败");

        sqlSession.close();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }
}

SqlSessionFactory 代码优化

//获取SqlSessionFactory对象
        String resource="mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

代码重复 — 工具类

SqlSessionFactory重复创建,浪费资源 — 静态代码块

package com.opn.util;

public class SqlSessionFactoryUtils {

    private static  SqlSessionFactory sqlSessionFactory;

    static {
        //静态代码块随类的加载自动执行,且只执行一次

        try{
            //获取SqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public static  SqlSessionFactory getSqlSessionFactory()
    {
        return sqlSessionFactory;
    }
}

调用

    //调用静态类
    SqlSessionFactory sqlSessionFactory= SqlSessionFactoryUtils.getSqlSessionFactory();

    //获取SqlSession对象
    SqlSession sqlSession= sqlSessionFactory.openSession();

JSP

Java Server Pages

Java服务端界面

一种动态的网页技术,其中既可以定义HTML、JS、CSS等静态内容,也可以定义Java代码的动态内容

JSP = HTML + Java

作用

简化开发,避免在Servlet中直接输出HTML代码

JSP快速入门

导入JSP坐标

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>provided</scope>
</dependency>

创建JSP文件

编写HTML和Java代码

JSP原理

JSP本质是一个Servlet

.jsp —> .java —> .class

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

JSP脚本

JSP脚本用于在JSP界面内定义Java代码

JSP脚本分类

//多类型
<%...%>  内容会直接放到_jspService()方法之中

//直接输出内容
<%=...%>   内容会放到out.print()中,作为out.print()的参数

//变量,方法
<%!...%>   内容会放到_jspService()方法之外,被类直接包含

JSP代码截断

可在java代码中穿插html代码

//遍历输出数字
<%
    for (int i = 0;i<100;i++) {
%>

<h1><%="当前的数字为"+i%></h1>

<%
    }
%>

JSP缺点

缺点

  • 复杂界面
  • 阅读麻烦
  • 复杂度高 运行需要依赖各种环境
  • 占用内存和磁盘
  • 调试困难 出错后,需要找到自动生成的.java文件进行调试
  • 不利于团队合作 前后端人员语言不同

不在JSP中直接写Java代码

其他方式替换JSP中的Java代码

JSP已逐渐退出历史舞台

—– > Servlet + HTML + AJAX

EL表达式

Expression Language 表达式语言

用于简化JSP界面的Java代码

写在前面 — isELIgnored 忽略/使用EL表达式

//使用EL表达式

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>

主要功能:获取数据

语法

${expression}

${a} 获取域中存储的key为a的数据

使用

    //1.准备数据
    String a = "123123";

    //2.存储到request域中
    request.setAttribute("aaa",a);

    //3.转发到el-demo.jsp
    request.getRequestDispatcher("/el-demo.jsp").forward(request,response);

输出 同效果

    ${aaa}

<%String p= (String) request.getAttribute("aaa");%>
<%=p%>

JavaWeb中的四大作用域

  • page:当前界面有效
  • request:当前请求有效
  • session:当前会话有效
  • application:当前程序有效

EL表达式获取数据,会依次从四个域中进行寻找,直到找到为止

JSTL标签

JSP标准标签库

Jsp Standarded Tag Library

使用标签取代JSP界面上的Java代码

快速入门

  1. 引入坐标

  2. 在JSP界面导入标签库

  3. 使用

    引入坐标
    ……

    导入标签库
    c:别名
    <%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core"%>

if

c:if 没有else

<c:if test="${aaa == "123123"}">
    <h1>true</h1>
</c:if>

<c:if test="${aaa != "123123"}">
    <h1>false</h1>
</c:if>

for

c:forEach

items:被遍历的容器

var:遍历产生的临时变量

varStatus:产生序号 index 从0 开始—count 从1开始

<c:forEach items="${a}"var="a" varStatus="status">
    <tr>
        <td>${a.id}</td>
        <td>${status.index}</td>
        <td>${a.name}</td>
        <td>${a.password}</td>
    </tr>
</c:forEach>

begin:开始数

end:结束数

step:步长

<c:forEach begin="0" end="10" step="1" var="i">
    ${i}
</c:forEach>

MVC模式和三层架构

MVC

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

Model—JavaBean
View—JSP
Controller—Servlet

三层架构

  • 表现层 — 接收请求,封装数据,调用业务逻辑层,响应数据 (Servlet+JSP)
  • 业务逻辑层 — 对业务逻辑进行封装,组成复杂的业务逻辑功能(登录、注册)
  • 数据访问层(持久层) — 对数据库增删改查的基本操作

表现层 — com.opn.web/controller
业务逻辑层 — com.opn.service
数据访问层(持久层) — com.opn.dao/mapper

三大框架 — SSM

  • SpringMVC
  • Spring
  • MyBatis

创建JavaWeb项目

https://www.bilibili.com/video/BV1Qf4y1T7Hx?p=118

会话跟踪技术

会话:

用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束

在一次会话中可以包含多次请求和响应

会话跟踪:

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

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

HTTP协议无状态,独立请求:
若非独立,后面的请求要携带前面请求的数据,请求体大,请求速度慢

实现方式:

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

Cookie基本使用

Cookie:

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

在Servlet中进行编写

  • 发送Cookie

    //1.创建Cookie对象,设置数据
    Cookie cookie = new Cookie(“key”,”value”);

    //2.发送Cookie到客户端,使用response对象
    response.addCookie(cookie);

  • 获取Cookie

    //1.获取浏览器携带的所有Cookie,使用request对象
    Cookie[] cookies = request.getCookies();

    //2.遍历数组,获取每一个Cookie对象:for

    //3.使用Cookie对象方法获取数据
    cookie.getName();
    cookie.getValue();

    ///…..获取对应name的value

    Cookie[] cookies = request.getCookies();

    for(Cookie cookie:cookies){

      String name = cookie.getName();
      if("name"==name){
          String value = cookie.getValue();
      }
    

    }

  • JSP el表达式 使用cookie值

    Cookie c_username = new Cookie(“username”,username);

    //el表达式使用cookie
    ${cookie.username.name}
    ${cookie.password.value}

    ${cookie.key.value}

Cookie原理

Cookie的实现是基于HTTP协议的

服务器向客户端发送—让客户端建立cookie
响应头:se-cookie

客户端向服务器发送—将cookie发送到服务器
请求头:cookie

Cookie使用细节

Cookie存活时间

默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁

Cookie持久化

//在创建Cookie时设置

setMaxAge(int seconds):设置cookie存活时间
1.正数:将Cookie写入浏览器所在的电脑硬盘,持久化存储,到时间自动删除
2.负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
3.零:立即删除对应Cookie

Cookie存储中文

不支持直接存储中文

使用URL编码

String value="张三";

value = URLEncoder.encode(value,"UTF-8");

Cookie cookie = new Cookie("username",value);

URL解码

String value = cookie.getValue();

value = URLDecoder.decode(value,"UTF-8");

Session基本使用

服务器会话跟踪技术:将数据保存到服务器

JavaEE提供HttpSession接口,来实现一次会话的多次请求间的数据共享功能

使用

//1.获取Session对象
HttpSession session = request.getSession();

//2.Session对象功能

//存储数据到Session域中
session.setAttribute();
void setAttribute(String name,Object o)

//根据key值,获取value
Object getAttribute(String name)

//根据key,删除该键值对
void removeAttribute(String name)

Session原理

Session 是基于Cookie实现的

根据cookie区分不同session对象

JESSIONID=xxx — 对应 — id=xxx 的Session

set-cookie —>

cookie <—

Session使用细节

Session钝化、活化

服务器重启,Session中的数据是否存在

钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中

活化:再次启动服务器后,从文件中加载数据到Session中(并将本地文件删除)

Session销毁

默认情况下,无操作,30分钟自动销毁

在web.xml中

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

Session调用invalidate()方法

登录、登出

session.invalidate();

区别

  • 存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端
  • 安全性:Cookie 不安全,Session安全
  • 数据大小:Cookie最大3KB,Session无大小限制
  • 存储时间:Cookie可以长期存储,Session 默认30分钟
  • 服务器性能:Cookie不占服务器资源,Session占用服务器资源

示例:保存个人信息

loginServlet


if (user!=null){
        Cookie c_username = new Cookie("username",username);
        response.addCookie(c_username);
        //判断用户是否勾选选项--记住我
        if(remember==1)
        {
            c_username.setMaxAge(1000);
            String checked = "true";
            Cookie c_password = new Cookie("password",password);
            c_password.setMaxAge(1000);
            response.addCookie(c_password);
            Cookie c_checked = new Cookie("checked",checked);
            c_checked.setMaxAge(1000);
            response.addCookie(c_checked);
        }
        else {
            Cookie[] cookies = request.getCookies();
            for(Cookie cookie:cookies){
                String name = cookie.getName();
                if("password".equals(name)|"checked".equals(name)){
                    cookie.setMaxAge(0);
                }
            }
        }
        request.getRequestDispatcher("/index.jsp").forward(request,response);

    }
    else {
        request.setAttribute("log_msg","登录失败");
        request.getRequestDispatcher("/login.jsp").forward(request,response);
    }

前端界面---login.jsp

<form action="/Tdemo/loginServlet" id="form">
    <h1 id="loginMsg">LOGIN IN</h1>
    <h1 >${log_msg}</h1>
    <p>Username:<input id="username" name="username" type="text" value=${cookie.username.value}></p>
    <p>Password:<input id="password" name="password" type="password" value=${cookie.password.value}></p>
    <p>Remember:<input id="remember" name="remember" value="1" type="checkbox" checked=${cookie.checked.value}></p>

示例:验证码

验证码是java代码生成的图片

https://opn90.top/2023/01/21/JavaWeb-Verification-code/

Filter过滤器

Filter 表示 过滤器 是JavaWeb 三大组件 (Servlet,Filter,Listener)之一

过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能

通用的操作 — 权限控制,统一编码处理,敏感字符处理

Filter快速入门

  1. 定义类,实现Filter接口,并重写所有方法

     //javax.servlet的Filter接口
    
     public class FilterDemo implements Filter {
         @Override
         public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
         }
         @Override
         public void init(FilterConfig filterConfig) throws ServletException {}
         @Override
         public void destroy() {}
     }
    
  2. 配置Filter让拦截资源的路径:在类上定义@WebFilter注解

    //在FilterDemo类上方添加
    @WebFilter("/*")    
  1. 在doFilter方法中进行相关处理,并放行

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

     System.out.println("Filter~~~");
    
     //放行
     filterChain.doFilter(servletRequest,servletResponse);
    

    }

Filter执行逻辑

web端请求—>放行前逻辑—>放行—>访问web资源、服务器端处理—>放行后逻辑—>返回响应

//放行
    filterChain.doFilter(servletRequest,servletResponse);

当url请求时,先执行Filter的放行前逻辑,再访问web资源,然后执行放行后逻辑,最后返回响应

放行前,对request数据进行处理
放行
放行后,对response数据进行处理

Filter拦截路径配置

@WebFilter("/*")

拦截具体的资源 /index.jsp — 前面不带项目名称,直接/文件
目录拦截 /user/*
后缀名拦截下 .jsp
拦截所有 /

过滤器链

一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链

filter1,filter2

请求–1.前–1.放行–2.前–2.放行–资源–2.后–1.后–响应

注解配置的Filter,优先级按照过滤器类名(字符串)的自然排序

登录验证 示例

判断url
开放访问登录、注册的界面
限制访问其他界面

LoginServlet

        //登录验证
            HttpSession session = request.getSession();
            session.setAttribute("islogin","1");

FilterDemo

//强制转化为HttpRequest
    HttpServletRequest req = (HttpServletRequest)servletRequest;

    //********** 判断访问资源路径是否和登录注册相关
    String[] urls = {"/login.jsp","/imgs","/css","/loginServlet","/register.jsp","/registerServlet","/checkCodeServlet"};
    //获取当前访问的资源路径
    String url = req.getRequestURL().toString();

    //循环判断
    for (String u :urls) {
        if(url.contains(u)) {
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
    }

    //********** 和登录不相关的url,判断登录后跳转到登录界面
    HttpSession session = req.getSession();
    Object islogin = session.getAttribute("islogin");
    System.out.println(islogin);

    if(islogin!=null){
        System.out.println("islogin!=null"+islogin);
        if(Objects.equals(islogin.toString(), "1"))
        {
            System.out.println("islogin==1"+islogin);
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
    else
    {
        System.out.println("islogin==null");
        req.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
    }

Listener

监听器

JavaWeb三大组件之一

监听器可以监听在application,session,request三个对象的创建、销毁或者向其中添加修改删除属性时 自动执行代码的功能组件

Listener分类

JavaWeb中提供了8个监听器

使用

1、定义类,实现ServletContextListener接口
复写方法

2、在类上添加@WebListener注解
无需配备路径,自动监听

AJAX

Asynchronous JavaScript And Xml

异步的HavaScript和XML

作用:

1、与服务器进行数据交换,通过AJAX可以给服务器发送请求,并获取服务器响应的数据

使用了AJAX和服务器进行通信,就可以用HTML+AJAX来替换JSP界面

前端工程师–html+ajax

后端纯java

在此之前,后端需要写jsp+java(不友好,分工不明确)

2、异步交互,可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页

同步和异步

不加载整个界面

在服务器端处理时,客户端可以进行其他的操作

AJAX 快速入门

1、编写AjaxServlet,并使用response输出字符串

2、创建XMLHttpRequest对象,用于和服务器交换数据

3、向服务器发送请求

4、获取服务器响应数据

2
https://www.w3school.com.cn/js/js\_ajax\_http.asp
3
https://www.w3school.com.cn/js/js\_ajax\_http\_send.asp
4
https://www.w3school.com.cn/js/js\_ajax\_http\_response.asp

服务端//1.响应数据
    response.getWriter().write("Hello AJAX");


客户端
<script>
//1.创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
    xhttp = new XMLHttpRequest();
} else {
    // code for IE6, IE5
    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.发送请求
xhttp.open("GET", "localhost:8080/Tdemo/ajaxServlet");
xhttp.send();
//3.获取响应
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
            alert(this.responseText);
    }
};
</script>

Axios异步框架

Axios对原生的AJAX进行封装,简化书写

官网
https://www.axios-http.cn

1、引入axios的js文件
2、使用axios发送请求,并获取响应结果

<script src="js/axios-0.18.0.js"></script>

axios({
    method:"get",
    url:"http://localhost:8080/Tdemo/axiosServlet?username=111",
}).then(function(resp){
    alert(resp.data);
})

axios({
    method:"post",
    url:"http://localhost:8080/Tdemo/axiosServlet",
    data:"username=1"
}).then(function(resp){
    alert(resp.data);
})

then() 后为获取响应结果后的前端操作

Axios请求方式别名

axios.get()

axios.get("http://localhost:8080/Tdemo/axiosServlet")
    .then(function(resp){
    alert(resp.data);
})

axios.post()

axios.post("http://localhost:8080/Tdemo/axiosServlet","username=1")
    .then(function(resp){
        alert(resp.data);
    })

JSON

JavaScript Object Notation

JavaScript 对象表示法

语法简单,层次结构鲜明,现多用于作为数据载体,在网络中进行数据传输

JSON基础语法

var 变量名 = {"key1":value1,
             "key2":value2,
             ...
            };

键需要带””
值按照数据类型带

value 数据类型

  • 数字(整数或者浮点数)
  • 字符串(在双引号中)
  • 逻辑值(true或false)
  • 数组(在方括号中)
  • 对象(在花括号中)
  • null

JSON数据和Java对象的相互转换

请求数据:JSON字符串转为Java对象

响应数据:Java对象转为JSON字符串

Fastjson

阿里巴巴提供的一个Java语言编写的高性能功能完善的JSON库,是目前Java语言中最快的JSON库,可以实现Java对象和JSON字符串的相互转换

使用

1、导入坐标
2、Java对象转JSON
3、JSON字符串转Java对象

String jsonStr = JSON.toJSONString(obj);

User user = JSON.parseObject(jsonStr,User.class);

服务端数据接收

不能用request.getParameter

    //获取请求数据
    BufferedReader br = request.getReader();
    String params = br.readLine();

    //将JSON对象转换为Java对象
    User user = JSON.parseObject(params,User.class);
    System.out.println(user);

AJAX - 客户端数据上传

<script>
//绑定单击事件
document.getElementById("btn").onclick = function (){
    //将表单数据转换为Json
    var formData = {
      userid:"",
      username:"",
      password:"",
    };
    //获取表单数据,设置数据
    formData.userid = document.getElementById("userid").value();
    formData.username = document.getElementById("username").value();
    formData.password = document.getElementById("password").value();


    //发送ajax请求
    axios({
        method:"get",
        url:"http://localhost:8080/demo/servlet",
        data:formData,
    }).then(function (resp){
        if(resp.data=="success"){
            //重新加载界面查询
            location.href="http://localhost:8080/demo/servlet";
        }
    })
}
</script>

Vue

前端框架,免除原生JavaScript中的DOM操作,简化书写

DOM document

Vue是一套前端框架,免除原生JavaScript中的DOM操作,简化书写

基于MVVM思想,实现数据的双向绑定,将编程的关注点放在数据上

Model–View–ViewModel

https://cn.vuejs.org

MVVM — MVC

MVC

只能实现模型到视图的单向展示

不能在更改模型数据之后,视图自动更改

MVVM

Model–View–ViewModel

可以实现数据的双向绑定

Vue快速入门

1、新建HTML界面,引入Vue.js文件

2、在JS代码区域,创建Vue核心对象,进行数据绑定

3、编写视图

//创建Vue核心对象
new Vue({
    //el--指定作用范围
    el:"#app",
    data:function (){
        return {
            //数据类型
            username:"",
        }
    }
})



<div id="app">
    <input v-model="username">
    <!--插值表达式-->
    {{username}}
</div>

Vue常用指令

指令:

HTML标签上带有v-前缀的特殊属性,不同指令具有不同含义

常用指令

//创建双向数据绑定
<input v-model="username">

https://blog.csdn.net/qq_42839746/article/details/124377801

Vue生命周期

生命周期的八个阶段

每触发一个生命周期事件,会自动执行一个生命周期方法(钩子)

mounted 挂载完成,Vue初始化完成,HTML界面渲染成功
发送异步请求,加载数据

new Vue({
    //el--指定作用范围
    el:"#app",
    data(){
        return {
            username:"",
        }
    mounted(){
        alert("vue挂载完成,发送异步请求");
    }
})

Vue - 客户端数据查询

<tr v-for="(TheData,i) in TheData">
    <td>{{i+1}}</td>
    <td>{{TheData.username}}</td>
    <td>{{TheData.password}}</td>
</tr>    




new Vue({
    el:"#app",
    data(){
        return{
            TheData:[],
        }
    },
    mounted(){
        //提升了TheData的作用域--解决--在axios中的this.TheData为windows参数,无法访问到Vue的TheData
        var _this= this;
        axios({
            method:"get",
            url:"http://localhost:8080/demo/servlet",
        }).then(function (resp){
            _this.TheData = resp.data;
        })
    }
})

Vue - 客户端数据添加–提交

<div id="app">
    <form action="" method="get">
        用户名:<input id="Username"v-model="TheData.username" name="username">
        密码:...
        
        <input type="button" id="btn" @click="submitform" value="提交">
    </form>
    
</div>


new Vue({
    el:"#app",
    data(){
        return{
            TheData:{},
        }
    },
    mounted(){
        submitform(){}
            //提升了TheData的作用域--解决--在axios中的this.TheData为windows参数,无法访问到Vue的TheData
            var _this= this;
            axios({
                method:"get",
                url:"http://localhost:8080/demo/servlet",
                data:_this.formData,
            }).then(function (resp){
                ...
        })
    }
}
})

Element

饿了么公司前端开发团队提供的一套基于Vue的网站组件库,用于快速构架网站

组件:组成网页的部件 超链接、按钮、图片、表格等


欠缺内容

MyBatis自动代理

依赖倒置


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!