10、MVC三层架构
三层架构
Model View Controller 模型、视图、控制器
Model
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD (Dao)
View
- 展示数据
- 提供链接发起Servlet请求(a标签,form,img图片…)
Controller(Servlet)
接收用户请求(req:请求参数、Session信息…)
交给业务层处理对应的代码
控制视图跳转
1.登录--->接收用户登录请求--->处理用户请求--->(获取用户登录参数,username,password)--->交给业务层处理登录业务(判断用户名是否正确:例如事务的处理)--->Dao层查询用户名和密码是否正确--->数据库
Filter
Filter 过滤器开发步骤
- 导包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zoXMFNcJ-1658071484717)(img.png)] - 编写过滤器
package com.yuan.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就已经初始化了,随时等待过滤对象的出现
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncondingFilter初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
System.out.println("执行前");
//让我们的请求继续走,如果不写,程序到这就会停止
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("执行后");
}
//销毁,web服务器关闭的时候,过滤就会销毁
@Override
public void destroy() {
System.out.println("CharacterEncondingFilter销毁");
}
}
- 配置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.yuan</groupId>
<artifactId>Javaweb-Filter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!-- JSP依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- JSTL表达式依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- 连接数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
13、JDBC
13.1、数据库驱动
应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道,如下所示:
13.2、JDBC概述
JDBC(Java DataBase Connectivity) 称为Java数据库连接,它是一种用于数据库访问的应用程序API,由一组用Java语言编写的类和接口组成
JDBC连接不同的数据库只需要不同的数据库驱动包即可,不用担心其数据库操作语言的差异性。
13.3、编写JDBC程序
1、创建数据库表
mysql创建简单的数据表
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','123@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');
SELECT * FROM users;
2、导入数据库依赖
<!--mysql的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
3、查询User表中数据。
package com.yuan;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/people?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3、向数据库发送Sql的对象Statement:CRUD(C:就是创建(Create), R:就是查找(Retrieve), U:就是更改(Update), D:就是删除(Delete))
Statement statement = connection.createStatement();
//4、编写SQL
String sql="select * from users";
//5、执行查询sql,返回一个ResultSet;结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id="+rs.getObject("id"));
System.out.println("id="+rs.getObject("name"));
System.out.println("id="+rs.getObject("password"));
System.out.println("id="+rs.getObject("email"));
System.out.println("id="+rs.getObject("birthday"));
}
//关闭连接
rs.close();
statement.close();
connection.close();
}
}
4、采用预编译模式对数据进行插入。
其中注意主键不能重复
package com.yuan;
import javax.swing.*;
import java.sql.*;
public class TestJdbc2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/people?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3、编写SQL
String sql="insert into users(id, name, password, email, birthday) value (?,?,?,?,?)";
//4、预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4);
preparedStatement.setString(2,"学习Java");
preparedStatement.setString(3,"pasdeed");
preparedStatement.setString(4,"21313@dad.daas");
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
//5、执行查询sql,返回一个ResultSet;结果集
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入数据成功");
}
//关闭连接
preparedStatement.close();
connection.close();
}
}
Junit单元测试
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
简单实用
@Test注解只是在方法上有效,只要增加了这个注解方法,就可以运行
package com.yuan;
import org.junit.Test;
public class TestJDBC3 {
@Test
public void test(){
System.out.println("hello");
}
}
事务
事务指逻辑上的一组操作,要么全部成功,要么全部不成功。
ACID 原则:之前数据库说过。
当JDBC程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会自动向数据库提交事务。若想关闭这种默认提交方式,让多条SQL在一个事务中执行,可使用下列的 JDBC控制事务语句。
//开启事务(start transaction)
Connection.setAutoCommit(false);
//提交事务(commit)
Connection.commit();
//回滚事务(rollback)
Connection.rollback();
代码测试
创建账户表
/*创建账户表*/
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(40),
money DECIMAL(9,2)
);
/*插入测试数据*/
insert into account(name,money) values('A',1000);
insert into account(name,money) values('B',1000);
insert into account(name,money) values('C',1000);
1、模拟转账成功时的业务场景
package com.yuan;
import org.junit.Test;
import org.omg.PortableInterceptor.ServerRequestInfo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJDBC4 {
@Test
public void test() {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/people?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
Connection connection=null;
//1、加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
//2、连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
//3、通知数据库开启事务,false开启
connection.setAutoCommit(false);
String sql="update account set money=money-100 where name ='A'";
connection.prepareStatement(sql).executeUpdate();
//制造错误
// int i=1/0;
String sql2="update account set money=money+100 where name ='B'";
connection.prepareStatement(sql2).executeUpdate();
//执行以上两条sql都执行成功了,就提交事务!
connection.commit();
System.out.println("success");
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2、模拟转账过程中出现异常导致有一部分SQL执行失败后让数据库自动回滚事务。
package com.yuan;
import org.junit.Test;
import org.omg.PortableInterceptor.ServerRequestInfo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJDBC4 {
@Test
public void test() {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/people?useUnicode=true&characterEncoding=utf-8";
String username="root";
String password="123456";
Connection connection=null;
//1、加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
//2、连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
//3、通知数据库开启事务,false开启
connection.setAutoCommit(false);
String sql="update account set money=money-100 where name ='A'";
connection.prepareStatement(sql).executeUpdate();
//制造错误
int i=1/0;
String sql2="update account set money=money+100 where name ='B'";
connection.prepareStatement(sql2).executeUpdate();
//执行以上两条sql都执行成功了,就提交事务!
connection.commit();
System.out.println("success");
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}