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语法–事务
navicat–可视化工具
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
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代码
快速入门
引入坐标
在JSP界面导入标签库
使用
引入坐标
……导入标签库
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 不安全,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快速入门
定义类,实现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() {} }
配置Filter让拦截资源的路径:在类上定义@WebFilter注解
//在FilterDemo类上方添加
@WebFilter("/*")
在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进行封装,简化书写
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
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 协议 ,转载请注明出处!