随堂笔记
约 3580 字大约 12 分钟
随堂笔记
1.复习
1.过滤器:对请求和响应进行过滤 接口javax.servlet.Filter
2.实现:
1)自定义类实现 接口javax.servlet.Filter
2)实现接口中的方法 doFilter(request,response,chain)
==>放行需要使用chain.doFilter(request,response);
不让访问资源,不书写代码chain.doFilter(request,response);
3)配置:
1.web.xml
2.注解 @WebFilter("过滤资源路径")
3.路径:
1)精确匹配 /xxx
2)目录匹配: /xxx/*
3)后缀名匹配: *.xx 不能加/
4)过滤所有: /*
4.生命周期:启动tomcat创建过滤器对象调用init初始化方法,每次访问被过滤的资源都要执行doFilter(request,response,chain) 。关闭tomcat想,销毁对象之前使用对象调用destroy方法
5.监听器:监听webs三大域对象(ServletContext HttpSession HttpServletRequest)的创建销毁以及属性变化的
6.fastjson:将java对象转换为json字符串,还可以将前端提交的json数据封装到java对象中
1)导入依赖
2)常见API:
1.String s = JSON.toJsonString(Object obj); 将java对象转换为json字符串
2.Object obj = JSON.parseObject(字节流/字符串,Class clazz);
User u=JSON.parseObject(request.getInputStream(),User.class);*****
BufferedReader br = request.getReader();获取关联浏览器的字符输入流
String line = br.readLine();
User u= JSON.parseObject(字符串,User.class);
2.用户角色权限管理系统的环境搭建
【1】导入后端项目
将后端项目导入到idea中之后修改maven仓库地址:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima.sh.heima141</groupId>
<artifactId>day09_maven-user_role_per_manager</artifactId>
<version>1.0-SNAPSHOT</version>
<name>day09_maven-user_role_per_manager</name>
<packaging>war</packaging>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<!--
servlet-api 用于编译
-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!--
junit测试框架
-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--fastjson:json数据和java对象之间的转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
<scope>runtime</scope>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--logback日志包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</project>
jdbc.properties
【2】导入前端项目
1.在vscode中切换终端目录到你的项目所在的路径位置
2.安装依赖
3.启动项目
【3】数据表关系
use day19_heima153;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT, -- 用户编号
`username` varchar(32) DEFAULT NULL, -- 用户名字
`password` varchar(32) DEFAULT NULL, -- 用户密码
`remark` varchar(32) DEFAULT NULL, -- 用户备注
`email` varchar(32) DEFAULT NULL, -- 用户邮箱
`createTime` timestamp not NULL DEFAULT CURRENT_TIMESTAMP, -- 该用户创建时间
`updateTime` timestamp not NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 该用户修改时间
PRIMARY KEY (`id`) -- 设置主键
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- timestamp 时间戳, 添加数据的时候createTime=null那么createTime = 系统当前时间 (年月日 时分秒)
-- updateTime 在你执行update语句,自动修改为修改的当前时间
-- 此语法在mysql8.0上是不兼容的可以修改成 `createTime` datetime
-- ----------------------------
-- Records of t_user
-- ----------------------------
insert into `t_user`(`id`,`username`,`password`,`remark`,`email`,`createTime`,`updateTime`) values (1,'admin','123',NULL,'admin@163.com','2021-06-22 09:09:43','2021-06-22 10:40:25'),(2,'张大三','123',NULL,'zhandasan@163.com','2021-06-22 09:09:43','2021-06-24 16:13:56'),(3,'李四四','123',NULL,'lisisi@163.com','2021-06-22 14:05:12','2021-06-24 16:14:34'),(4,'wangwu','123',NULL,'wangwu@163.com','2021-06-22 14:05:12','2021-06-22 14:05:12'),(5,'wangwu','123',NULL,'wangwu@163.com','2021-06-22 14:05:12','2021-06-22 14:05:12'),(6,'wangwu','123',NULL,'wangwu@163.com','2021-06-22 14:05:12','2021-06-22 14:05:12'),(7,'wangwu','123',NULL,'wangwu@163.com','2021-06-22 14:05:12','2021-06-22 14:05:12');
# 角色表
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT, -- 角色id
`name` varchar(32) DEFAULT NULL, -- 角色名字
`keyword` varchar(64) DEFAULT NULL, -- 角色关键字
`description` varchar(128) DEFAULT NULL, -- 角色描述
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理员', 'ROLE_ADMIN', '这是管理员')
,('2', '会员', 'ROLE_MEMBER', '这是会员')
,('3', '游客', 'ROLE_VISITOR', '这是游客');
# 权限表
CREATE TABLE `t_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT, -- 权限编号
`name` varchar(32) DEFAULT NULL, -- 权限名字
`keyword` varchar(64) DEFAULT NULL, -- 权限关键字
`description` varchar(128) DEFAULT NULL, -- 权限描述
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', '新增', 'ITEM_ADD', '这是新增权限')
,('2', '删除', 'ITEM_DELETE', '这是删除权限')
,('3', '编辑', 'ITEM_EDIT', '这是编辑权限')
,('4', '查询', 'ITEM_QUERY', '这是查询权限');
# 用户角色中间表
CREATE TABLE `t_user_role` (
`user_id` int(11) NOT NULL,
`role_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`role_id`),
KEY `FK_Reference_8` (`role_id`),
CONSTRAINT `FK_Reference_7` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 联合主键
-- 1. 一张表只能有一个主键 (唯一标识)
-- 2. 一个主键可以多个字段 (联合主键)
-- 2.1 class=316 班级号
-- 2.2 number=5 座位号
-- 2.3 以上任一字段都无法确定一个同学, 两者合在一起就可以唯一确定一位同学(联合主键)
-- ----------------------------
-- Records of t_user_role
-- ----------------------------
insert into `t_user_role`(`user_id`,`role_id`) values (1,1),(3,1),(4,1),(5,1),(2,2),(3,2),(4,2),(2,3),(4,3),(6,3),(7,3);
# 角色权限中间表
CREATE TABLE `t_role_permission` (
`role_id` int(11) NOT NULL,
`permission_id` int(11) NOT NULL,
PRIMARY KEY (`role_id`,`permission_id`),
KEY `FK_Reference_12` (`permission_id`),
CONSTRAINT `FK_Reference_11` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`),
CONSTRAINT `FK_Reference_12` FOREIGN KEY (`permission_id`) REFERENCES `t_permission` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
insert into `t_role_permission`(`role_id`,`permission_id`) values (1,1),(1,2),(1,3),(2,3),(1,4),(2,4),(3,4);
3.BaseServlet编写 掌握 课下完成
【1】代码实现1
package com.itheima.case2.web;
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.lang.reflect.Method;
/*
TODO:
1. /user/* 表示目录匹配,在前端输入的路径只要以/user开始都会访问当前User1Servlet
前端访问后端的路径:
http://localhost:8080/user/findAll 表示查询所有用户
http://localhost:8080/user/update 表示更新用户
http://localhost:8080/user/add 表示添加用户
我们在后端向知道用户即前端执行哪个功能就是根据请求资源路径最后一级目录判断的,因此我们需要获取请求资源
路径的最后一级目录:
findAll 表示查询所有用户
update 表示更新用户
add 表示添加用户
*/
@WebServlet("/user/*")
public class User1Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求资源路径
String uri = request.getRequestURI();// /user/findAll /user/update
//2.获取uri表示的最后一个/的索引
int lastIndex = uri.lastIndexOf("/");
//3.根据上述获取的最后一个/的索引截取最后/下个字符一直到字符串末尾 findAll update
//参数lastIndex + 1==》这里+1的原因是我们向截取最后一个/的下哥字符开始一直到字符串uri的末尾
String methodName = uri.substring(lastIndex + 1);
//System.out.println("methodName = " + methodName);// findAll update
//4.判断要执行哪个方法
/*if("findAll".equals(methodName)){
//说明是查询所有用户功能
findAll(request,response);
}else if("update".equals(methodName)){
//说明是更新用户功能
update(request,response);
}else if("add".equals(methodName)){
//说明是添加用户功能
add(request,response);
}else if("delete".equals(methodName)){
//说明是删除用户功能
delete(request,response);
}*/
/////////////////////////////////////////////////////////////////////////////////////
//TODO:使用反射执行上述过多if语句问题
try {
//1.获取当前类的Class对象
//TODO:这里的this表示当前类的对象即User1Servlet类的对象
Class<?> clazz = this.getClass();
//2.获取要执行的方法
/*
public Method getMethod(String name, Class<?>... parameterTypes)
参数:
name:方法名 delete add update findAll
parameterTypes:要执行方法的形参Class类型
*/
//methodName = 方法名 delete add update findAll
Method m = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//3.执行方法
/*
Methhod类中的方法:执行方法
public Object invoke(Object obj, Object... args)
参数:
obj:要执行方法依赖的对象,delete方法依赖对象是User1Servlet对象即this
args:要执行方法的实参 request response
返回值:Object 表示要执行方法的返回值,如果执行方法没有返回值这里是null
*/
m.invoke(this,request,response);
} catch (Exception e) {
e.printStackTrace();
}
}
public void delete(HttpServletRequest request, HttpServletResponse response) {
System.out.println("删除用户");
}
public void add(HttpServletRequest request, HttpServletResponse response) {
System.out.println("添加用户");
}
public void update(HttpServletRequest request, HttpServletResponse response) {
System.out.println("更新用户");
}
public void findAll(HttpServletRequest request, HttpServletResponse response) {
System.out.println("查询所有用户");
}
}
【2】最后代码
package com.itheima.case2.web;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
TODO:
以后在创建Servlet我们只需要继承 BaseServlet,而BaseServlet继承了HttpServlet,因此
UserServlet属于Servlet类
*/
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
public void delete(HttpServletRequest request, HttpServletResponse response) {
System.out.println("删除用户");
}
public void add(HttpServletRequest request, HttpServletResponse response) {
System.out.println("添加用户");
}
public void update(HttpServletRequest request, HttpServletResponse response) {
System.out.println("更新用户");
}
public void findAll(HttpServletRequest request, HttpServletResponse response) {
System.out.println("查询所有用户");
}
}
package com.itheima.case2.web;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
//TODO:不需要被访问,因此不要加路径
//@WebServlet("/BaseServlet")
public class BaseServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求资源路径
String uri = request.getRequestURI();// /user/findAll /user/update
//2.获取uri表示的最后一个/的索引
int lastIndex = uri.lastIndexOf("/");
//3.根据上述获取的最后一个/的索引截取最后/下个字符一直到字符串末尾 findAll update
//参数lastIndex + 1==》这里+1的原因是我们向截取最后一个/的下哥字符开始一直到字符串uri的末尾
String methodName = uri.substring(lastIndex + 1);
//TODO:使用反射执行上述过多if语句问题
try {
//4.获取当前类的Class对象
//TODO:这里的this表示当前类的对象即User1Servlet类的对象
Class<?> clazz = this.getClass();
//5.获取要执行的方法
//methodName = 方法名 delete add update findAll
Method m = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
//6.执行方法
m.invoke(this,request,response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.SpringIOC思想
package com.itheima.case2.web;
import com.itheima.case2.pojo.vo.PageResult;
import com.itheima.case2.pojo.vo.QueryPageBean;
import com.itheima.case2.pojo.vo.Result;
import com.itheima.case2.service.UserService;
import com.itheima.case2.utils.BaseController;
import com.itheima.case2.utils.BeansFactory;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
TODO:
以后在创建Servlet我们只需要继承 BaseServlet,而BaseServlet继承了HttpServlet,因此
UserServlet属于Servlet类
*/
@WebServlet("/user/*")
public class UserServlet extends BaseServlet {
public void delete(HttpServletRequest request, HttpServletResponse response) {
System.out.println("删除用户");
}
public void add(HttpServletRequest request, HttpServletResponse response) {
System.out.println("添加用户");
}
public void update(HttpServletRequest request, HttpServletResponse response) {
System.out.println("更新用户");
}
public void findAll(HttpServletRequest request, HttpServletResponse response) {
try {
//1.将前端提交的请求参数即当前页码和每页条数封装到实体类QueryPageBean对象中
QueryPageBean pb = BaseController.parseJSON2Object(request, QueryPageBean.class);
//2.创建业务层对象
/*
TODO:
1.问题:我们以前创建对象都是通过newc创建对象,例如创建业务层对象:
new UserServiceImpl();
这种方式创建对象的弊端是:严重耦合。如果业务层实现类UserServiceImpl被删除了,web报错。或者我们实际开发中
向对业务层进行扩展,一般是定义一个新的业务层类UserServiceImpl2,然后将之前的UserServiceImpl替换。就造成
web层无法运行,那么太过于耦合。
2.解决问题:降低耦合。就是不在web层类中使用new方式创建对象。
使用:反射+面向接口编程+读取配置文件+工厂设计模式等方式取代new创建对象
*/
// UserServiceImpl userService = new UserServiceImpl();
//实现左边解耦合了,如果扩展实现类只需要修改等号右边
// UserService userService = new UserServiceImpl();
// //使用反射+读取配置文件创建对象
// ResourceBundle bundle = ResourceBundle.getBundle("beans");//参数beans表示要关联的配置文件的名字,不能书写后缀名
// //根据配置文件的key获取值
// //userService=com.itheima.case2.service.impl.UserServiceImpl
// String classNameStr = bundle.getString("userService");//"com.itheima.case2.service.impl.UserServiceImpl"
// //使用反射创建对象
// Class<?> clazz = Class.forName(classNameStr);
// UserService userService = (UserService) clazz.newInstance();//调用UserServiceImpl类的无参构造方法
//TODO:从SpringIOC的工厂中获取UserServiceImpl类的对象
UserService userService = BeansFactory.getInstance("userService");
UserService userService1 = BeansFactory.getInstance("userService");
UserService userService2 = BeansFactory.getInstance("userService");
//3.使用对象调用方法
PageResult pageResult = userService.findAll(pb);
//4.创建Result对象
Result result = new Result(true, "查询用户成功", pageResult);
//5.将result转换为json之后响应给前端
BaseController.printResult(response,result);
} catch (Exception e) {
//打印到控制台
e.printStackTrace();
try {
//响应给浏览器
//6.创建Result对象
Result result = new Result(false, "查询用户失败");
//7.将result转换为json之后响应给前端
BaseController.printResult(response,result);
} catch (Exception ioException) {
ioException.printStackTrace();
}
}
}
}
工厂类
package com.itheima.case2.utils;
import java.util.HashMap;
import java.util.ResourceBundle;
/*
TODO:当前工厂类的作用就是创建对象的
回顾:
一个类对象:
1)单例 单个对象
2)多例 多个对象
我们这里实现产生的对象是单例 userService=com.itheima.case2.service.impl.UserServiceImpl
1.创建一个Map集合: new HashMap<String,Object>();
2.Map集合的key:例如配置文件等号左边的标识userService roleService
3.Map集合的value:就是创建的对象UserServiceImpl 类的对象 RoleServiceImpl类的对象
4.实现步骤:
1)创建map集合存储创建的对象
2)定义静态方法创建具体类的对象
3)在静态方法中判断map集合的key是否有值,如果没有值,说明第一创建对象
4)直接使用反射+读取配置文件方式创建对象
5)将创建的对象作为map集合的value和key存入到map中
6)返回给调用者创建的对象
*/
public class BeansFactory {
// 1)创建map集合存储创建的对象
/*
key value
userService UserServiceImpl0x001
roleService RoleServiceImpl0x002
*/
private static HashMap<String,Object> map = new HashMap<>();
// 2)定义静态方法创建具体类的对象
//多线程安全问题:t1 t2
public static synchronized <T> T getInstance(String key) throws Exception{//String key=userService roleService
// 3)在静态方法中判断map集合的key是否有值,如果没有值,说明第一创建对象
Object obj = map.get(key);
// 4)直接使用反射+读取配置文件方式创建对象
if(obj == null){
//说明当前map集合中没有传递的key对应的值
//4.1使用反射+读取配置文件创建对象
ResourceBundle bundle = ResourceBundle.getBundle("beans");//参数beans表示要关联的配置文件的名字,不能书写后缀名
//4.2根据配置文件的key获取值 t1
//userService=com.itheima.case2.service.impl.UserServiceImpl
String classNameStr = bundle.getString(key);//"com.itheima.case2.service.impl.UserServiceImpl"
//4.3使用反射创建对象
Class<?> clazz = Class.forName(classNameStr);
obj = clazz.newInstance();//调用UserServiceImpl类的无参构造方法
// 5)将创建的对象作为map集合的value和key存入到map中
map.put(key,obj);//t1线程创建的对象0x001 t2线程创建的对象0x002
}
// 6)返回给调用者创建的对象
return (T)obj;
}
}
userService=com.itheima.case2.service.impl.UserServiceImpl
小结:
SpringIOC:使用反射+读取配置文件+面向接口编程+工厂设计模式创建类的对象。其实SpringIOC底层是Map集合,我们经常会说SpringIOC容器即Map集合。在集合中存放对象。这样做的好处:解耦合。