JavaWeb介绍
对勾都要重点学习
- Tomcat + HTTP + Servlet
- Request + Response
- JSP
- Cookie + Session
- Filter + Listener
- 综合案例
Juit测试
@test
class addtest(){
}
用断言判定结果是否正确
Assert.assertEquals(期望的结果,程序运算的结果)不一样就会抛出黄色警告
@Before
被Before修饰的方法会在test方法执行前被自动执行
@After
被After修饰的方法会在测试方法执行后自动执行,用于释放资源
反射
- 框架设计的灵魂
注解
本质就是一个接口,该接口默认继承Annotation接口
自定义注解格式: public @interface 注解名称{ }
属性:接口中的抽象方法
要求:
-
属性的返回值类型有下列取值
- 基本数据类型
- String
- 枚举
- 注解
- 以上数据类型的数组
-
定义了属性,在使用时需要给属性赋值
- 如果定义属性时,使用default关键字给默认初始化值,则使用注解时,可以不进行属性的赋值
- 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
- 数组赋值时,值使用{}包裹,如果数组只有一个值,则省略{}
一、JDBC
- JDBC就是使用java语言操作关系型数据库的一套API
1.简介
用java语言操作关系型数据库的一套API 全程 java Database Connectivity Java数据连接
同一套代码,操作不同的关系型数据库,JDBC就是一套标准的接口来连接各种数据库
2.快速入门
给idea项目添加jar包:https://blog.csdn.net/weixin_44031029/article/details/109284132
先给当前的项目文件中添加jar驱动包,然后改为局部模块
// 8.0版本后的jar驱动文件,mysql5之后这行代码可以不写
Class.forName("com.mysql.cj.jdbc.Driver");
//之前
Class.forName("com.mysql.jdbc.Driver");
/*---------------------------JDBC操作数据库步骤-----------------------*/
package com.mypro.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/*
JDBC快速入门
*/
public class JDBCDemo {
public static void main(String[] args) throws Exception {
//1. 注册驱动 jar包版本用的是Class.forName("com.mysql.jdbc.Driver");,8.0版本之后的要用下面这个
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/heima";
String username = "root";
String password = "123456";
//定义mysql路径,用户名和密码,方便登录
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的对象statement
int count = stmt.executeUpdate(sql);
//6.处理结果
System.out.println(count);
//7.释放资源
stmt.close();
conn.close();
}
}
3.API详解
1.DriverManager
- 注册驱动
- 获取数据库连接
上面的栗子中,获取路径时出现了三个参数,url(连接路径),user(用户名),password(密码).这里对url做一个讲解
// url 连接路径
/*
语法: jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2...
示例: jdbc:mysql://localhost:3306/heima ip地址可以用localhost替代
细节:
1.如果连接的是本机的mysql服务器,并且mysql服务默认端口是3306,则url可以简写为: jdbc:mysql:///数据库名称?参数键值对
2.配置useSSL=false参数,禁止安全连接方式,解决警告提示
*/
//localhost代替ip地址
String url = "jdbc:mysql://localhost:3306/heima";
//本地mysql简写
String url = "jdbc:mysql:///heima";
//加上键值对
String url = "jdbc:mysql:///heima?useSSL=false";
2.Connection
数据库连接对象,作用:
- 获取执行SQL的对象
- 管理事务
// 普通执行SQL对象 !!
Statement createStatement()
//预编译SQL的执行SQL对象,防止SQL注入 !!
preparedStatement prepareStatement(sql)
//执行存储过程的对象
CallableStatement prepareCall(sql)
// 事务管理
//Mysql事务管理 默认自动提交
开启事务:begin/start transaction
提交事务:commit
回滚事务:rollback
//JDBC事务管理:Connection接口中定义了三个对应方法
//开启事务
setAutoCommit(boolean autoCommit): true为自动提交事务,false手动
//提交事务
commit()
//回滚事务
rollback()
/*-------------------------------处理事务案例----------------------------------*/
package com.mypro.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo3_Connection {
public static void main(String[] args) throws Exception {
//1. 注册驱动 jar包版本用的是Class.forName("com.mysql.jdbc.Driver");,8.0版本之后的要用下面这个
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/heima";
String username = "root";
String password = "123456";
//定义mysql路径,用户名和密码,方便登录
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义SQL
String sql1 = "update account set money = 4000 where id = 1";
String sql2 = "update account set money = 2000 where id = 2";
//4.获取执行sql的对象statement
Statement stmt = conn.createStatement();
//------------------------- 事务管理----------------------------------
try {
//开启事务
conn.setAutoCommit(false);
//5.执行sql的对象statement
int count1 = stmt.executeUpdate(sql1);
int count2 = stmt.executeUpdate(sql2);
//6.处理结果
System.out.println(count1);
System.out.println(count2);
//提交事务
conn.commit();
} catch (Exception e) {
conn.rollback();
throw new RuntimeException(e);
}
//7.释放资源
stmt.close();
conn.close();
}
}
3.Statement
作用:用于执行sql语句
//执行SQL语句
int executeUpdate(sql):执行DML、DDL语句
//返回值:1.DML语句影响的行数 2.DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql)执行DQL语句
返回值 : ResultSet结果集对象
4.ResultSet(结果集对象)
作用:1.封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql):执行SQL语句,返回ResultSet对象
//获取查询结果
Boolean next:(1)将光标从当前位置向前移动一行 (2)判断当前行是否为有效行
返回值:
true 有效行,当前行有数据 false 无效行,当前行没数据
xxx getXxx(参数):获取数据
xxx:数据类型;如int getInt(参数) String getString(参数)
参数:
int 列的编号,从1开始 String列的名称
使用步骤:
- 游标向下移动一行,并判断改行是否有数据:next()
- 获取数据:getXxx(参数)
//循环判断游标是否是最后一行末尾
while(rs.next()){
//获取数据
rs.getXxx(参数);
}
//----------------------------------------案例--------------------------------
/**
* 执行DQL,查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中
* 1.定义实体类Account
* 2.查询数据,封装到Account对象中
* 3.将Account对象存入到ArrayList集合中
*
*
* @throws Exception
*/
@Test
public void testResultSet2() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/heima";
String username = "root";
String password = "123456";
//定义mysql路径,用户名和密码,方便登录
Connection conn = DriverManager.getConnection(url, username, password);
//3.定义SQL
String sql = "select * from account";
//4.获取statement对象
Statement stmt = conn.createStatement();
//5.执行sql
ResultSet rs = stmt.executeQuery(sql);
//创建一个集合
List<Account> list = new ArrayList<>();
//6.处理结果,遍历rs中的所有数据
//6.1光标向下一行并且判断是否有数据
//因为get中有方法的重载,所以可以直接写字段名
while (rs.next()) {
//每循环一遍创建一个对象,将下面的数据放入对象中,然后存入集合
Account account = new Account();
//6.2获取数据 getXxx
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
//给对象赋值
account.setId(id);
account.setName(name);
account.setMoney(money);
//将对象存入集合
list.add(account);
}
System.out.println(list);
//7.释放资源
rs.close();
stmt.close();
conn.close();
}
}
5.PreparedStatement(执行SQL语句的对象)
继承自statement,作用:
- 预编译SQL语句并执行:预防SQL注入问题
SQL注入:通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法
//1.获取preparedStatement对象
//SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pst = conn.prepareStatement(sql);
//2.设置参数值
PreparedStatement 对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型;如setInt(参数1,参数2)
参数:
参数1:?的位置编号,从1开始
参数2:?/的值
//3.执行SQL
executeUpdate(); / executeQuery() 不需要在传递sql
4.数据库连接池
1.简介
- 数据库连接池是个容器,负责分配、管理数据库连接
- 它允许应用程序重复使用一个现有的数据库连接,而不是在重新建立一个
- 释放空间时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接二引起的数据库连接遗漏
好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
标准接口:DataSource
- 官方提供的数据库连接池标准接口,由第三方组织实现此接口
- 功能:获取连接 Connection getConnection()
常见的数据库连接池:DBCP、C3P0 、Druid
Druid:是阿里巴巴开源的数据库连接池项目,功能强大,性能优,是java语言最好的数据库连接池之一
2.Driud使用步骤
- 导入jar包 druid-1.1.12jar
- 定义配置文件
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
配置driud文件
-
下载driud.jar包:https://blog.csdn.net/YyjYsj/article/details/108854572
-
将jar包放入同自己的项目的文件中
- 因为要放入多个jar包,可以创一个文件夹专门放包
-
加载配置文件:在src目录下写一个druid.properties文件
1.
-
#配置文件中的内容 driverClassName=com.mysql.cj.jdbc.Driver #自己SQL文件的注册驱动 # mysql的连接,根据自己本机来设置 url=jdbc:mysql:///heima?useSSL=false&useServerPrepStmts=true username=root password=123456 # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 #最大等待时间 maxWait=3000
-
-
在java类中代码实现
-
package com.mypro.druid; import com.alibaba.druid.pool.DataSourceClosedException; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.util.Properties; /** * Druid数据库连接池演示 */ public class DruidDemo { public static void main(String[] args) throws Exception { // 1.导入jar包 //2.定义配置文件 //3.加载配置文件 Properties prop = new Properties(); //本地的druid.properties文件目录 prop.load(new FileInputStream("D:/idea-2022/mypro/MyWeb_test/src/druid.properties")); //4.获取连接池对象 DataSource dataSource = DruidDataSourceFactory.createDataSource(prop); //5.获取数据库连接 Connection Connection connection = dataSource.getConnection(); System.out.println(connection); System.out.println(System.getProperty("user.dir")); } }
-
5.实现品牌数据的增删改查案例
1.MySQL数据库准备
# 创建品牌信息table
create table tb_brand
(
id int primary key auto_increment,
brand_name varchar(20),
company_name varchar(20),
ordered int,
description varchar(100),
status int
);
insert into tb_brand
values (null, '三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
(null, '华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人,每个家庭,每个组织,构建万物互联的智能世界', 1),
(null, '小米', '小米科技有限公司', 50, 'are you ok', 1);
2.idea中Brand类创建
package com.mypro.pojo;
/**
* 品牌信息
* <p>
* 实体类中,基本数据类型建议使用其对应的包装类型
*/
public class Brand {
//主键
private Integer id;
//品牌名称
private String brandName;
//企业名称
private String companyName;
//排序字段
private Integer ordered;
//描述信息
private String description;
//状态 0禁用 1启用 用Integer而不用int是因为int有默认值0,可能对业务产生影响,Integer默认值是null
private Integer status;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrandName() {
return brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Integer getOrdered() {
return ordered;
}
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
@Override
public String toString() {
return "Brand{" +
"id=" + id +
", brandName='" + brandName + '\'' +
", companyName='" + companyName + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
}
3.查询所有数据
- 获取connection
- 定义SQL:select * from tb_brand;
- 获取PreparedStatement对象
- 设置参数:不需要
- 执行SQL
- 处理结果:将每一个对象放入集合中 List
- 释放资源
/**
* 查询所有
* 1. SQL: select * from tb_brand;
* 2. 是否需要参数,这里不需要
* 3. 结果存入 : brands<list>
*
* @throws Exception
*/
@Test
public void testSelectAll() throws Exception {
//注册驱动连接java和MySql
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql:///heima";
String username = "root";
String password = "123456";
//1.获取Connecion
Connection conn = DriverManager.getConnection(url, username, password);
//2.定义sql查找语句
String sql = "select * from tb_brand;";
//3.获取执行sql对象的statement对象
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//4.执行sql
ResultSet rs = preparedStatement.executeQuery();
//创建一个集合存储对象
List<Brand> brands = new ArrayList<>();
Brand brand = null;
//游标判断,是否找到数据,一个一个检索
while (rs.next()) {
brand = new Brand();
//获取数据
int id = rs.getInt("id");
String brandName = rs.getString("brand_name");
String comName = rs.getString("company_name");
int order = rs.getInt("ordered");
String description = rs.getString("description");
int status = rs.getInt("status");
brand.setId(id);
brand.setBrandName(brandName);
brand.setCompanyName(comName);
brand.setOrdered(order);
brand.setDescription(description);
brand.setStatus(status);
//装载集合
brands.add(brand);
}
System.out.println(brands);
//资源释放
rs.close();
preparedStatement.close();
conn.close();
}
4.添加数据
/**
* 添加
* 1. SQL: insert into tb_brand(brand_name,company_name,ordered,description,status)
* values(?,?,?,?,?); 问号个数与表中参数个数一样
* 2. 是否需要参数,需要,除了id的所有参数 id由数据库自动生成,设置auto_increment;
* 3. 结果 : boolean
*
* @throws Exception
*/
@Test
public void testAdd() throws Exception {
//接受页面提交的参数
String brandName = "香飘飘";
String companyName = "香飘飘";
int ordered = 1;
String description = "绕地球一圈";
int status = 1;
//注册驱动连接java和MySql
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql:///heima";
String username = "root";
String password = "123456";
//1.获取Connecion
Connection conn = DriverManager.getConnection(url, username, password);
//2.定义sql查找语句
String sql = "insert into tb_brand(brand_name,company_name,ordered,description,status)values(?,?,?,?,?);";
//3.获取执行sql对象的statement对象
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//4.设置参数
preparedStatement.setString(1, brandName);
preparedStatement.setString(2, companyName);
preparedStatement.setInt(3, ordered);
preparedStatement.setString(4, description);
preparedStatement.setInt(5, status);
//5.执行sql executeUpdate方法返回的是受影响的行数
int count = preparedStatement.executeUpdate();
//6.处理结果
if (count > 0) {
System.out.println("处理成功");
} else {
System.out.println("处理失败");
}
//7.资源释放
preparedStatement.close();
conn.close();
}
5.修改数据
/**
* 修改
* 1. SQL:
update tb_brand
set brand_name = ?,
company_name = ?,
ordered = ?,
description = ?,
status = ?
where id = ?
* <p>
* <p>
* 2. 是否需要参数,需要,除了id的所有参数 id由数据库自动生成,设置auto_increment;
* 3. 结果 : boolean
*
* @throws Exception
*/
@Test
public void testUpdate() throws Exception {
//修改页面提交的参数
String brandName = "香飘飘";
String companyName = "香飘飘";
int ordered = 1000;
String description = "绕地球3圈";
int status = 1;
int id = 4;
//注册驱动连接java和MySql
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql:///heima";
String username = "root";
String password = "123456";
//1.获取Connecion
Connection conn = DriverManager.getConnection(url, username, password);
//2.定义sql查找语句
String sql = "update tb_brand\n" +
" set brand_name = ?,\n" +
" company_name = ?,\n" +
" ordered = ?,\n" +
" description = ?,\n" +
" status = ?\n" +
" where id = ?";
//3.获取执行sql对象的statement对象
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//4.设置参数
preparedStatement.setString(1, brandName);
preparedStatement.setString(2, companyName);
preparedStatement.setInt(3, ordered);
preparedStatement.setString(4, description);
preparedStatement.setInt(5, status);
preparedStatement.setInt(6, id);
//5.执行sql executeUpdate方法返回的是受影响的行数
int count = preparedStatement.executeUpdate();
//6.处理结果
System.out.println(count > 0);
//7.资源释放
preparedStatement.close();
conn.close();
}
6.删除操作
/**
* 删除操作
* 1. SQL: delete from tb_brand where id = ?;
* 2. 是否需要参数,需要,id的参数
* 3. 结果 : boolean
*
* @throws Exception
*/
@Test
public void testDeleteById() throws Exception {
//修改页面提交的参数
int id = 4;
//注册驱动连接java和MySql
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql:///heima";
String username = "root";
String password = "123456";
//1.获取Connecion
Connection conn = DriverManager.getConnection(url, username, password);
//2.定义sql语句
String sql ="delete from tb_brand where id = ?";
//3.获取执行sql对象的statement对象
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//4.设置参数
preparedStatement.setInt(1, id);
//5.执行sql executeUpdate方法返回的是受影响的行数
int count = preparedStatement.executeUpdate();
//6.处理结果
System.out.println(count > 0);
//7.资源释放
preparedStatement.close();
conn.close();
}
二、Maven
1.Maven简介
- Maven是专门用于管理和构建Java项目的工具,它的主要功能有
- 提供了一套标准化的项目结构
- 提供了一套标准化的构建流程(编译,测试,打包,发布)
- 提供了一套依赖管理机制
Maven是一个项目管理和构建的工具,它基于项目对象模型(POM)的概念,通过一小段描述信息来管理项目的构建、报告和文档
作用:
- 标准化的项目结构
- 标准化的构建流程
- 方便的依赖管理
2.Maven安装配置
https://blog.csdn.net/qq_38190185/article/details/115921070
3.Maven基本使用
常用命令
- compile 编译
- clean 清理
- test 测试
- package 打包
- install 安装
4.IDEA配置Maven
IDEAMaven的配置:https://blog.csdn.net/hgnuxc_1993/article/details/125427590
1.Maven坐标
- 什么是坐标:
- Maven中的坐标是资源的唯一标识
- 使用坐标来定义项目或引入项目中需要的依赖
- Maven坐标主要组成
- groupId:定义当前Maven项目隶属组织的名称(通常是域名反写,例如com.heima)
- artifactId定义当前Maven项目名称(通常是模块名称,例如order-service、goods-service)
- version:定义当前项目版本号
2.IDEA创建Maven项目
- 创建模块,选择新建项目(idea2022默认java项目)
- 选择下面的构建Maven系统,finish创建完成
- 高级设置里可以设置公司id
- 创建成功后可编写java项目
3.导入外部Maven项目
5.依赖管理
步骤 使用坐标导入jar包
- 在pom.xml中编写标签
- 在标签中使用引入坐标
- 定义坐标的groupId,artifactId,varsion
- 点击刷新按钮,使坐标生效
1.依赖范围
XML
概念:可拓展标记语言,标签都是自定义的
1.功能
- 存储数据
- 配置文件
- 在网络中传输
xml和html的区别
- xml标签都是自定义的,html标签是预定义
- xml的语法严格,html的语法松散
- xml是存储数据的,html是展示数据的
2.语法
基本语法
- xml文档的后缀名 .xml
- xml第一行必须定义为文档声明
- xml文档中有且仅有一个根标签
- 属性值必须使用引号(单双都可以)引起来
- 标签必须正确关闭
- xml标签名称区分大小写
约束:规定xml文档的书写规则
作为框架的使用者(程序员):
1.能够在xml引入约束文档
2.能够简单的读懂约束文档
操作xml文档
- 解析(读取):将文档中的数据读取到内存中
- 写入:将内存中的数据保存到xml文档中.持久化的存储
解析xml的方式:
- DOM:将标记语言文档一次性加载进内存,在内存中形成一颗dom树 客户端
- 优点:操作方便,可以对文档进行增删改查操作
- 缺点:占内存
- SAX:逐行读取,基于事件驱动 移动端
- 优点:不占内存
- 缺点:只能读取,不能增删改
Maven创建Web项目
1.利用骨架–Maven Archetype创建–> 找这个
删除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>Tomcat-demo1</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 打包方式 打成war包-->
<packaging>war</packaging>
</project>
在main文件中创建 java和resources项目
2.不利用骨架
-
直接创建Maven项目,并给pom.xml配置打包方式为war–>war
-
点击文件–>项目结构
-
找到facet–>配置web项目
-
Web项目生成后记住拖拽到src下的main目录下面
Maven集成本地tomcat
1.手动导入
正常添加配置
2.maven插件导入
在pom.xml中配置插件
<build>
<plugins>
<!-- tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build>
Web
1.Web相关内容回顾
- 软件架构
- C/S:客户端/服务器端
- B/S:浏览器/服务器端
- 资源分类
- 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源,静态资源可以直接被浏览器解析 如html,css,js
- 动态资源:每个用户访问相同资源后,得到的结果可能不一样,称为动态资源,动态资源被访问后,需要先转换为静态资源,在返回给浏览器. 如 servlet/jsp,php,asp…
- 网络通信三要素
- IP:电子设备在网络中的唯一标识
- 端口:应用程序在计算机中的唯一标识. 0~65536
- 传输协议:规定了数据传输的规则
- 基础协议
- tcp安全协议,三次握手.速度稍慢
- udp不安全协议.速度快
- 基础协议
2.Tomcat安装及配置
apache基金组织,中小型的javaEE服务器,仅仅支持少量的JavaEE规范 servlet/jsp 开源的,免费的
-
官网下载:https://tomcat.apache.org/
-
将压缩包解压到自定目录(目录文件中不要出现中文和空格)
-
打开解压后的bin目录,点击startup.bat启动
- 如果闪退:java环境配置问题
- 乱码:打开D:\Tomcat\apache-tomcat-10.0.22\conf 中的logging.properties文件,将java.util.logging.ConsoleHandler.encoding = UTF-8替换成java.util.logging.ConsoleHandler.encoding = GBK
-
浏览器网址中输入:http://127.0.0.1:8080,如果出现一只猫,则说明Tomcat安装配置成功了
-
黑窗口中输入:ipconfig查看自己当前的ip地址
-
Tomcat启动报错
- 可能时启动端口8080被占用,解决方法
- 暴力,找到占用端口的程序,直接关闭.输入netstat -ano找到当前占用的端口号,在任务管理器里直接结束进程
- 温柔,改一个启动端口在重新启动:
- 可能时启动端口8080被占用,解决方法
-
Tomcat关闭:
- 正常关闭:ctrl+c
- 强制关闭,点击x号
-
配置
- 部署项目的方式
- 直接将项目放到webapps目录下接口
- 简化部署:将项目打成一个war包,再将war包放置到webapps目录下,自动解压缩
- 直接将项目放到webapps目录下接口
- 部署项目的方式
Servlet
1.Servlet接口在idea中无法创建
Servlet包本来就不是Java自带的,需要tomcat外部导入,正常情况下是不会出现Servlet包没有的情况,除非更改tomcat版本的时候,路径文件配置没有更新,导致无法使用,点击运行–>编辑配置–>配置,往下拉,找到库
里面如果有这两个文件则说明可以正常使用Servlet接口
概念:运行在服务端的小程序
Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则.
将来我们自定义一个类,实现Servlet接口,复写方法
2.快速入门
-
创建javaEE项目
-
定义一个类实现Servlet接口
-
public class ServletDemo1 implements Servlet
-
-
实现接口中的抽象方法
-
配置Servlet
-
Servlet3.0版本之前: <!--配置Servlet --> <servlet> <servlet-name>demo1</servlet-name> //文件的路径名 <servlet-class>mypro.ServletDeom1</servlet-class> </servlet> <!-- 设置映射--> <servlet-mapping> <servlet-name>demo1</servlet-name> <url-pattern>/demo1</url-pattern> </servlet-mapping> Servlet3.0版本之后-----利用注解进行配置 创建时不用勾选creat web.xml选项,在实现Servlet的类中添加@WebServlet("/demo"); demo----Servlet的名称,资源路径,输入这个路径后,调用接口中的service方法
-
-
运行servlet,运行一遍,执行一次service方法
Servlet生命周期:
-
被创建:执行init方法,只执行一次
-
默认情况下,第一次被访问时,但也可以自己设置它的执行时间
-
<servlet> <servlet-name>demo1</servlet-name> <servlet-class>crz.mypro.ServletDemo1</servlet-class> <!--指定Servlet的创建时机 在<servlet>标签下修改 1.第一次被访问时,创建<load-on-startup>的值为负数 2.在服务器启动时,创建<load-on-startup>的值为0或正整数 Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例 多个用户同时访问时,可能存在线程安全问题 解决:尽量不要在Servlet中定义成员变量.及时定义了成员变量,也不要对修改值 --> <load-on-startup>-5</load-on-startup> </servlet>
-
-
提供服务:执行service方法,执行多次
-
被销毁:执行destroy方法,只执行一次
- Servlet被销毁时执行,服务器关闭时,Servlet被销毁
- 只有服务器正常关闭时,才会执行destroy方法
- 在Servlet被销毁之前执行,用于释放资源
3.Servlet体系结构
1.Request对象
在service力的两个参数:
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service.....");
}
- request对象和response对象的原理
- request和response对象是由服务器创建的.我们来使用它
- request对象来获取请求消息,response对象来设置相应消息
- request对象继承体系结构
- ServletRequest --接口
- HttpServletRequest --接口
- request功能
- 获取请求消息
- 获取请求行数据
- GET/虚拟目录/Servlet路径/name=zhang;
- 获取请求方式:GET String getMethod();
- (* )获取虚拟目录 :String getContextPath();
- 获取Servlet路径:String getServletPath();
- 获取get方式请求参数:String getQueryString();
- (*)获取请求URI:/虚拟目录/Servlet路径 Sting getRequestURI(); StringBuffer getRequestURL();
- URL:统一资源定位符:http://localhost:8080/Mytom/demo1 中华人民共和国
- URI统一资源标识符:/Mytom/demo1 共和国
- 获取版本号: Sting getProtocol()
- 获取客户机的IP地址:String getRemoteAddr();
- GET/虚拟目录/Servlet路径/name=zhang;
- 获取请求头数据
- (*)String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration getHeaderNames():获取所有请求头的名称
- 获取请求体数据
- 获取请求行数据
- 获取请求消息
package crz.mypro;
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("/demo1")
public class RequestDemo1 extends HttpServlet {
/**
* Request获取请求行数据
*/
//1.获取请求方式:GET
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求方式
String method = req.getMethod();
System.out.println(method);
//2.获取虚拟目录
String contextPath = req.getContextPath();
System.out.println(contextPath);
//3.获取Servlet路径
String servletPath = req.getServletPath();
System.out.println(servletPath);
//4.获取get方式请求参数
String queryString = req.getQueryString();
System.out.println(queryString);
//5.获取请求URI
String requestURI = req.getRequestURI();
StringBuffer requestURL = req.getRequestURL();
System.out.println(requestURI);
System.out.println(requestURL);
//6.获取协议及版本
String protocol = req.getProtocol();
System.out.println(protocol);
//7.获取客户机ip地址
String remoteAddr = req.getRemoteAddr();
System.out.println(remoteAddr);
}
}
request其他功能
1.获取请求参数的方式
package crz.mypro;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
// -----------------------获取请求头数据--------------------------------
@WebServlet("/demo2")
public class RequestDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取所有请求头的值
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = req.getHeader(name);
System.out.println(name + "---" + value);
}
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//post获取请求参数
//1.根据参数获取参数值(用于input表单)
String username = req.getParameter("username");
System.out.println("post");
//post方式获取中文参数乱码解决方式---->设置流的编码
req.setCharacterEncoding("utf-8")
System.out.println(username);
//2.获取参数值数组(获取表单值)
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
//3.获取所有请求的参数名称(获取键值对)但只能获得一个值
Enumeration<String> parameterNames = req.getParameterNames();
//往后迭代,如果还有数据,则返回true
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();
System.out.println(name);
String value = req.getParameter(name);
System.out.println(value);
System.out.println("---------------------");
}
}
username
zhangsan
---------------------
password
123
---------------------
hobby
game
---------------------
//4.获取所有参数的map集合
Map<String, String[]> parameterMap = req.getParameterMap();
//遍历
Set<String> keySet = parameterMap.keySet();
for (String name : keySet) {
//获取键值
String[] values = parameterMap.get(name);
System.out.println(name);
for (String value : values) {
System.out.println(value);
}
}
username
zhangsan
------------
password
123
-------------
hobby
game
study
2.请求转发
步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse response)
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前浏览器内部资源中
- 转发是一次请求
3.共享数据
域对象 :一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
- void setAttribute(String name,Object obj)存储数据
- Object getAttribute(String name)通过键获取值
- void removeAttribute(String name)通过键移除键值对
4.获取ServletContext
2.Response对象
-
功能:设置相应消息
- 设置相应行
- 格式:HTTP/1.1 200 ok
- 设置状态码:setStatus(int sc)
- 设置响应头:setHeader(String name,String value)
- 设置相应体
- 获取输出流
- 字符输出流:printWriter()
- 字节输出流:servletOutputStream getOutputStream()
- 使用输出流,将数据输出到客户端浏览器
- 获取输出流
- 设置相应行
-
案例:
-
完成重定向:资源跳转
-
代码实现:
-
//设置状态码为302 response.setStatus(302); //设置响应头,及告诉服务器要跳转的资源路径 response.setHeader("跳转的文件路径"); //简单的重定向方法 response.sendRedirectn ("跳转的文件路径")
-
-
重定向的特点:
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求.不能使用request对象来共享数据
-
转发的特点:
- 转发地址栏路径不变
- 转发只能访问当前服务器下的资源
- 转发是一次请求,可以使用request对象来共享数据
-
路径写法
- 相对路径
- 不以/开头以.开头 如.index/html
- 规则:找到当前资源和目标资源之间的相对位置关系
- ./:当前目录
- …/:后退一级目录
- 绝对路径
- 以/开头的路径 如http://localhost/day/sldfjk
- 规则:判断定义的路径是给谁用
- 给客户端浏览器使用:需要加虚拟目录
- 动态获取虚拟目录:request.getContextPath()
- 给服务器使用:不需要加虚拟目录
- 转发路径
- 给客户端浏览器使用:需要加虚拟目录
- 相对路径
-
-
服务器输出字符数据到浏览器
-
//或者简单的设置编码----解决乱码问题 resp.setContentType("text/html;charset=utf-8"); //获取字符输出流 PrintWriter pw = resp.getWriter(); //输出数据 pw.write("你好呀 abc");
-
乱码问题
- PrintWriter pw = resp.getWriter();获取的流默认编码是ISO-8859-1
- 设置该流的默认编码
- 告诉浏览器相应体使用的编码
-
-
服务器输出字节数据到浏览器
-
//或者简单的设置编码----解决乱码问题 resp.setContentType("text/html;charset=utf-8"); //获取字符输出流 PrintWriter pw = resp.getWriter(); pw.write("你好".getBytes("utf-8"));//利用getBytes方法返回字节数组
-
-
验证码:
ServletContext对象
概念:
HTTP协议
1.请求消息
超文本传输协议
定义了客户端和服务器端
特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求/相应模型的:一次请求对应一次相应
- 无状态的:每次请求之间相互独立,不能交互数据
请求消息数据格式
- 请求行
- 请求方式 请求url 请求协议/版本
GET /login.html HTTP/1.1 - 请求方式:HTTP协议有7种请求方式,常用两种
- GET:参数在请求行中,URL后 请求的URL有长度限制 不安全
- POST:参数在请求体中 请求的URL没有长度限制 相对安全
- 请求方式 请求url 请求协议/版本
- 请求头:客户端浏览器告诉服务器一些信息
- 请求头名称:请求头值
- User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
- 在服务器端获取该头的信息,解决浏览器的兼容性问题
- Referer:http://localhost/…
- 告诉服务器,我(当前请求)从哪里来?
- 作用:
- 防盗链
- 统计工作
- User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
- 请求头名称:请求头值
- 请求空行(空格)
- 用于分割POST请求的请求头,和请求体的
- 请求体(正文)
- 封装POST请求消息的请求参数
字符串格式
Host: localhost:8080
sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
2.响应消息
服务器端发送给客户端的数据
数据格式:
- 相应行
- 组成:协议/版本 响应状态码 状态码描述
- 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
- 状态码都是3位数
- 分类:
- 1xx:服务器就受到客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码
- 2xx:成功 代表200
- 3xx:重定向:代表 302(重定向) 204(访问缓存)
- 4xx:客户端错误
- 404 没找到路径
- 405 请求方式没有对应的方法
- 5xx:服务器端错误 代表 500 服务器内部出现异常
- 响应头
- Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
- Content-disposition:服务器告诉客户端以什么格式打开响应体数据
- in-line:默认值,在当前页面打开
- attachment:filename=xxx:以附件形式打开响应体.文件下载
- 相应空行
- 响应体
- 显示出来的html页面
会话技术
- Cookie
- Session
- 会话:一次会话中包含多次请求和响应
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到一方断开为止
- 功能:再一次会话的范围内的多次请求,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务的会话技术:Session
1.Cookie
概念:客户端会话技术,将数据保存到客户端
快速入门:
- 创建Cookie对象,绑定数据
- new Cookie(String name,String value)
- 发送Cookie对象
- response.addCookie(Cookie cookie)
- 获取Cookie,拿到对象
- Cookie[] request.getCookies()
实现原理:基于响应头set-cookie和请求头cookie实现
cookie的细节:
- 一次可不可以发送多个Cookie
- 可以,创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可
- Cookie在浏览器中保存多长时间?
- 默认情况下,当浏览器关闭后Cookie数据被销毁
- 持久化存储
- setMaxage(int seconds)
- 正数:将Cookie数据写到硬盘的文件中.持久化存储,Cookie存活时间
- 负数:默认值.浏览器关闭后数据清除
- 零:删除Cookie信息
- setMaxage(int seconds)
- Cookie能不能存中文?
- tomcat8之后支持中文,之前不支持中文
- Cookie共享问题?
- 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 默认情况下cookie不能共享
- setPath(String path):设置cookie 的获取范围.默认情况下,设置当前的虚拟目录
- 如果要共享,则可以将path设置为“/”
- 不同的tomcat服务器间cookie共享问题?
- setDomain(String path):如果设置一级域名相同,那么多个服务器之间Cookie可以共享
- setDomain(“.baidu.com”),那么tieba.baidu.com和news.baidu.com中cookie可以共享
- setDomain(String path):如果设置一级域名相同,那么多个服务器之间Cookie可以共享
- 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- Cookie的特点和作用
- cookie存储数据在客户端浏览器
- 浏览器对于单个cookie的大小有限制(4kb) 以及 对同一个域名下的总cookie的数量有有限制
- 作用:
- cookie一般用于存出少量的不太敏感的数据
- 在不登录的情况下,完成服务器对客户端的身份识别
- ==案例:==记住上一次访问的时间
- 需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:时间字符串
- 分析
- 可以用cookie来实现
- 在服务器中的Servlet判断是否有一个名为LastTime的cookie
- 有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:…
- 写回cookie:lastTime = …
- 没有:是第一次访问
- 响应数据:您好,欢迎首次访问
- 写回cookie lastime :…
- 有:不是第一次访问
- 需求:
2.Session
-
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中.HttpSession
-
快速入门:
- 获取HttpSession对象
1.HttpSession session = request.getSession();- 使用HttpSession对象:
3.Object getAttribute(String name)
2.void setAttribute(String name,Object value)
void removeAttribute(String name)
- 使用HttpSession对象:
- 获取HttpSession对象
-
原理:Session的实现依赖于Cookie,通过请求头来辨别要找的Session对象
-
细节
-
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
- 默认情况下不是
- 如需要相同,则可以创建Cookie,键为Jsessionid,设置最大存活时间,让cookie持久化保存
cookie c = new cookie(“Jsessionid”,session.getId())
c.setMaxAge(60*60)
resp.addCookie©
-
客户端不关闭,服务器关闭后,两次获取的session是同一个吗
- 不是同一个,但要确保数据不丢失。tomcat自动完成以下工作
- session的钝化:服务器正常关闭之前,将session对象序列化到硬盘上
- session的活化:服务器启动后,将session文件转化为内存中的session对象即可
- 不是同一个,但要确保数据不丢失。tomcat自动完成以下工作
-
session什么时候被销毁?
-
服务器关闭
-
session对象调用invalidate();
-
session默认失效时间 30分钟
选择性配置修改<session-config> <session-timeout>30</session-timeout> </session-config>
-
-
-
session的特点
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型数据,任意大小数据
-
session和cookie的区别
- session存储数据在服务器端,Cookie在客户端
- session存储没有数据大小限制,Cookie有
- session数据安全,Cookie相对于不安全
验证码案例
需求:
- 访问带有验证码的登录页面login.jsp
- 用户输入用户名,密码以及验证码
- 如果用户名和验证码输入有误,跳转登录页面,提示:用户名或密码错误
- 如果验证码输入有误,跳转登录页面,提示:验证码错误
- 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
- 分析:
JSP
-
概念:java server pages java服务器端页面
- 可以理解为一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
- 用于简化书写!!!
-
原理:
- 本质上就是一个Servlet——源码中实现了HTTPServlet,并有一个JSPservice方法
-
JSP脚本:定义java代码的方式
- <% java代码 %>z 在Service方法中。service方法中可以定义什么,该脚本就可以定义什么 类似局部变量
- <%!java代码 %> 定义的Java代码在JSP转换后的java类的成员位置 类似全局变量
- <% = java代码 %> = 定义的java代码会输出到页面上,输出语句中可以定义什么,该脚本中就可以定义什么
-
JSP的内置对象
- 在jsp页面中不需要获取和创建,可以直接使用的对象
- jsp一共有9个内置对象
- request
- response
- out:字符输出流对象,可以将数据输出到页面上,和response.getWriter()类似
- 在这里插入图片描述
-
指令
- 作用:用于配置JSP页面,导入资源文件
- 格式:<%@ 指令名称 属性名1 = 属性值1 属性名2 = 属性名2 … %>
- 分类:
- page :配置JSP页面
- include :页面包含的.导入页面的资源文件
- taglib : 导入资源
-
注释
- <%–> 注释内容 <–%>
MVC开发模式
- MVC:
- Model,模型.javaBean 完成具体的业务操作,如:查询数据库,封装对象
- View,视图.JSP 展示数据
- Controller,控制器.Servlet 获取用户的输入、调用模型、将数据交给视图进行处理
- 优点:
- 耦合性低,方便维护,利于分工协作
- 复用性高
- 缺点:使项目结构变的复杂,对开发人员要求高
EL表达式
-
概念:Expression Language 表达式语言
-
作用:替换和简化jsp页面中java代码的编写
-
语法:${表达式}
-
注意:jsp默认支持el表达式。如果想要忽略el表达式
- 设置jsp中page指令:isElignored=“true” 忽略当前jsp页面中所有的el表达式
- ${表达式}: 忽略当前这个el表达式
-
使用:
使用步骤: -
将想要发给前端的数据存入. request session中 (常用)
-
转发至前端页面
-
在前端jsp页面中${数据名}使用
request.setAttribute("brands",brands);
request.getRequestDispatcher("xxx.jsp").forword(request,response);
日期格式化
http://c.biancheng.net/view/878.html
Filter
Ajax
Ajax是一种无需重新加载整个网页的情况下,能够更新部分网页的技术,传统的网页,如果需要更新内容,必须重新加载整个网页页面
作用:
- 与服务器进行数据交换:通过ajax可以给服务器发送请求,并获取服务器响应的数据
- 使用了ajax和服务器进行通信,就可以使用html+ajax来替换jsp页面了
- 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术
原生代码实现(了解)
Jquery代码实现
---------------使用$.ajax()发送异步请求---------------------
<script>
function fun(){
//使用$.ajax()发送异步请求
$.ajax({
url:"ajaxServlet", //请求路径
type:"POST", //默认是GET
//请求参数,键值对形式——JSON对象
data:{
"username":"jack","age":23},
//相应成功后的回调函数
success:function(data) {
alert(data)
},
error:function(){
alert("出错了...")
},
//设置接受到的相应数据的格式
dataType:"text"
});
}
</script>
------------------------使用$.get发送请求----------------------
$.get(url,[data],[callback],[type])
url:请求路径
data;请求参数
callback:回调函数
type:响应结果的类型
原生代码实现ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="css/register.css" rel="stylesheet">
</head>
<body>
<div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="login.html">登录</a>
</div>
<form id="reg-form" action="#" method="get">
<table>
<tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名已存在</span>
</td>
</tr>
<tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr>
<tr>
<td>验证码</td>
<td class="inputs">
<input name="checkCode" type="text" id="checkCode">
<img src="imgs/a.jpg">
<a href="#" id="changeImg">看不清?</a>
</td>
</tr>
</table>
<div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form>
</div>
-----------------------------------案例实现--------------------------------------
<script>
//1.给用户名输入框绑定失去焦点的事件
document.getElementById("username").onblur = function () {
//获取用户名的值
var username = this.value;
//2发送ajax请求
//21.创建ajax对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.2发送请求 路径写全路径,便于前后端分工协作 全路径:浏览器打开ajaxServlet接口的路径
xhttp.open("GET", "http://localhost:8080/Brand_demo/selectUserServlet?username=" + username);
xhttp.send();
//2.3获取响应
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// alert(this.responseText);
//字符串判断,如果文本是true则说明用户名存在...
if (this.responseText == "true") {
//用户名存在 显示提示信息 将显示信息的display属性设置一下
document.getElementById("username_err").style.display = 'block';
} else {
//不存在 清除提示信息
document.getElementById("username_err").style.display = 'none';
}
}
};
}
</script>
</body>
</html>
后端代码
package com.crz.web;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/selectUserServlet")
public class selectUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("GET...");
//1.接收用户名
String username = request.getParameter("username");
//2.调用service查询user对象
boolean flag = true;
//3.响应样式
response.getWriter().write("" + flag);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Post...");
this.doGet(request, response);
}
}
axios框架实现ajax
快速入门
-
引入axios 的js文件
-
使用axios发送请求,并获取响应结果
axios({ method:"get", url:"http://localhost:8080/Brand_demo/selectUserServlet?username=xxxx" }).then(function(resp){ alert(resp.data); })
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="js/axios-0.18.0.js"></script>
<script>
//1.get
// axios({
// method:"get",
// url:"http://localhost:8080/Brand_demo/axiosServlet?username=123"
// }).then(function (resp){
// alert(resp.data);
// })
//post
axios({
method: "post",
url: "http://localhost:8080/Brand_demo/axiosServlet",
data: "username=123"
}).then(function (resp) {
alert(resp.data);
})
</script>
</body>
</html>
利用别名进一步简化代码
JSON
Fastjson是阿里巴巴提供的一个java语言编写的高性能功能完善的JSON库,是目前java语言中最快的JSON库,可以实现java对象和JSON字符串的相互转换
使用:
-
导入坐标
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.13</version> </dependency>
-
java对象转JSON
String jsonString = JSON.toJSONString(user);
-
JSON字符串转java对象
User u = JSON.parseObject("{\"id\":1,\"password\":\"123\",\"username\":\"zhangsan\"}", User.class);
Mybatis
1.什么是Mybatis
- 一款优秀的持久层框架,用于简化JDBC开发
持久层
- 负责将数据dao保存到数据库的那一层代码
- javaEE三层架构:表现层、业务层、持久层
应用:
查询user表中所有数据
-
创建user表,添加数据
-
创建模块,导入坐标
-
编写mybatis核心配置文件 --> 替换连接信息 解决硬编码问题
-
<environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!-- 数据库的连接信息--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment>
-
-
编写SQL映射文件 --> 统一管理sql语句,解决硬编码问题
-
编码
-
定义pojo类
-
加载核心配置文件,获取SqlSessionFactory
-
//1.加载mybatis的核心配置文件 获取SqlSessionFactory 路径就是resources中的mybatis-config.xml String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
-
-
获取SqlSession对象,执行sql语句
-
//2.获取SqlSessionFactory对象,用它执行sql SqlSession sqlSession = sqlSessionFactory.openSession(); //3.1获取UserMapper接口的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> users = userMapper.selectAll(); System.out.println(users);
-
-
释放资源
-
sqlSession.close();
-
-
2.Mapper代理开发
目的:
- 解决原生方式中的硬编码
- 简化后期执行SQL
步骤:
- 定义与SQL映射文件同名的Mapper接口,并将Mapper接口和映射文件放置在同一目录下
- 在resources文件中创建一个和mapper相同的目录,命名:
com/crz/mapper
- 在resources文件中创建一个和mapper相同的目录,命名:
- 设置SQL映射文件的namespace属性为Mapper接口全限定名
- 在Mapper接口中定义方法,方法名就是SQL映射文件中SQL语句的id,并保持参数类型和返回值类型一致
- 编码
- 通过SqlSession的getMapper方法获取Mapper接口的代理对象
- 调用对应的方法完成sql的执行
细节:如果Mapper接口名称和SQL映射文件名称相同,在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载
Mybatis完成操作需要几步:
-
编写接口方法
-
mapper文件中的xxxMapper接口
-
package com.crz.mapper; import com.crz.pojo.Brand; import java.util.List; /** * 查询所有 */ public interface BrandMapper { public List<Brand> selectAll(); }
-
-
编写SQL
-
xml文件
-
<?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"> <!-- namespace:名称空间 --> <mapper namespace="com.crz.mapper.BrandMapper"> <select id="selectAll" resultType="com.crz.pojo.Brand"> select * from tb_brand; </select> </mapper>
-
-
执行方法
-
package com.crz.test; import com.crz.mapper.BrandMapper; import com.crz.pojo.Brand; 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 org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MyBatisTest { @Test public void testSelectAll() throws IOException { //1.获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取sqlSessionFactory对象参数true(自动提交事务)false(手动提交事务) SqlSession sqlSession = sqlSessionFactory.openSession(); //3.获取Mapepr接口的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //4.执行方法 List<Brand> brands = brandMapper.selectAll(); System.out.println(brands); //5.释放资源 sqlSession.close(); } }
-
3.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>
<!-- 简化mapper文件中的resultType 设置完后默认user类名就可以使用,不分辨大小写-->
<typeAliases>
<package name="com.crz.pojo.User"/>
</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:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<!-- 映射源文件 加载sql映射文件-->
<mappers>
<!-- 加载sql映射文件-->
<!-- <mapper resource="com/crz/mapper/UserMapper.xml"/>-->
<!-- Mapper代理方式 简化代码,只用一行就能扫描吗mapper包下文件所有的mapper.xml文件,适用于mapper.xml多的情况下使用 -->
<package name="com.crz.mapper"/>
</mappers>
</configuration>
4.配置文件完成增删改查
一.查:
1.查所有
select * from 表名;
2.查看详情
思路:点击查看详情时跳转到当前点击的品牌详情展示页面——>通过id查找到点击项,然后返回一个Brand对象
3.多条件查询
思路分析:查询当前状态–设置一个status变量,如果0是一种状态,1是另一种…,查询企业名称,利用like模糊查询,数据库中内容在输入框中出现即可,品牌名称,同上,因为是多条件查询,所以需要用and来进行连接
4.多条件动态查询
根据上面提到的多条件查询,用户不一定必须把每个查询条件都输入,可能只通过某一项进行查找。SQL语句随着用户输入数据的变化而变化
5.单条件动态查询
二.添加
1.添加品牌
2.添加 主键返回
需要添加useGeneratedKeys=“true” keyProperty="id"两个参数
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into tb_brand (brandName, companyName, ordered, description, status)
values (#{
brandName}, #{
companyName}, #{
ordered}, #{
description}, #{
status});
</insert>
三.修改
1.修改全部字段
2.修改动态字段
<update id="update">
update tb_brand
<set>
<if test="brandName != null and brandName != ''">
brandName = #{brandName},
</if>
<if test="companyName != null and companyName != ''">
companyName = #{companyName},
</if>
<if test="ordered != null and ordered != ''">
ordered = #{ordered},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="status != null">
status = #{status}
</if>
</set>
where id = ${id};
</update>
四.删除
思路:点击删除时获取当前的品牌id,然后将后台id对应的数据删除 逻辑删除:更改状态
1.删除一个
获取到点击删除按钮品牌的id,然后将id对应的品牌删除–>执行删除SQL语句
2.批量删除
将选中的序号封装进一个id数组,一次性接收后进行遍历,根据每个序列号的id进行批量删除
5.注解完成增删改查
特殊字符处理
例如想要实现 select * from tb_brand where id < #{id}; 此时<无法被识别
解决方案: 1.转义字符: < (小于号)
2.CDATA区: <![CDATA[ 需要转义的内容 ]]> 输入CD自动生成
Mybatis参数传递
Mybatis接口方法中可以接收各种各样的参数,Mybatis底层对于这些参数进行不同的封装处理方式
- 单个参数
- POJO类型:可以直接使用 保证属性名 和 对应的参数占位符名称一致
- Map集合:可以直接使用,键名 和 参数占位符名称一致
- Collection:封装为Map集合
- map.put(“arg0”,collection集合);
- map.put(“collection”,collection集合);
- List:封装为Map集合
- map.put(“arg0”,collection集合);
- map.put(“collection”,List集合);
- map.put(“List”,List集合);
- Array:封装为Map集合
- map.put(“arg0”,数组);
- map.put(“array”,数组);
- 其他类型
- 多个参数:
Mybatis提供了ParamNameResolver类来进行参数封装
例如上面的username和password两个参数,没有添加注解之前各自有两个默认的参数名:arg0 param1, arg1 param2
因此可以使用@param注解来更改变量名称
JSTL
在jsp页面中替换java代码—if for
导入坐标:
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId> standard</artifactId>
<version>1.1.2</version>
</dependency>
MVC架构
一种分层开发的模式
- M:Model,业务模型,处理业务
- V:View,视图,界面展示
- C:Controller,控制器,处理请求,调用模型和视图
好处:
- 指责单一互不影响
- 有利于分工协作
- 有利于组件重用
三层架构
项目配置(resources)+功能总结
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>Brand_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- jstl-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- standard-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build>
</project>
环境配置
-----------------BrandMapepr.xml-------------------
<?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">
<!--
namespace:名称空间
-->
<mapper namespace="com.crz.mapper.BrandMapper">
</mapper>
---------------------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>
<!-- 简化mapper文件中的resultType 设置完后默认user类名就可以使用,不分辨大小写-->
<typeAliases>
<!-- 设置别名 -->
<!-- <typeAlias alias="brand" type="com.crz.pojo.Brand"/>-->
<package name="com.crz.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:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<!-- 加载sql映射文件-->
<mappers>
<!-- 加载sql映射文件-->
<!-- <mapper resource="com/crz/mapper/UserMapper.xml"/>-->
<!-- Mapper代理方式 简化代码,只用一行就能扫描吗mapper包下文件所有的mapper.xml文件,适用于mapper.xml多的情况下使用 -->
<package name="com.crz.mapper"/>
</mappers>
</configuration>
查找功能
-
创建Mapper映射的xml文件
-
<?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"> <!-- namespace:名称空间 --> <mapper namespace="com.crz.mapper.BrandMapper"> </mapper>
-
-
写Mapper接口,实现查找所有的方法(注解)
-
引入SqlSessionFactoryUtils工具类
-
package com.crz.util; import org.apache.ibatis.io.Resources; 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 inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } }
-
-
编写Service,执行selectAll方法,获得结果集
-
package com.crz.service; import com.crz.mapper.BrandMapper; import com.crz.pojo.Brand; import com.crz.util.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.util.List; public class BrandService { SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory(); /** * 查询所有 * @return */ public List<Brand> selectAll() { //调用BrandMapper.selected //2.获取SqlSession SqlSession sqlSession = factory.openSession(); //3.获取BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); //4.调用方法 List<Brand> brands = mapper.selectedAll(); sqlSession.close(); return brands; } }
-
-
SelectAllServlet接口实现前后端数据交互(Servlet可以优化),将数据存入request域中传递给前端界面
-
package com.crz.web; import com.crz.pojo.Brand; import com.crz.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.util.List; @WebServlet("/selectAllServlet") public class selectAllServlet extends HttpServlet { BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.调用BrandService完成查询 执行sql语句后返回一个brand对象 List<Brand> brands = service.selectAll(); //2.存入request域中 request.setAttribute("brands", brands); //3.转发到brand.jsp中 request.getRequestDispatcher("/brand.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
-
前端页面获取request中的内容,并将数据显示
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0" width="80%"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="status"> <tr align="center"> <td>${status.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:if test="${brand.status == 1}"> <td>禁用</td> </c:if> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> <hr> <c:forEach begin="1" end="10" step="1" var="i"> <a href="#">${i}</a> </c:forEach> </body> </html>
-
添加功能
-
通过Mapper接口在Mapper.xml文件中生成sql语句 void add(Brand brand);
-
写添加语句 insert into…语句
-
brandService中实现添加语句方法 注意需要提交事务
-
public void add(Brand brand){ SqlSession sqlSession = factory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); mapper.add(brand); //提交事务 增删改需要提交事务,将处理过的数据重新上传 sqlSession.commit(); //释放资源 sqlSession.close(); }
-
-
在brand.jsp页面中点击添加信息后,跳转至addBrand.jsp页面,此页面是一个表单,收集添加品牌的各种信息,最后将表单中信息提交至addServlet进行处理
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>添加品牌</title> </head> <body> <h3>添加品牌</h3> <form action="/Brand_demo/addServlet" method="post"> 品牌名称:<input name="brandName"><br> 企业名称:<input name="companyName"><br> 排序:<input name="ordered"><br> 描述信息:<textarea rows="5" cols="20" name="description"></textarea><br> 状态: <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1">启用<br> <input type="submit" value="提交"> </form> </body> </html>
-
-
addServlet处理表单内容–>将表单提交过来的信息封装成一个brand对象,并重新转发到查询所有,以更新添加后的最新后台数据
-
package com.crz.web; import com.crz.pojo.Brand; import com.crz.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/addServlet") // 关键部分 public class addServlet extends HttpServlet { BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理中文乱码问题 request.setCharacterEncoding("utf-8"); Brand brand = new Brand(); //1.接收表单提交的数据,封装成一个brand对象 String brandName = request.getParameter("brandName"); String companyName = request.getParameter("companyName"); String ordered = request.getParameter("ordered"); String description = request.getParameter("description"); String status = request.getParameter("status"); //2.封装数据 brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.valueOf(ordered)); brand.setDescription(description); brand.setStatus(Integer.valueOf(status)); //3.调用方法 完成添加 service.add(brand); //4.转发到查询所有 request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
修改功能
-
用户点击修改连接后,转到修改品牌的页面,并将当前的品牌信息回显在页面中
点击修改链接后,跳转到selectByIdServlet接口,通过当前点击修改品牌的id找到这个对象package com.crz.web; import com.crz.pojo.Brand; import com.crz.service.BrandService; import javax.servlet.ServletException; 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("/updateServlet") public class updateServlet extends HttpServlet { BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理中文乱码问题 request.setCharacterEncoding("utf-8"); Brand brand = new Brand(); //1.接收表单提交的数据,封装成一个brand对象 String id = request.getParameter("id"); String brandName = request.getParameter("brandName"); String companyName = request.getParameter("companyName"); String ordered = request.getParameter("ordered"); String description = request.getParameter("description"); String status = request.getParameter("status"); //2.封装数据 brand.setId(Integer.valueOf(id)); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.valueOf(ordered)); brand.setDescription(description); brand.setStatus(Integer.valueOf(status)); //3.调用方法 完成添加 service.update(brand); //4.转发到查询所有 request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
-
通过id找到的对象,发送到前端jsp中,回显在页面中,因为要知道修改那一个对象,因此需要获取到对应品牌的id值,这里需要用隐藏域将id值保存以便于后台接收.点击提交后将数据传给updateServlet进行处理
<form action="/Brand_demo/updateServlet" method="post"> <%-- 隐藏域 用与保存id,方便修改信息时id读取--%> <input type="hidden" name="id" value="${brand.id}"> 品牌名称:<input name="brandName" value="${brand.brandName}"><br> 企业名称:<input name="companyName" value="${brand.companyName}"><br> 排序:<input name="ordered" value="${brand.ordered}"><br> 描述信息:<textarea rows="5" cols="20" name="description">${ brand.description}</textarea><br> 状态: <c:if test="${brand.status == 0}"> <input type="radio" name="status" value="0" checked>禁用 <input type="radio" name="status" value="1">启用<br> </c:if> <c:if test="${brand.status == 1}"> <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1" checked>启用<br> </c:if> <input type="submit" value="提交"> </form>
-
-
对update.jsp中的值进行修改并返回给后端处理(和添加一样,方法名不一样)
- 写update接口 void update(Brand brand);并在映射文件中写sql语句
<update id="update"> update tb_brand <set> <if test="id != null"> id = #{id}, </if> <if test="brandName != null and brandName != ''"> brandName = #{brandName}, </if> <if test="companyName != null and companyName != ''"> companyName = #{companyName}, </if> <if test="ordered != null and ordered != ''"> ordered = #{ordered}, </if> <if test="description != null and description != ''"> description = #{description}, </if> <if test="status != null"> status = #{status} </if> </set> where id = ${id}; </update>
- 写update接口 void update(Brand brand);并在映射文件中写sql语句
-
Service层中实现update方法 与add相似
public void update(Brand brand) { SqlSession sqlSession = factory.openSession(); BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); mapper.update(brand); sqlSession.commit(); sqlSession.close(); }
-
updateServlet实现最后的更新和最新数据的显示,通过重新调用selectAllServlet接口将数据更新
package com.crz.web; import com.crz.pojo.Brand; import com.crz.service.BrandService; import javax.servlet.ServletException; 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("/updateServlet") public class updateServlet extends HttpServlet { BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理中文乱码问题 request.setCharacterEncoding("utf-8"); Brand brand = new Brand(); //1.接收表单提交的数据,封装成一个brand对象 String id = request.getParameter("id"); String brandName = request.getParameter("brandName"); String companyName = request.getParameter("companyName"); String ordered = request.getParameter("ordered"); String description = request.getParameter("description"); String status = request.getParameter("status"); //2.封装数据 brand.setId(Integer.valueOf(id)); brand.setBrandName(brandName); brand.setCompanyName(companyName); brand.setOrdered(Integer.valueOf(ordered)); brand.setDescription(description); brand.setStatus(Integer.valueOf(status)); //3.调用方法 完成添加 service.update(brand); //4.转发到查询所有 request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }