首页
壁纸
留言板
友链
更多
统计归档
Search
1
TensorBoard:训练日志及网络结构可视化工具
12,687 阅读
2
主板开机跳线接线图【F_PANEL接线图】
9,806 阅读
3
移动光猫获取超级密码&开启公网ipv6
8,475 阅读
4
Linux使用V2Ray 原生客户端
7,528 阅读
5
NVIDIA 显卡限制功率
3,490 阅读
好物分享
实用教程
linux使用
wincmd
学习笔记
mysql
java学习
nginx
综合面试题
大数据
网络知识
linux
k8s
放码过来
python
javascript
java
opencv
蓝桥杯
leetcode
深度学习
开源模型
相关知识
数据集和工具
模型轻量化
语音识别
计算机视觉
杂七杂八
硬件科普
主机安全
嵌入式设备
其它
bug处理
登录
/
注册
Search
标签搜索
好物分享
学习笔记
linux
MySQL
nvidia
typero
内网穿透
webdav
vps
java
cudann
gcc
cuda
树莓派
CNN
图像去雾
ssh安全
nps
暗通道先验
阿里云
jupiter
累计撰写
359
篇文章
累计收到
119
条评论
首页
栏目
好物分享
实用教程
linux使用
wincmd
学习笔记
mysql
java学习
nginx
综合面试题
大数据
网络知识
linux
k8s
放码过来
python
javascript
java
opencv
蓝桥杯
leetcode
深度学习
开源模型
相关知识
数据集和工具
模型轻量化
语音识别
计算机视觉
杂七杂八
硬件科普
主机安全
嵌入式设备
其它
bug处理
页面
壁纸
留言板
友链
统计归档
搜索到
359
篇与
的结果
2022-04-28
spring5学习笔记
1.spring简介1.1 介绍spring:春天--给软件行业带来了春天2002年,首次推出了spring框架的雏形:interface212004年3月24日诞生Rod Johnson,Spring Framework创始人spring理念:使现有的技术更加容易复用,本身是一个大杂烩,整合了现有的技术框架官网:https://spring.io/Spring Framework 中文文档:https://www.docs4dev.com/docs/zh/spring-framework/官方下载地址 : https://repo.spring.io/libs-release-local/org/springframework/spring/GitHub : https://github.com/spring-projectsjava两套框架SSH:Struct2+Spring+HibernateSSH:SpringMVC+Spring+Mybatis1.2 优点spring是一个开源免费的框架(容器)spring是一个轻量级的、非入侵式的框架支持事务处理支持对框架整合的指出1.3 核心特点控制反转(IOC)面向切面编程(AOP)1.4 组成Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。1.5 拓展在Spring的官网有这个介绍:现代化的Java开发!说白就是基于Spring的开发!Spring Boot与Spring CloudSpring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务;Spring Cloud是基于Spring Boot实现的;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。。因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!1.6 弊端弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,人称:“配置地狱!”1.7 小结总结一句话:Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架。2. IOC理论推导2.1 分析实现0、新建一个空白的maven项目我们先用我们原来的方式写一段代码 .1、先写一个UserDao接口public interface UserDao { public void getUser(); }2、再去写Dao的实现类public class UserDaoImpl implements UserDao { @Override public void getUser() { System.out.println("获取用户数据"); } }3、然后去写UserService的接口public interface UserService { public void getUser(); }4、最后写Service的实现类public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImpl(); @Override public void getUser() { userDao.getUser(); } }5、测试一下@Test public void test(){ UserService service = new UserServiceImpl(); service.getUser(); }这是我们原来的方式 , 开始大家也都是这么去写的对吧 . 那我们现在修改一下 .把Userdao的实现类增加一个 .public class UserDaoMySqlImpl implements UserDao { @Override public void getUser() { System.out.println("MySql获取用户数据"); } }紧接着我们要去使用MySql的话 , 我们就需要去service实现类里面修改对应的实现public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoMySqlImpl(); @Override public void getUser() { userDao.getUser(); } }在假设, 我们再增加一个Userdao的实现类 .public class UserDaoOracleImpl implements UserDao { @Override public void getUser() { System.out.println("Oracle获取用户数据"); } }那么我们要使用Oracle , 又需要去service实现类里面修改对应的实现 . 假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 .那我们如何去解决呢 ? 我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 .public class UserServiceImpl implements UserService { private UserDao userDao; // 利用set实现 public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); } }现在去我们的测试类里 , 进行测试 ;@Test public void test(){ UserServiceImpl service = new UserServiceImpl(); service.setUserDao( new UserDaoMySqlImpl() ); service.getUser(); //那我们现在又想用Oracle去实现呢 service.setUserDao( new UserDaoOracleImpl() ); service.getUser(); }大家发现了区别没有 ? 可能很多人说没啥区别 . 但是同学们 , 他们已经发生了根本性的变化 , 很多地方都不一样了 . 仔细去思考一下 , 以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者 . 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 .这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 !2.2 IOC本质控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。3.HelloSpring3.1 实现HelloSpring0、导入Jar包<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.10.RELEASE</version> </dependency>1、编写一个Hello实体类package com.kuang.pojo; public class Hello { private String name; public String getName(){ return name; } public void setName(String name){ this.name = name; } public void show(){ System.out.println("Hello"+name); } }2、编写我们的spring文件 , 这里我们命名为beans.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--bean就是java对象 , 由Spring创建和管理--> <bean id="hello" class="com.kuang.pojo.Hello"> <property name="name" value="Spring"/> </bean> </beans>3、我们可以去进行测试了 .@Test public void test(){ //解析beans.xml文件 , 生成管理相应的Bean对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //getBean : 参数即为spring配置文件中bean的id . Hello hello = (Hello) context.getBean("hello"); hello.show(); }3.2 思考Hello 对象是谁创建的 ? hello 对象是由Spring创建的Hello 对象的属性是怎么设置的 ? hello 对象的属性是由Spring容器设置的这个过程就叫控制反转 :控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的反转 : 程序本身不创建对象 , 而变成被动的接收对象 .依赖注入 : 就是利用set方法来进行注入的.IOC是一种编程思想,由主动的编程变成被动的接收可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .3.3 修改案例一我们在案例一中, 新增一个Spring配置文件beans.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="MysqlImpl" class="com.kuang.dao.impl.UserDaoMySqlImpl"/> <bean id="OracleImpl" class="com.kuang.dao.impl.UserDaoOracleImpl"/> <bean id="ServiceImpl" class="com.kuang.service.impl.UserServiceImpl"> <!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写--> <!--引用另外一个bean , 不是用value 而是用 ref--> <property name="userDao" ref="OracleImpl"/> </bean> </beans>测试!@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("ServiceImpl"); serviceImpl.getUser(); }OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !3.4 IOC创建对象方式3.4.1 通过无参构造方法来创建1、User.javapublic class User { private String name; public User() { System.out.println("user无参构造方法"); } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+ name ); } }2、beans.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.kuang.pojo.User"> <property name="name" value="kuangshen"/> </bean> </beans>3、测试类@Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //在执行getBean的时候, user已经创建好了 , 通过无参构造 User user = (User) context.getBean("user"); //调用对象的方法 . user.show(); }结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了!3.4.2 通过有参构造方法来创建1、UserT . javapublic class UserT { private String name; public UserT(String name) { this.name = name; } public void setName(String name) { this.name = name; } public void show(){ System.out.println("name="+ name ); } }2、beans.xml 有三种方式编写<!-- 第一种根据index参数下标设置 --> <bean id="userT" class="com.kuang.pojo.UserT"> <!-- index指构造方法 , 下标从0开始 --> <constructor-arg index="0" value="kuangshen2"/> </bean> <!-- 第二种根据参数名字设置 --> <bean id="userT" class="com.kuang.pojo.UserT"> <!-- name指参数名 --> <constructor-arg name="name" value="kuangshen2"/> </bean> <!-- 第三种根据参数类型设置 --> <bean id="userT" class="com.kuang.pojo.UserT"> <constructor-arg type="java.lang.String" value="kuangshen2"/> </bean>3、测试@Test public void testT(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserT user = (UserT) context.getBean("userT"); user.show(); }结论:在配置文件加载的时候。其中管理的对象都已经初始化了!3.5 其他Spring配置3.5.1 别名alias 设置别名 , 为bean设置别名 , 可以设置多个别名<!--设置别名:在获取Bean的时候可以使用别名获取--> <alias name="userT" alias="userNew"/>3.5.2 Bean的配置<!--bean就是java对象,由Spring创建和管理--> <!-- id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符 如果配置id,又配置了name,那么name是别名 name可以设置多个别名,可以用逗号,分号,空格隔开 如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象; class是bean的全限定名=包名+类名 --> <bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello"> <property name="name" value="Spring"/> </bean>3.5.3 import团队的合作通过import来实现 .<import resource="{path}/beans.xml"/>4.依赖注入(DI)4.1 概念依赖注入(Dependency Injection,DI)。依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .4.2 构造器注入我们在之前的案例已经讲过了4.3 Set 注入 (重点)要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .测试pojo类 :Address.java public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }Student.java package com.kuang.pojo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private String wife; private Properties info; public void setName(String name) { this.name = name; } public void setAddress(Address address) { this.address = address; } public void setBooks(String[] books) { this.books = books; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public void setCard(Map<String, String> card) { this.card = card; } public void setGames(Set<String> games) { this.games = games; } public void setWife(String wife) { this.wife = wife; } public void setInfo(Properties info) { this.info = info; } public void show(){ System.out.println("name="+ name + ",address="+ address.getAddress() + ",books=" ); for (String book:books){ System.out.print("<<"+book+">>\t"); } System.out.println("\n爱好:"+hobbys); System.out.println("card:"+card); System.out.println("games:"+games); System.out.println("wife:"+wife); System.out.println("info:"+info); } }1、常量注入 <bean id="student" class="com.kuang.pojo.Student"> <property name="name" value="小明"/> </bean>测试: @Test public void test01(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); }2、Bean注入 注意点:这里的值是一个引用,ref <bean id="addr" class="com.kuang.pojo.Address"> <property name="address" value="重庆"/> </bean> <bean id="student" class="com.kuang.pojo.Student"> <property name="name" value="小明"/> <property name="address" ref="addr"/> </bean>3、数组注入 <bean id="student" class="com.kuang.pojo.Student"> <property name="name" value="小明"/> <property name="address" ref="addr"/> <property name="books"> <array> <value>西游记</value> <value>红楼梦</value> <value>水浒传</value> </array> </property> </bean>4、List注入 <property name="hobbys"> <list> <value>听歌</value> <value>看电影</value> <value>爬山</value> </list> </property>5、Map注入 <property name="card"> <map> <entry key="中国邮政" value="456456456465456"/> <entry key="建设" value="1456682255511"/> </map> </property>6、set注入 <property name="games"> <set> <value>LOL</value> <value>BOB</value> <value>COC</value> </set> </property>7、Null注入 <property name="wife"><null/></property>8、Properties注入 <property name="info"> <props> <prop key="学号">20190604</prop> <prop key="性别">男</prop> <prop key="姓名">小明</prop> </props> </property>测试结果:4.4 p命名和c命名注入User.java :【注意:这里没有有参构造器!】 public class User { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }1、P命名空间注入 : 需要在头文件中加入约束文件 导入约束 : xmlns:p="http://www.springframework.org/schema/p" <!--P(属性: properties)命名空间 , 属性依然要设置set方法--> <bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>2、c 命名空间注入 : 需要在头文件中加入约束文件 导入约束 : xmlns:c="http://www.springframework.org/schema/c" <!--C(构造: Constructor)命名空间 , 属性依然要设置set方法--> <bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>发现问题:爆红了,刚才我们没有写有参构造!解决:把有参构造器加上,这里也能知道,c 就是所谓的构造器注入!测试代码: @Test public void test02(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); System.out.println(user); }4.5 Bean的作用域在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象 .几种作用域中,request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。Singleton当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置: <bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">测试: @Test public void test03(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); User user2 = (User) context.getBean("user"); System.out.println(user==user2); }Prototype当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将bean定义成prototype,可以这样配置: <bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> 或者 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>Request当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义: <bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。Session当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义: <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。5.Bean的自动装配5.1 自动装配说明自动装配是使用spring满足bean依赖的一种方法spring会在应用上下文中为某个bean寻找其依赖的bean。Spring中bean有三种装配机制,分别是:在xml中显式配置;在java中显式配置;隐式的bean发现机制和自动装配。这里我们主要讲第三种:自动化的装配bean。Spring的自动装配需要从两个角度来实现,或者说是两个操作:组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。推荐不使用自动装配xml配置 , 而使用注解 .5.2 测试环境搭建1、新建一个项目2、新建两个实体类,Cat Dog 都有一个叫的方法public class Cat { public void shout() { System.out.println("miao~"); } } public class Dog { public void shout() { System.out.println("wang~"); } }3、新建一个用户类 Userpublic class User { private Cat cat; private Dog dog; private String str; }4、编写Spring配置文件<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> <property name="str" value="qinjiang"/> </bean> </beans>5、测试public class MyTest { @Test public void testMethodAutowire() { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); User user = (User) context.getBean("user"); user.getCat().shout(); user.getDog().shout(); } }结果正常输出,环境OK5.3 autowire byName (按名称自动装配)由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。采用自动装配将避免这些错误,并且使配置简单化。测试:1、修改bean配置,增加一个属性 autowire="byName"<bean id="user" class="com.kuang.pojo.User" autowire="byName"> <property name="str" value="qinjiang"/> </bean>2、再次测试,结果依旧成功输出!3、我们将 cat 的bean id修改为 catXXX4、再次测试, 执行时报空指针java.lang.NullPointerException。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。小结:当一个bean节点带有 autowire byName的属性时。将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。去spring容器中寻找是否有此字符串名称id的对象。如果有,就取出注入;如果没有,就报空指针异常。5.4 autowire byType (按类型自动装配)使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。测试:1、将user的bean配置修改一下 : autowire="byType"2、测试,正常输出3、在注册一个cat 的bean对象!<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User" autowire="byType"> <property name="str" value="qinjiang"/> </bean>4、测试,报错:NoUniqueBeanDefinitionException5、删掉cat2,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。这就是按照类型自动装配!5.5 使用注解jdk1.5开始支持注解,spring2.5开始全面支持注解。准备工作:利用注解的方式注入属性。1、在spring配置文件中引入context文件头xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/context/spring-aop.xsd">2、开启属性注解支持!<context:annotation-config/>@Autowired@Autowired是按类型自动转配的,不支持id匹配。需要导入 spring-aop的包!测试:1、将User类中的set方法去掉,使用@Autowired注解public class User { @Autowired private Cat cat; @Autowired private Dog dog; private String str; public Cat getCat() { return cat; } public Dog getDog() { return dog; } public String getStr() { return str; } }2、此时配置文件内容<context:annotation-config/> <bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"/>3、测试,成功输出结果!【小狂神科普时间】@Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。//如果允许对象为null,设置required = false,默认为true @Autowired(required = false) private Cat cat;@Qualifier@Autowired是根据类型+id自动装配的,加上@Qualifier则可以根据byName的方式自动装配@Qualifier不能单独使用。测试实验步骤:1、配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!<bean id="dog1" class="com.kuang.pojo.Dog"/> <bean id="dog2" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/>2、没有加Qualifier测试,直接报错3、在属性上添加Qualifier注解@Autowired @Qualifier(value = "cat2") private Cat cat; @Autowired @Qualifier(value = "dog2") private Dog dog;测试,成功输出!@Resource@Resource如有指定的name属性,先按该属性进行byName方式查找装配;其次再进行默认的byName方式进行装配;如果以上都不成功,则按byType的方式自动装配。都不成功,则报异常。实体类:public class User { //如果允许对象为null,设置required = false,默认为true @Resource(name = "cat2") private Cat cat; @Resource private Dog dog; private String str; }beans.xml<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"/>测试:结果OK配置文件2:beans.xml , 删掉cat2<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/>实体类上只保留注解@Resource private Cat cat; @Resource private Dog dog;结果:OK结论:先进行byName查找,失败;再进行byType查找,成功。@Autowired与@Resource异同:1、@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。2、@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用3、@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。6. 静态/动态代理模式为什么要学习代理模式,因为AOP的底层机制就是动态代理!代理模式:静态代理动态代理学习aop之前 , 我们要先了解一下代理模式!6.1 静态代理静态代理角色分析抽象角色 : 一般使用接口或者抽象类来实现真实角色 : 被代理的角色代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .客户 : 使用代理角色来进行一些操作 .代码实现Rent . java 即抽象角色//抽象角色:租房 public interface Rent { public void rent(); }Host . java 即真实角色//真实角色: 房东,房东要出租房子 public class Host implements Rent{ public void rent() { System.out.println("房屋出租"); } }Proxy . java 即代理角色//代理角色:中介 public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } //租房 public void rent(){ seeHouse(); host.rent(); fare(); } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }Client . java 即客户//客户类,一般客户都会去找代理! public class Client { public static void main(String[] args) { //房东要租房 Host host = new Host(); //中介帮助房东 Proxy proxy = new Proxy(host); //你去找中介! proxy.rent(); } }分析:在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。静态代理的好处:可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .公共的业务由代理来完成 . 实现了业务的分工 ,公共业务发生扩展时变得更加集中和方便 .缺点 :类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !6.2 静态代理再理解同学们练习完毕后,我们再来举一个例子,巩固大家的学习!练习步骤:1、创建一个抽象角色,比如咋们平时做的用户业务,抽象起来就是增删改查!//抽象角色:增删改查业务 public interface UserService { void add(); void delete(); void update(); void query(); }2、我们需要一个真实对象来完成这些增删改查操作//真实对象,完成增删改查操作的人 public class UserServiceImpl implements UserService { public void add() { System.out.println("增加了一个用户"); } public void delete() { System.out.println("删除了一个用户"); } public void update() { System.out.println("更新了一个用户"); } public void query() { System.out.println("查询了一个用户"); } }3、需求来了,现在我们需要增加一个日志功能,怎么实现!思路1 :在实现类上增加代码 【麻烦!】思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!4、设置一个代理类来处理日志!代理角色//代理角色,在这里面增加日志的实现 public class UserServiceProxy implements UserService { private UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } public void add() { log("add"); userService.add(); } public void delete() { log("delete"); userService.delete(); } public void update() { log("update"); userService.update(); } public void query() { log("query"); userService.query(); } public void log(String msg){ System.out.println("执行了"+msg+"方法"); } }5、测试访问类:public class Client { public static void main(String[] args) { //真实业务 UserServiceImpl userService = new UserServiceImpl(); //代理类 UserServiceProxy proxy = new UserServiceProxy(); //使用代理类实现日志功能! proxy.setUserService(userService); proxy.add(); } }OK,到了现在代理模式大家应该都没有什么问题了,重点大家需要理解其中的思想;我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想聊聊AOP:纵向开发,横向开发6.3 动态代理动态代理的角色和静态代理的一样 .动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理基于接口的动态代理----JDK动态代理基于类的动态代理--cglib现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist我们这里使用JDK的原生代码来实现,其余的道理都是一样的!、JDK的动态代理需要了解两个类核心 : InvocationHandler 和 Proxy , 打开JDK帮助文档看看【InvocationHandler:调用处理程序】Object invoke(Object proxy, 方法 method, Object[] args); //参数 //proxy - 调用该方法的代理实例 //method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。 //args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。【Proxy : 代理】//生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); }代码实现 抽象角色和真实角色和之前的一样!Rent . java 即抽象角色//抽象角色:租房 public interface Rent { public void rent(); }Host . java 即真实角色//真实角色: 房东,房东要出租房子 public class Host implements Rent{ public void rent() { System.out.println("房屋出租"); } }ProxyInvocationHandler. java 即代理角色public class ProxyInvocationHandler implements InvocationHandler { private Rent rent; public void setRent(Rent rent) { this.rent = rent; } //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this); } // proxy : 代理类 method : 代理类的调用处理程序的方法对象. // 处理代理实例上的方法调用并返回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { seeHouse(); //核心:本质利用反射实现! Object result = method.invoke(rent, args); fare(); return result; } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }Client . java//租客 public class Client { public static void main(String[] args) { //真实角色 Host host = new Host(); //代理实例的调用处理程序 ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setRent(host); //将真实角色放置进去! Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类! proxy.rent(); } }核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、6.4 深化理解我们来使用动态代理实现代理我们后面写的UserService!我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!public class ProxyInvocationHandler implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } //生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } // proxy : 代理类 // method : 代理类的调用处理程序的方法对象. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String methodName){ System.out.println("执行了"+methodName+"方法"); } }测试!public class Test { public static void main(String[] args) { //真实对象 UserServiceImpl userService = new UserServiceImpl(); //代理对象的调用处理程序 ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(userService); //设置要代理的对象 UserService proxy = (UserService)pih.getProxy(); //动态生成代理类! proxy.delete(); } }测试,增删改查,查看结果!动态代理的好处静态代理有的它都有,静态代理没有的,它也有!可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .公共的业务由代理来完成 . 实现了业务的分工 ,公共业务发生扩展时变得更加集中和方便 .一个动态代理 , 一般代理某一类业务一个动态代理可以代理多个类,代理的是接口!7.AOP7.1 什么是AOPAOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。7.2 Aop在Spring中的作用提供声明式事务;允许用户自定义切面以下名词需要了解下:横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ....切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。目标(Target):被通知对象。代理(Proxy):向目标对象应用通知之后创建的对象。切入点(PointCut):切面通知 执行的 “地点”的定义。连接点(JointPoint):与切入点匹配的执行点。SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .7.3 使用Spring实现Aop【重点】使用AOP织入,需要导入一个依赖包!<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency>第一种方式:通过 Spring API 实现首先编写我们的业务接口和实现类public interface UserService { public void add(); public void delete(); public void update(); public void search(); } public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加用户"); } @Override public void delete() { System.out.println("删除用户"); } @Override public void update() { System.out.println("更新用户"); } @Override public void search() { System.out.println("查询用户"); } }然后去写我们的增强类 , 我们编写两个 , 一个前置增强 一个后置增强public class BeforeLog implements MethodBeforeAdvice { //method : 要执行的目标对象的方法 //objects : 被调用的方法的参数 //Object : 目标对象 @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了"); } } public class AfterLog implements AfterReturningAdvice { //returnValue 返回值 //method被调用的方法 //args 被调用的方法的对象的参数 //target 被调用的目标对象 @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了" + target.getClass().getName() +"的"+method.getName()+"方法," +"返回值:"+returnValue); } }最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束 .<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--注册bean--> <bean id="userService" class="com.kuang.service.UserServiceImpl"/> <bean id="beforLog" class="com.kuang.log.BeforeLog"/> <bean id="afterLog" class="com.kuang.log.AfterLog"/> <!--aop的配置--> <aop:config> <!--切入点 expression:表达式匹配要执行的方法--> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点--> <aop:advisor advice-ref="beforLog" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>测试public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) context.getBean("userService"); userService.search(); } }Aop的重要性 : 很重要 . 一定要理解其中的思路 , 主要是思想的理解这一块 .Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理 .第二种方式:自定义类来实现Aop目标业务类不变依旧是userServiceImpl第一步 : 写我们自己的一个切入类public class DiyPointcut { public void before(){ System.out.println("---------方法执行前---------"); } public void after(){ System.out.println("---------方法执行后---------"); } }去spring中配置<!--第二种方式自定义实现--> <!--注册bean--> <bean id="diy" class="com.kuang.config.DiyPointcut"/> <!--aop的配置--> <aop:config> <!--第二种方式:使用AOP的标签实现--> <aop:aspect ref="diy"> <aop:pointcut id="diyPonitcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <aop:before pointcut-ref="diyPonitcut" method="before"/> <aop:after pointcut-ref="diyPonitcut" method="after"/> </aop:aspect> </aop:config>测试:public class MyTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) context.getBean("userService"); userService.add(); } }第三种方式:使用注解实现第一步:编写一个注解实现的增强类package com.kuang.config; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class AnnotationPointcut { @Before("execution(* com.kuang.service.UserServiceImpl.*(..))") public void before(){ System.out.println("---------方法执行前---------"); } @After("execution(* com.kuang.service.UserServiceImpl.*(..))") public void after(){ System.out.println("---------方法执行后---------"); } @Around("execution(* com.kuang.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("环绕前"); System.out.println("签名:"+jp.getSignature()); //执行目标方法proceed Object proceed = jp.proceed(); System.out.println("环绕后"); System.out.println(proceed); } }第二步:在Spring配置文件中,注册bean,并增加支持注解的配置<!--第三种方式:注解实现--> <bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/> <aop:aspectj-autoproxy/>aop:aspectj-autoproxy:说明通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了 <aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。8.整合MyBatis8.1 步骤1、导入相关jar包<!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--mysql-connector-java--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--spring相关--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.10.RELEASE</version> </dependency> <!--aspectJ AOP 织入器--> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> <!--mybatis-spring整合包 【重点】--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency>配置Maven静态资源过滤问题!<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>2、编写配置文件3、代码实现8.2 回忆MyBatis编写pojo实体类package com.kuang.pojo; public class User { private int id; //id private String name; //姓名 private String pwd; //密码 }实现mybatis的配置文件<?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> <typeAliases> <package name="com.kuang.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <package name="com.kuang.dao"/> </mappers> </configuration>UserDao接口编写public interface UserMapper { public List<User> selectUser(); }接口对应的Mapper映射文件<?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"> <mapper namespace="com.kuang.dao.UserMapper"> <select id="selectUser" resultType="User"> select * from user </select> </mapper>测试类@Test public void selectUser() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.selectUser(); for (User user: userList){ System.out.println(user); } sqlSession.close(); }8.3 MyBatis-Spring学习引入Spring之前需要了解mybatis-spring包中的一些重要类;http://www.mybatis.org/spring/zh/index.html什么是 MyBatis-Spring?MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。知识基础在开始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术语。这很重要MyBatis-Spring 需要以下版本:MyBatis-SpringMyBatisSpring 框架Spring BatchJava2.03.5+5.0+4.0+Java 8+1.33.4+3.2.2+2.1+Java 6+如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency>要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。在 MyBatis-Spring 中,可使用SqlSessionFactoryBean来创建 SqlSessionFactory。要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> </bean>注意:SqlSessionFactory需要一个 DataSource(数据源)。这可以是任意的 DataSource,只需要和配置其它 Spring 数据库连接一样配置它就可以了。在基础的 MyBatis 用法中,是通过 SqlSessionFactoryBuilder 来创建 SqlSessionFactory 的。而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来创建。在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射了的语句,提交或回滚连接,最后,当不再需要它的时候,你可以关闭 session。SqlSessionFactory有一个唯一的必要属性:用于 JDBC 的 DataSource。这可以是任意的 DataSource 对象,它的配置方法和其它 Spring 数据库连接是一样的。一个常用的属性是 configLocation,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改 MyBatis 的基础配置非常有用。通常,基础配置指的是 < settings> 或 < typeAliases>元素。需要注意的是,这个配置文件并不需要是一个完整的 MyBatis 配置。确切地说,任何环境配置(),数据源()和 MyBatis 的事务管理器()都会被忽略。SqlSessionFactoryBean 会创建它自有的 MyBatis 环境配置(Environment),并按要求设置自定义环境的值。SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。模板可以参与到 Spring 的事务管理中,并且由于其是线程安全的,可以供多个映射器类使用,你应该总是用 SqlSessionTemplate 来替换 MyBatis 默认的 DefaultSqlSession 实现。在同一应用程序中的不同类之间混杂使用可能会引起数据一致性的问题。可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean>现在,这个 bean 就可以直接注入到你的 DAO bean 中了。你需要在你的 bean 中添加一个 SqlSession 属性,就像下面这样:public class UserDaoImpl implements UserDao { private SqlSession sqlSession; public void setSqlSession(SqlSession sqlSession) { this.sqlSession = sqlSession; } public User getUser(String userId) { return sqlSession.getMapper...; } }按下面这样,注入 SqlSessionTemplate:<bean id="userDao" class="org.mybatis.spring.sample.dao.UserDaoImpl"> <property name="sqlSession" ref="sqlSession" /> </bean>8.4 整合实现一1、引入Spring配置文件beans.xml<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">2、配置数据源替换mybaits的数据源<!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean>3、配置SqlSessionFactory,关联MyBatis<!--配置SqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--关联Mybatis--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/kuang/dao/*.xml"/> </bean>4、注册sqlSessionTemplate,关联sqlSessionFactory;<!--注册sqlSessionTemplate , 关联sqlSessionFactory--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--利用构造器注入--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean>5、增加Dao接口的实现类;私有化sqlSessionTemplatepublic class UserMapperImpl implements UserMapper { //sqlSession不用我们自己创建了,Spring来管理 private SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectUser(); } }6、注册bean实现<bean id="UserMapper" class="com.kuang.mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean>7、测试 @Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); }结果成功输出!现在我们的Mybatis配置文件的状态!发现都可以被Spring整合!<?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> <typeAliases> <package name="com.kuang.pojo"/> </typeAliases> </configuration>8.5 整合实现二mybatis-spring1.2.3版以上的才有这个 .官方文档截图 :dao继承Support类 , 直接利用 getSqlSession() 获得 , 然后直接注入SqlSessionFactory . 比起方式1 , 不需要管理SqlSessionTemplate , 而且对事务的支持更加友好 . 可跟踪源码查看测试:1、将我们上面写的UserDaoImpl修改一下public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.selectUser(); } }2、修改bean的配置<bean id="userDao" class="com.kuang.dao.UserDaoImpl"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>3、测试@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); }9.声明式事务9.1 回顾事务事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。事务四个属性ACID原子性(atomicity)事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用一致性(consistency)一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中隔离性(isolation)可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏持久性(durability)事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中9.2 测试将上面的代码拷贝到一个新项目中在之前的案例中,我们给userDao接口新增两个方法,删除和增加用户;//添加一个用户 public int addUser(User user); //根据id删除用户 public int deleteUser(int id);mapper文件,我们故意把 deletes 写错,测试!<insert id="addUser" parameterType="com.kuang.pojo.User"> insert into user (id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <delete id="deleteUser" parameterType="int"> deletes from user where id = #{id} </delete>编写接口的实现类,在实现类中,我们去操作一波public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper { //增加一些操作 public List<User> selectUser() { User user = new User(4,"小明","123456"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(4); return mapper.selectUser(); } //新增 public int addUser(User user) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.addUser(user); } //删除 public int deleteUser(int id) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.deleteUser(id); } }测试@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); }报错:sql异常,delete写错了结果 :插入成功!没有进行事务的管理;我们想让他们都成功才成功,有一个失败,就都失败,我们就应该需要事务!以前我们都需要自己手动管理事务,十分麻烦!但是Spring给我们提供了事务管理,我们只需要配置即可;9.3 Spring中的事务管理Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。编程式事务管理将事务管理代码嵌到业务方法中来控制事务的提交和回滚缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码声明式事务管理一般情况下比编程式事务好用。将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。使用Spring管理事务,注意头文件的约束导入 : txxmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">事务管理器无论使用Spring的哪种事务管理策略(编程式或者声明式)事务管理器都是必须的。就是 Spring的核心事务管理抽象,管理封装了一组独立于技术的方法。JDBC事务<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>配置好事务管理器后我们需要去配置事务的通知<!--配置事务通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--配置哪些方法使用什么样的事务,配置事务的传播特性--> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="search*" propagation="REQUIRED"/> <tx:method name="get" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>spring事务传播特性:事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这 3 个服务类的 3 个方法通过 Spring 的事务传播机制都工作在同一个事务中。就好比,我们刚才的几个方法存在调用,所以会被放在一组事务当中!配置AOP导入aop的头文件!<!--配置aop织入事务--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.kuang.dao.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config>进行测试删掉刚才插入的数据,再次测试!@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); }思考问题?为什么需要配置事务?如果不配置,就需要我们手动提交控制事务;事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!参考资料【狂神说Java】Spring5最新完整教程IDEA版通俗易懂
2022年04月28日
870 阅读
0 评论
0 点赞
2022-04-27
leetcode|中等:36. 有效的数独
1.题目请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)注意:一个有效的数独(部分已被填充)不一定是可解的。只需要根据以上规则,验证已经填入的数字是否有效即可。空白格用 '.' 表示。示例 1:输入:board = [["5","3",".",".","7",".",".",".","."] ,["6",".",".","1","9","5",".",".","."] ,[".","9","8",".",".",".",".","6","."] ,["8",".",".",".","6",".",".",".","3"] ,["4",".",".","8",".","3",".",".","1"] ,["7",".",".",".","2",".",".",".","6"] ,[".","6",".",".",".",".","2","8","."] ,[".",".",".","4","1","9",".",".","5"] ,[".",".",".",".","8",".",".","7","9"]] 输出:true示例 2:输入:board = [["8","3",".",".","7",".",".",".","."] ,["6",".",".","1","9","5",".",".","."] ,[".","9","8",".",".",".",".","6","."] ,["8",".",".",".","6",".",".",".","3"] ,["4",".",".","8",".","3",".",".","1"] ,["7",".",".",".","2",".",".",".","6"] ,[".","6",".",".",".",".","2","8","."] ,[".",".",".","4","1","9",".",".","5"] ,[".",".",".",".","8",".",".","7","9"]] 输出:false 解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。提示:board.length == 9board[i].length == 9board[i][j] 是一位数字(1-9)或者 '.'2. 题解2.1 思路分析思路1:题目比较简单 暴力遍历即可2.2 代码实现思路1:class Solution { public boolean isValidSudoku(char[][] board) { // 0.计数数组 int[] counter = new int[9]; // 1.数字 1-9 在每一行只能出现一次。 for (int i = 0; i < 9; i++) { Arrays.fill(counter,0); for (int j = 0; j < 9; j++) { if(board[i][j]!='.'){ int index = board[i][j]-'1'; counter[index]++; if(counter[index]>1){ return false; } } } } // 2.数字 1-9 在每一列只能出现一次。 for (int i = 0; i < 9; i++) { Arrays.fill(counter,0); for (int j = 0; j < 9; j++) { if(board[j][i]!='.'){ int index = board[j][i]-'1'; counter[index]++; if(counter[index]>1){ return false; } } } } // 3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Arrays.fill(counter,0); int x_offset = 3*i; int y_offset = 3*j; for (int k = 0; k < 3; k++) { for (int l = 0; l < 3; l++) { if(board[x_offset+k][y_offset+l]!='.'){ int index = board[x_offset+k][y_offset+l]-'1'; counter[index]++; if(counter[index]>1){ return false; } } } } } } return true; } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过1 ms40.8 MBJava2022/04/27 19:31添加备注参考资料https://leetcode-cn.com/problems/valid-sudoku/
2022年04月27日
681 阅读
0 评论
0 点赞
2022-04-27
leetcode|中等:31. 下一个排列
1.题目整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。给你一个整数数组 nums ,找出 nums 的下一个排列。必须 原地 修改,只允许使用额外常数空间。2. 题解2.1 思路分析思路1: 1.倒序遍历数组, 找到第一个前一个数比后一个数小的位置(即nums[i] < nums[i+1]); firstIndex = i 2.这个时候我们不能直接把后一个数nums[i+1] 跟前一个数nums[i]交换就完事了; 还应该从nums[i+1]-->数组末尾这一段的数据中 找出最优的那个值 如何最优? 即比nums[i]稍微大那么一丢丢的数, 也就是 nums[i+1]-->数组末尾中, 比nums[i]大的数中最小的那个值 下标记为secondeIndex 3.找到之后, 跟num[i]交换, 这还不算是下一个排列, num[i]后面的数值还不够小, 所以还应当对 nums[i+1]-->数组末尾 进升序排列 eg:nums = [1,2,7,4,3,1], 1.倒序遍历数组, 找出第一组 前一个数比后一个数小的两个数 即[2,7] 2.2所处的这个位置就是需要找出比它稍微大的数的位置; 3.我们从[7,4,3,1]中找出比2大的数中的最小值, 也就是3, 找到后跟2交换即可; 当然了, 如果没找到的话, 直接跳到第5步, 直接升序排列输出. 4.目前nums=[1,3,7,4,2,1], 明显可以看出来还不算下一个排列 5.对3后面的数, 升序排列, 即最终结果: nums = [1,3,1,2,4,7]2.2 代码实现思路1:import java.util.*; public class Solution { public void nextPermutation(int[] nums) { // 1.倒序遍历数组,找到第一个满足nums[i] < nums[i+1]的位置 for (int firstIndex = nums.length-2; firstIndex >=0; firstIndex--) { if(nums[firstIndex]<nums[firstIndex+1]){ int secondeIndex = firstIndex+1; // 2.在 nums[i+1]-->数组末尾 找比nums[i]大的数中最小的那个值 for (int i = secondeIndex+1; i < nums.length; i++) { if(nums[i]>nums[firstIndex]&&nums[i]<nums[secondeIndex]){ secondeIndex = i; } } // 3.交换nums[firstIndex]和nums[secondeIndex] int temp = nums[secondeIndex]; nums[secondeIndex] = nums[firstIndex]; nums[firstIndex] = temp; // 4.对nums[firstIndex+1]之后的数进行升序排列 Arrays.sort(nums,firstIndex+1,nums.length); return; } } // 5.如果没找到直接升序排列并返回 Arrays.sort(nums); return; } public static void main(String[] args) { Solution solution = new Solution(); int[] nums = new int[]{1,3,2}; solution.nextPermutation(nums); System.out.println(Arrays.toString(nums)); } } 2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过1 ms41.8 MBJava2022/04/27 18:36添加备注参考资料https://leetcode-cn.com/problems/next-permutation/
2022年04月27日
668 阅读
0 评论
0 点赞
2022-04-26
leetcode|困难:30. 串联所有单词的子串
leetcode|困难:30. 串联所有单词的子串1.题目给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。示例 1:输入:s = "barfoothefoobarman", words = ["foo","bar"] 输出:[0,9] 解释: 从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。 输出的顺序不重要, [9,0] 也是有效答案。示例 2:输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"] 输出:[]示例 3:输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"] 输出:[6,9,12]提示:1 <= s.length <= 104s 由小写英文字母组成1 <= words.length <= 50001 <= words[i].length <= 30words[i] 由小写英文字母组成2. 题解2.1 思路分析思路1:滑动窗口+词频统计 对words进行词频统计 然后以words包含的所有字符数作为窗口大小进行滑动+窗口词频统计 判断词频是否相等并记录相对的位置 思路2:#TODO 借鉴KMP对思路1进行优化 避免进行一些冗余比较2.2 代码实现思路1:滑动窗口+词频统计class Solution { public List<Integer> findSubstring(String s, String[] words) { List<Integer> res = new ArrayList<>(); // 记录下来每个单词的长度和单词的总长度 int wordLen = words[0].length(); int allWordLen = words.length*wordLen; // 统计words的词频 Map<String,Integer> wordFrequnce = new HashMap<>(); for (int i = 0; i < words.length; i++) { if(!wordFrequnce.containsKey(words[i])) { wordFrequnce.put(words[i], 1); }else { wordFrequnce.replace(words[i], wordFrequnce.get(words[i])+1); } } // 采用滑动窗口进行遍历,每次滑动一个字符 for (int i = 0; i <= s.length()-allWordLen; i++) { // 统计滑动窗口内的词频 Map<String,Integer> winWordFrequnce = new HashMap<>(); for (int j = 0; j < allWordLen; j+=wordLen) { String tmpWord = s.substring(i+j,i+j+wordLen); if(!winWordFrequnce.containsKey(tmpWord)) { winWordFrequnce.put(tmpWord, 1); }else { winWordFrequnce.replace(tmpWord, winWordFrequnce.get(tmpWord)+1); } } // 判断二者的词频是否一致 boolean sameFlag = winWordFrequnce.equals(wordFrequnce); // 将开始所以加入到res if(sameFlag){ res.add(i); } } return res; } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过247 ms42.2 MBJava2022/04/26 13:56添加备注参考资料https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
2022年04月26日
697 阅读
0 评论
0 点赞
2022-04-26
leetcode|中等:29. 两数相除
1.题目给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。返回被除数 dividend 除以除数 divisor 得到的商。整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2示例 1:输入: dividend = 10, divisor = 3 输出: 3 解释: 10/3 = truncate(3.33333..) = truncate(3) = 3示例 2:输入: dividend = 7, divisor = -3 输出: -2 解释: 7/-3 = truncate(-2.33333..) = -2提示:被除数和除数均为 32 位有符号整数。除数不为 0。假设我们的环境只能存储 32 位有符号整数,其数值范围是 $[−2^{31}, 2^{31} − 1]$。本题中,如果除法结果溢出,则返回 $2^{31} − 1$。2. 题解2.1 思路分析思路1:用减法来模拟乘法 O(n)会运行超时 思路2: 思路1优化:借鉴计算机网络的流量拥塞控制机制,对被除数进行快速倍增2.2 代码实现思路1:用减法来模拟乘法public class Solution { public int divide(int dividend, int divisor) { // 解决计算结果上溢的问题 if(dividend==Integer.MIN_VALUE&&divisor==-1){ return Integer.MAX_VALUE; } // 判断结果的正负并把负数取绝对值+类型提升int-->long System.out.println("dividend="+dividend+",divisor="+divisor); boolean positiveFlag = true; long dividendLong = dividend; long divisorLong = divisor; if(dividend<0){ positiveFlag = !positiveFlag; dividendLong = -(long)dividend; } if(divisor<0){ positiveFlag = !positiveFlag; divisorLong = -(long)divisor; } System.out.println("dividendLong="+dividendLong+",divisorLong="+divisorLong); // 用减法模拟乘法 long res = 0; while (dividendLong>=divisorLong){ dividendLong -= divisorLong; res++; } // 结果符号修正 res = positiveFlag?res:-res; return (int)res; } public static void main(String[] args) { Solution solution = new Solution(); int in = 3; System.out.println(solution.divide(Integer.MIN_VALUE,3)); } }思路2: 思路1优化:借鉴计算机网络的流量拥塞控制机制,对被除数进行快速倍增public class Solution { public int divide(int dividend, int divisor) { // 解决计算结果上溢的问题 if(dividend==Integer.MIN_VALUE&&divisor==-1){ return Integer.MAX_VALUE; } // 判断结果的正负并把负数取绝对值+类型提升int-->long boolean positiveFlag = true; long dividendLong = dividend; long divisorLong = divisor; if(dividend<0){ positiveFlag = !positiveFlag; dividendLong = -(long)dividend; } if(divisor<0){ positiveFlag = !positiveFlag; divisorLong = -(long)divisor; } // 用减法模拟乘法+快速倍乘 long res = 0; while (dividendLong>=divisorLong) { long base = divisorLong; while (dividendLong >= base) { dividendLong -= base; res += (base/divisorLong); base *= 2; } } // 结果符号修正 res = positiveFlag?res:-res; return (int)res; } public static void main(String[] args) { Solution solution = new Solution(); int in = 3; System.out.println(solution.divide(Integer.MIN_VALUE,2)); } }2.3 提交结果思路1提交结果执行用时内存消耗语言提交时间备注超出时间限制N/AN/AJava2022/04/26 10:10添加备注思路2提交结果执行用时内存消耗语言提交时间备注通过1 ms38.5 MBJava2022/04/26 10:29添加备注参考资料https://leetcode-cn.com/problems/divide-two-integers/
2022年04月26日
580 阅读
0 评论
0 点赞
2022-04-25
leetcode|中等:22. 括号生成
1.题目数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。示例 1:输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]示例 2:输入:n = 1 输出:["()"]提示:1 <= n <= 82. 题解2.1 思路分析思路1:DFS 比较简单 直接看代码2.2 代码实现import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class Solution { public void dfs(char[] brackets,int lNum,int rNum,int n,List<String> res){ if(lNum==n && rNum==n) { res.add(new String(brackets)); return; } // 增加左括号 if(lNum<n){ brackets[lNum+rNum] = '('; dfs(brackets,lNum+1,rNum,n,res); } // 增加右括号 if(lNum>rNum&&rNum<n){ brackets[lNum+rNum] = ')'; dfs(brackets,lNum,rNum+1,n,res); } } public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); char[] brackets = new char[2*n]; dfs(brackets,0,0,n,res); return res; } public static void main(String[] args) { Solution solution = new Solution(); int in = 3; System.out.println(solution.generateParenthesis(in)); } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过0 ms41.3 MBJava2022/04/25 20:33添加备注参考资料https://leetcode-cn.com/problems/generate-parentheses/
2022年04月25日
545 阅读
0 评论
0 点赞
2022-04-25
leetcode|中等:17. 电话号码的字母组合
1.题目给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。示例 1:输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]示例 2:输入:digits = "" 输出:[]示例 3:输入:digits = "2" 输出:["a","b","c"]提示:0 <= digits.length <= 4digits[i] 是范围 ['2', '9'] 的一个数字。2. 题解2.1 思路分析思路1:DFS 比较简单 直接看代码2.2 代码实现class Solution { public void dfs(char[] tel,int depth,HashMap<Character,String> digit2CharsMap,String digits,List<String> res){ // dfs出口 if(depth==tel.length) { res.add(new String(tel)); return; } char curDigit = digits.charAt(depth); char[] digit2Chars = digit2CharsMap.get(curDigit).toCharArray(); for(int i=0;i<digit2Chars.length;i++){ tel[depth]=digit2Chars[i]; dfs(tel,depth+1,digit2CharsMap,digits,res); } } public List<String> letterCombinations(String digits) { HashMap<Character,String> digit2CharsMap = new HashMap<>(); digit2CharsMap.put('2',"abc"); digit2CharsMap.put('3',"def"); digit2CharsMap.put('4',"ghi"); digit2CharsMap.put('5',"jkl"); digit2CharsMap.put('6',"mno"); digit2CharsMap.put('7',"pqrs"); digit2CharsMap.put('8',"tuv"); digit2CharsMap.put('9',"wxyz"); List<String> res = new ArrayList<>(); if(digits.length()==0){ return res; } char[] tel = new char[digits.length()]; dfs(tel,0,digit2CharsMap,digits,res); return res; } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过0 ms39.9 MBJava2022/04/25 20:18添加备注参考资料https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
2022年04月25日
518 阅读
0 评论
0 点赞
2022-04-24
YOLOV5 加入注意力机制(以CA注意力机制为例)
0.CA注意力机制网络结构图1.在common.py中先添加你想添加的注意力模块### 常用注意力机制模块实现 class h_sigmoid(nn.Module): def __init__(self, inplace=True): super(h_sigmoid, self).__init__() self.relu = nn.ReLU6(inplace=inplace) def forward(self, x): return self.relu(x + 3) / 6 class h_swish(nn.Module): def __init__(self, inplace=True): super(h_swish, self).__init__() self.sigmoid = h_sigmoid(inplace=inplace) def forward(self, x): return x * self.sigmoid(x) class CoordAtt(nn.Module): def __init__(self, inp, oup, reduction=32): super(CoordAtt, self).__init__() self.pool_h = nn.AdaptiveAvgPool2d((None, 1)) self.pool_w = nn.AdaptiveAvgPool2d((1, None)) mip = max(8, inp // reduction) self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0) self.bn1 = nn.BatchNorm2d(mip) self.act = h_swish() self.conv_h = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0) self.conv_w = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0) def forward(self, x): identity = x n, c, h, w = x.size() x_h = self.pool_h(x) x_w = self.pool_w(x).permute(0, 1, 3, 2) y = torch.cat([x_h, x_w], dim=2) y = self.conv1(y) y = self.bn1(y) y = self.act(y) x_h, x_w = torch.split(y, [h, w], dim=2) x_w = x_w.permute(0, 1, 3, 2) a_h = self.conv_h(x_h).sigmoid() a_w = self.conv_w(x_w).sigmoid() out = identity * a_w * a_h return out class SELayer(nn.Module): def __init__(self, c1, r=16): super(SELayer, self).__init__() self.avgpool = nn.AdaptiveAvgPool2d(1) self.l1 = nn.Linear(c1, c1 // r, bias=False) self.relu = nn.ReLU(inplace=True) self.l2 = nn.Linear(c1 // r, c1, bias=False) self.sig = nn.Sigmoid() def forward(self, x): b, c, _, _ = x.size() y = self.avgpool(x).view(b, c) y = self.l1(y) y = self.relu(y) y = self.l2(y) y = self.sig(y) y = y.view(b, c, 1, 1) return x * y.expand_as(x) class eca_layer(nn.Module): """Constructs a ECA module. Args: channel: Number of channels of the input feature map k_size: Adaptive selection of kernel size """ def __init__(self, channel, k_size=3): super(eca_layer, self).__init__() self.avg_pool = nn.AdaptiveAvgPool2d(1) self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False) self.sigmoid = nn.Sigmoid() def forward(self, x): # feature descriptor on the global spatial information y = self.avg_pool(x) # Two different branches of ECA module y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1) # Multi-scale information fusion y = self.sigmoid(y) x = x * y.expand_as(x) return x * y.expand_as(x) class ChannelAttention(nn.Module): def __init__(self, in_planes, ratio=16): super(ChannelAttention, self).__init__() self.avg_pool = nn.AdaptiveAvgPool2d(1) self.max_pool = nn.AdaptiveMaxPool2d(1) self.f1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False) self.relu = nn.ReLU() self.f2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False) # 写法二,亦可使用顺序容器 # self.sharedMLP = nn.Sequential( # nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False), nn.ReLU(), # nn.Conv2d(in_planes // rotio, in_planes, 1, bias=False)) self.sigmoid = nn.Sigmoid() def forward(self, x): avg_out = self.f2(self.relu(self.f1(self.avg_pool(x)))) max_out = self.f2(self.relu(self.f1(self.max_pool(x)))) out = self.sigmoid(avg_out + max_out) return out class SpatialAttention(nn.Module): def __init__(self, kernel_size=7): super(SpatialAttention, self).__init__() assert kernel_size in (3, 7), 'kernel size must be 3 or 7' padding = 3 if kernel_size == 7 else 1 self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False) self.sigmoid = nn.Sigmoid() def forward(self, x): avg_out = torch.mean(x, dim=1, keepdim=True) max_out, _ = torch.max(x, dim=1, keepdim=True) x = torch.cat([avg_out, max_out], dim=1) x = self.conv(x) return self.sigmoid(x) class CBAMC3(nn.Module): # CSP Bottleneck with 3 convolutions def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion super(CBAMC3, self).__init__() c_ = int(c2 * e) # hidden channels self.cv1 = Conv(c1, c_, 1, 1) self.cv2 = Conv(c1, c_, 1, 1) self.cv3 = Conv(2 * c_, c2, 1) self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)]) self.channel_attention = ChannelAttention(c2, 16) self.spatial_attention = SpatialAttention(7) # self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)]) def forward(self, x): out = self.channel_attention(x) * x print('outchannels:{}'.format(out.shape)) out = self.spatial_attention(out) * out return out 2.修改yolo.py在def parse_model(d, ch):函数的代码中增加你想添加的注意力名称添加前 if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP, C3, C3TR, C3SPP, C3Ghost]: c1, c2 = ch[f], args[0] if c2 != no: # if not output c2 = make_divisible(c2 * gw, 8)添加后 if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, CoordAtt]: c1, c2 = ch[f], args[0] if c2 != no: # if not output c2 = make_divisible(c2 * gw, 8)3.修改yaml文件/创建自定义的yaml文件示例-yolov5s-CA.yaml
2022年04月24日
547 阅读
0 评论
1 点赞
2022-04-19
常用网站推荐
1.小说下载八零电子书:https://www.txt80.com/熊猫搜书:https://xmsoushu.com/2.百度文库下载在待下载的文档的链接里面把baidu换成baiduvvveg:https://wenku.baidu.com/view/108dccfc487302768e9951e79b89680202d86b3a.html换成https://wenku.baiduvvv.com/view/108dccfc487302768e9951e79b89680202d86b3a.html3.论文下载sci-hub:https://sci-hub.se/4.网盘资源搜索大圣盘:https://www.dashengpan.com/大力盘:https://www.dalipan.com/5.影视资源搜索人人电影网:https://www.rrdynb.com/index.html -- 支持百度网盘保存电影先生:http://dyxs12.com/ -- 可以结合m3u8工具下载BD影视:https://www.bd2020.co/ -- 支持百度网盘保存热点剧更新 -- 支持百度网盘保存6.PPT模板免费下载优品PPT:https://www.ypppt.com/PPT宝藏:http://www.pptbz.com/PPT超级市场:https://www.pptsupermarket.com/office plus:https://www.officeplus.cn/7.简历模板免费下载office plus:https://www.officeplus.cn/8.图像处理图片背景消除:https://www.remove.bg/zh在线ps:https://ps.gaoding.com/#/9.临时邮箱临时邮箱,邮箱有效不限时间 https://www.linshi-email.com/YOPmail 邮箱有效5日 http://www.yopmail.com/10分钟邮箱 邮箱有效10分钟[可无限续时10分钟] https://10minutemail.net/Guerrilla 邮箱有效60分钟 https://www.guerrillamail.comTempMail 邮箱有效不限时 https://temp-mail.org/crazymailing 邮箱有效30分钟 https://www.crazymailing.com/10.jetbrains破解码Pycharm 激活码:https://docs.qq.com/doc/DUWhnVEN4VlJEQmJ3?dver=IDEA 激活码:https://ma.qieit.com/idea.html
2022年04月19日
2,029 阅读
5 评论
2 点赞
2022-04-19
2021年湖南省长沙市岳麓区教师招聘考试教综真题(2021.7.11)含解析
PDF版下载一、单项选择题(每小题1.25分。共8小题,10分)1.品德评价法是根据对学生品德的要求,对其作出肯定或否定的评价,发挥其优点,克服其缺点,促进学生进步的一种方法。下列选项中不属于运用该方法时应该注意的内容的是( ) 。 A.有明确的目的和正确的态度 B.公正合理,实事求是 C.发挥民主性,让学生参与评价 D.多作批评,少加表扬 ⒉老师在讲解知识点时,利用多感官,丰富学生直接经验来掌握知识点,老师讲解时运用了( ) 。 A.启发性原则 B.直观性原则 C.生动性原则 D.针对性原则 3.在综合实践课程《生活中的垃圾》的一课中,不仅要求学生对科学的垃圾分类进行了解,还要求学生自己进行调查,亲手将垃圾分类,这属于( ) 。 A.教学目标 B.课程目标 C.培养目标 D.教育目的 4.气质类型中的多血质的人活泼好动,善于交际,思维敏捷,容易接受新事物,但情绪情感容易产生,也容易消失。下列职业中最有可能属于多血质的人的是( ) 。 A.法官 B.汽修工 C.主持人 D.科学家 5.在做练习题时,小米做完后,会请杨老师看看是否正确,杨老师竖起大拇指表示赞同。根据加涅的信息加工理论,这属于学习过程中的() A.动机阶段 B.反馈阶段 C.回忆阶段 D.概括阶段 6.布鲁姆认为,认知目标分为识记、领悟、运用、分析、综合和评价六级水平。 学完加减法后,学生能到商店自由购物,这属于学习水平中的( )。 A.领会 B.运用 C.分析 D.评价 7.根据《新时代中小学教师职业行为十项准则》相关内容。以下漫画中的老师违反了( )的规定。 A.传播优秀文化 B.规范从教行为 C.坚守廉洁自律 D.关心爱护学生 8.李老师在日常的线上教学过程中积极进行总结和反思,李老师总结了自身的线上教学经验以论文形式发表,这体现了李老师在使用( )。 A.教育教学权 B.科学研究与学术进修权 C.指导与管理学生权 D.民主管理权二、论述题。(10分)学生是一个独立的个体,他们既是管理的对象,又是管理的主体,是有思想有感情活生生的个体。请谈谈在班级管理过程中应怎样引导学生发挥其主体作用。参考答案:一、单项选择题(每小题1.25分。共8小题,10分)1、答案:D【解析】在教育中运用品德评价法的基本要求有如下几点:1、公平、正确、合情合理;2、发扬民主,获得群众支持:3、注重宝传与教育;4、奖励为主,抑中带扬。本题比较筒单,D选项明显错误,只要审题仔细即可.2、答案:B【解析】本题当抓住题干中的关键信息“感官”、“直接经验”等可以选到直观性原则。教学原则记忆口诀免费送给大家:量力理论因材系,科思巩固启发直。 (量力性原则、理论联系实际原则、因材施教原则、系统性原则(循序渐进原则)、科学性和思想性相结合原则、巩固性原则、启发性原则、直观性原则)。大家如果做错了要去复习相应知识。3、答案:A【解析】教育目的--国家层面;培养目标--各级各类学校层面;课程目标--课程层面;教学目标--教师/教学层面。题干中是指一堂具体的课,属于教学目标.4、答案:C【解析】这个题目属于送分题,从题干中把握“活泼好动,善于交际,思维敏捷”,再根据选项即可选出主持人符合该特点。大家要好好把捱气质类型的知识点。5、答案:B【解析】 加涅的信息加工学习理论--八个阶段:洞(动机阶段)里(领会阶段)习(习得阶段)习微风,保(保持阶段〉证会(回忆阶段)盖(概括阶段)被子并且要做(作业阶段)饭(反馈阶段)。这八个阶段都是字面意思,并没有特别难理解的。 (1)动机阶段。学习者的学习是受动机推动的,学习者的动机或期望对整个学习过程都有影响。加涅认为,通过学生内部形成一种期望,可以使学生形成动机。期望是指学生对完成学习任务后将会得到满意结果的一种预期。加涅指出,理想的期望只有通过学生自己的体会才能形成,光凭外界条件是不行的。形成动机或期望,是整个学习过程的预备阶段。 (2)领会阶段。有了学习动机的学生,首先必须注意与学习有关的刺激。例如,在阅读教材时,必须注意句子的意义,而不是字体或版面设计。当学生把所注意的刺激特征从其他刺激中分化出来时,这些刺激特征就被进行知觉编码,贮存在短时记忆中。这个过程就是加涅所讲的选择性知觉。 (3习得阶段。只有当学生注意或知觉外部情境之后,学习过程才真正开始。习得阶段涉及到对新获得的刺激进行知觉编码后贮存在短时记忆中,然后再把它们进一步编码加工后转入长时记忆中。 (4)保持阶段。学生习得的信息经过编码过程后,即进入长时记忆贮存阶段,这种贮存可能是永久的。加涅认为,相对于其他阶段,我们对保持阶段了解得最少,因为最不容易对它进行调查。 (5)回忆阶段。即信息的检索阶段,学生习得的信息要通过作业表现出来,信息的提取是其中必需的一环。在这一阶段中,提取线索很重要,提供检索的方法和策略有利于回忆。 (6)概括阶段。学生提取习得信息的过程,并不始终是在与最初学习信息时相同的情境中进行的,况且,学习需要举一反三,因此,学习过程中必然有一个概括的阶段。这里的概括,就是指我们通常所讲的学习迁移。一般说来,学生学习某件事情时经历的情境越多,就越容易迁移。在教学中提供有利于把学习内容用于新情境的提示,或让学生在不同的情境中学习,都有利于迁移的发生。 (7)作业阶段。学习过程需要有作业阶段是很明显的,因为只有通过作业才能反映学生是否已习得了所学习的内容。一般说来,仅凭一次作业是很难对学生做出判断的,因此,教师需要根据几次作业才能对学生的成绩做出推断。 (8)反馈阶段。当学生完成作业后,他马上意识到自己已经达到了预期的目标,这时,教师需要给予反馈,让学生及时知道自己的作业是否正确。加涅所讲的信息反馈,类似于其他心理学家所讲的强化。6、答案:B【解析】记忆技巧:知(知识)道你(理解领会〉应(应用/运用〉该在分(分析)小棕(综合)瓶(评价). 布鲁姆认为,认知领域的目标包括知识、领会、应用、分析、综合、评价等六级水平。 1.知识 指对所学材料的记忆,包括对具体事实、方法、过程、概念和原理的回忆。它所要求的心理过程是记忆,这是最低水平的认知学习结果。 常见描述动词:回忆、叙述、匹配、朗诵、界定……例子:学生能够将《出师表》背诵出来。 ⒉.领会(理解) 指把握所学材料的意义。可以借助三种形式来表明对材料的领会:一是转换,即用自己的话或用不同于原先表达方式的方式表达自己的思想;二是解释,即对一项信息加以说明或概述;三是推断,即对事物之间的逻辑关系进行推理。领会超越了单纯的记忆,代表最低水平的理解。 常见描述动词:解释、转换、鉴别、选择、引申、猜测、改写…… 例子:学生能够用自己的话把《出师表》的意思转述出来。 3.应用 指将所学材料应用于新的情境之中,包括概念、规则、方法、规律和理论的应用。应用代表较高水平的理解。 常见描述动词:运用、修改、叙述、操作、计算、示范、改变、解释、说明……例子:学习加减法的运算之后,学生能够到模拟商店自由购物。 4.分析 指将整体材料分解成其构成成分并理解其组织结构,包括对要素的分析(如一篇论文由几个部分构成)、关系的分析(如因果关系分析)和组织原理的分析(如语法结构分析)。分析代表了比应用更高的智能水平,因为它既要理解材料的内容,又要理解其结构。 常见描述动词:分解、区分、指出、说明、图解、细分……例子:学生能够辨别所给的句子哪些自相矛盾、哪些符合逻辑。 5.综合 指将所学的零碎知识整合为知识系统。包括三个水平:用语言表达自己意见时表现的综合(如发表一篇内容独特的演说或文章);处理事物时表现的综合(如拟定一项操作计划);推演抽象关系时表现出的综合(如概括出一套抽象关系)。综合所强调的是创造能力,需要产生新的模式或结构。常见描述动词:创造、制定、编写、设计、发明……例子:结合查阅所得资料,制定国庆出游计划。 6.评价 指对所学材料(论点的陈述、小说、诗歌以及研究报告等)作价值判断的能力,包括按材料的内在标准(如材料内在组织的逻辑性)或外在标准(如材料对目标的适用性)作评价。评价是最高水平的认知学习结果,因为它要求超越原先的学习内容,并需要基于明确标准的价值判断。常见描述动词:评价、批判、证明、辩护、判断……7、答案:D【解析】政治爱国优文化,教书育人雅正言。爱护学生公自律,从教行为有安全。漫画中对学生进行侮辱,违背了关心爱护学生的规定。 一、坚定政治方向。坚持以习近平新时代中国特色社会主义思想为指导,拥护中国共产党的领导,贯彻党的教育方针;不得在教育教学活动中及其他场合有损害党中央权威、违背党的路线方针政策的言行。 二、自觉爱国守法。忠于祖国,忠于人民,恪守宪法原则,遵守法律法规,依法履行教师职责:不得损害国家利益、社会公共利益,或违背社会公序良俗。 三、传播优秀文化。带头践行社会主义核心价值观,弘扬真善美,传递正能量:不得通过课堂、论坛、讲座、信息网络及其他渠道发表、转发错误观点,或编造散布虚假信息、不良信息。 四、潜心教书育人。落实立德树人根本任务,遵循教育规律和学生成长规律,因材施教,教学相长:不得违反教学纪律,敷衍教学,或擅自从事影响教育教学本职工作的兼职兼薪行为。 五、关心爱护学生。严慈相济,诲人不倦,真心关爱学生,严格要求学生,做学生良师益友;不得歧视、侮辱学生,严禁虐待、伤害学生。 六、加强安全防范。增强安全意识,加强安全教育,保护学生安全,防范事故风险:不得在教育教学活动中遇突发事件、面临危险时,不顾学生安危,擅离职守,自行逃离。 七、坚持言行雅正。为人师表,以身作则,举止文明,作风正派,自重自爱:不得与学生发生任何不正当关系,严禁任何形式的猥亵、性骚扰行为。 八、秉持公平诚信。坚持原则,处事公道,光明磊落,为人正直:不得在招生、考试、推优、保送及绩效考核、岗位聘用、职称评聘、评优评奖等工作中徇私舞弊、弄虚作假。 九、坚守廉洁自律。严于律己,清廉从教;不得索要、收受学生及家长财物或参加由学生及家长付费的宴请、旅游、娱乐休闲等活动,不得向学生推销图书报刊、教辅材料、社会保险或利用家长资源谋取私利。 十、规范从教行为。勤勉敬业,乐于奉献,自觉抵制不良风气:不得组织、参与有偿补课,或为校外培训机构和他人介绍生源、提供相关信息。8、答案:B【解析】题干“总结了自身的线上教学经验以论文形式发表”是教师在进行教育科学研究。 《中华人民共和国教育法》和《中华人民共和国教师法》对中国教师现阶段的权利有具体规定,主要包括:(1)进行教育教学活动,开展教育教学改革和实验,简称教育教学权;(2)从事科学研究、学术交流,参加专业学术团体,在学术活动中充分发表意见,简称科研、学术权;(3)指导学生的学习和发展,评定学生的品行和学业成绩,简称对受教育者的指导、评价权;(4)获取工资报酬,享受国家规定的福利待遇以及寒暑假期的带薪休假,即获取报酬权;(5)对学校教育教学、管理工作和教育行政部门的工作提出意见和建议,通过教职工代表大会或者其他形式,参与学校的民主管理,简称参与民主管理权;(6)参加进修或者其他方式的培训,简称参加进修培训权。教师的某些与履行教育教学职责相关的权利,也是其应尽的义务,是不能随意放弃的。二、论述题。(10分)【参考答案】 1.树立以人为本、尊重学生主体地位的理念。(进行2-3句话的解释) 2鼓励学生自我管理,加强学生在班级管理中的主人翁意识的培养。 3.建立民主、平等、和谐、友爱的师生关系。 4.多组织班级集体活动,鼓励学生积极参与,激发学生的主观能动性。 5.制定班级共同的奋斗目标,并且把目标落实到小组和个人。增强学生的班级责任感。 6.在班级管理过程中,以鼓励和表扬为主,强化学生的主体意识和行为。言之有理即可得分。作为论述题每个要点都要进行相应地阐述。
2022年04月19日
510 阅读
0 评论
0 点赞
2022-04-18
javaWeb学习笔记
1、基本概念1.1、前言web开发:web,网页的意思,www.baidu.com·静态webhtml,css提供给所有人看的数据始终不会发生变化!动态web淘宝,几乎是所有的网站;提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同!技术栈:Servlet/JSP,ASP,PHP1.2、web应用程序web应用程序:可以提供浏览器访问的程序;a.html、b.html.….多个web资源,这些web资源可以被外界访问,对外界提供服务;你们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。URL这个统一的web资源会被放在同一个文件夹下,web应用程序>Tomcat:服务器一个web应用由多部分组成(静态web,动态web)html,css,jsjsp,servletJava程序jar包配置文件(Properties)Web酸用程序编写完毕后,若想提供给外界访问;需费一个服务蔬来统一管理1.3、静态web*.htm, *.html这些都是网页的后缀、如果服务器上一直存在这些东西,我们就可以直接进行读取、需要网络;静态web存在的缺点Web页面无法动态更新,所有用户看到都是同一个页面轮播图,点击特效:伪动态JavaScript[实际开发中,它用的最多]VBScript它无法和数据库交互(数据无法持久化,用户无法交互)1.4、 动态web页面会动态展示,“web页面的展示效果因人而异” 缺点:假如服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布(停机维护);优点:Web页面可以动态更新,所有用户看到都不是同一个页面它可以与数据库交互(数据持久化:注册,商品信息,用户信息………) 2、web服务器2.1、技术讲解ASP:微软:国内最早流行的就是ASP;·在HTML中嵌入了VB的脚本,ASP+COM;·在ASP开发中,基本一个页面都有几干行的业务代码,页面极其换乱·维护成本高!C#IISphp:PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,WP)无法承载大访问量的情况(局限性)jSP/Servlet: B/S;浏览和服务器C/S:客户端和服务器sun公司主推的B/S架构基于Java语言的(所有的大公司,或者一些开源的组件,都是用Java写的)可以承载三高问题带来的影响;语法像ASP,ASP->JSP,加强市场强度;2.2、web服务器服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息; lIS 微软的;ASP.,Windows中自带的 Tomcat 面向百度编程: Tomcat是Apache 软件基金会(Apache Software Foundation)的jakarta项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受lava爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。对于一个Java初学web的人来说,它是最佳的选择Tomcat 实际上运行JSP页面和Serlet。Tornct最新版易9.0工作3-5年之后,可以尝试手写Tomcat服务器;下载tomcat:安装or解压了解配置文件及目录结构这个东西的作用3、Tomcat3.1安装tomcat tomcat官网:http://tomcat.apache.org/ 3.2、Tomcat启动和配置文件夹作用: 访问测试:http://localhost:8080/ 可能遇到的问题:Java环境变量没有配置闪退问题:需要配置兼容性乱码问题:配置文件中设置可以修改 conf/logging.properties 中的 java.util.logging.ConsoleHandler.encoding = GBK 解决乱码问题3.3、配置可以配置启动的端口号tomcat的默认端口号为:8080mysql:3306http:80https:443<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />可以配置主机的名称默认的主机名为:localhost->127.0.0.1默认网站应用存放的位置为:webapps <Host name="www.qinjiang.com" appBase="webapps" unpackWARs="true" autoDeploy="true">**高难度面试题: 请你谈谈网站是如何进行访问的!**输入一个域名;回车检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问 127.0.0.1 www.qinjiang.com没有:去DNS服务器找,找到的话就返回,找不到就返回找不到; 4.可以配置一下环境变量(可选性)3.4、发布一个web网站不会就先模仿将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了网站应该有的结构--webapps :Tomcat服务器的web目录 -ROOT -kuangstudy :网站的目录名 - WEB-INF -classes : java程序 -lib:web应用所依赖的jar包 -web.xml :网站配置文件 - index.html 默认的首页 - static -css -style.css -js -img -.....HTTP协议:面试 Maven:构建工具Maven安装包Servlet入门HelloWorld!Servlet配置 ·原理4、Http4.1、什么是HTTPHTTP(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。文本:html,字符串,…超文本:图片,音乐,视频,定位,地图.……端口:80Https:安全的端口:4434.2、两个时代http1.0HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接http2.0HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。4.3、Http请求客户端–发请求(Request)–服务器百度:Request URL:https://www.baidu.com/ 请求地址 Request Method:GET get方法/post方法 Status Code:200 OK 状态码:200 Remote(远程) Address:14.215.177.39:443 Accept:text/html Accept-Encoding:gzip, deflate, br Accept-Language:zh-CN,zh;q=0.9 语言 Cache-Control:max-age=0 Connection:keep-alive1、请求行请求行中的请求方式:GET请求方式:Get,Post,HEAD,DELETE,PUT,TRACT.…get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。2、消息头Accept:告诉浏览器,它所支持的数据类型 Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1 Accept-Language:告诉浏览器,它的语言环境 Cache-Control:缓存控制 Connection:告诉浏览器,请求完成是断开还是保持连接 HOST:主机..../.4.4、Http响应服务器–响应…….客户端百度:Cache-Control:private 缓存控制 Connection:Keep-Alive 连接 Content-Encoding:gzip 编码 Content-Type:text/html 类型 1、响应体Accept:告诉浏览器,它所支持的数据类型 Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1 Accept-Language:告诉浏览器,它的语言环境 Cache-Control:缓存控制 Connection:告诉浏览器,请求完成是断开还是保持连接 HOST:主机..../. Refresh:告诉客户端,多久刷新一次; Location:让网页重新定位;2、响应状态码200:请求响应成功200 3xx:请求重定向重定向:你重新到我给你新位置去;4xx:找不到资源404:资源不存在;5xx:服务器错误500:服务器代码错误502:网关错误常见面试题: 当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?5、Maven我为什么要学习这个技术?在Javaweb开发中,需要使用大量的jar包,我们手动去导入;如何能够让一个东西自动帮我导入和配置这个jar包。由此,Maven诞生了!5.1 Maven项目架构管理工具我们目前用来就是方便导入jar包的! Maven的核心思想:约定大于配置有约束,不要去违反。Maven会规定好你该如何去编写我们Java代码,必须要按照这个规范来;5.2下载安装Maven官网:https://maven.apache.org/ 下载完成后,解压即可; 小狂神友情建议:电脑上的所有环境都放在一个文件夹下,方便管理;5.3配置环境变量在我们的系统环境变量中配置如下配置:M2\_HOME maven目录下的bin目录MAVEN\_HOME maven的目录在系统的path中配置%MAVEN\_HOME%\bin 测试Maven是否安装成功,保证必须配置完毕!5.4阿里云镜像镜像:mirrors作用:加速我们的下载国内建议使用阿里云的镜像<mirror> <id>nexus-aliyun</id> <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>D:Enmvironment\apache-maven-3.6.2conf\settings.xml (狂神老师配置源和仓库的文件位置)5.5本地仓库在本地的仓库,远程仓库; 建立一个本地仓库:localRepository<localRepository>D:\Environment\apache-maven-3.6.2\maven-repo</localRepository>5.6 ~ 5.13笔记-下载地址下载地址:https://lanzoui.com/ibuibxi本站缓存后面的 5.6 ~ 5.13 + 案例演示 (图)**后面第 5 剩下部分的笔记建议配合狂神的 “javaweb-06:IDEA中Maven的操作”、“javaweb-07:解决大家遇到的一些问题” 仔细(回)看**6、Servlet6.1、Servlet简介Servlet就是sun公司开发动态web的一门技术Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:编写一个类,实现Serlet接口把开发好java类部署到web服务器中。把实现了Servlet接口的Java程序叫做,ServletSerlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServled6.2、HelloServlet构建一个普通的Maven项目,等理面的sc目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就题Maven主工程;关于Maven父子工程的理解; 父项目中会有 <modules> <module>servlet-01</module> </modules>子项目会有 <parent> <artifactId>javaweb-02-servlet</artifactId> <groupId>com.kuang</groupId> <version>1.0-SNAPSHOT</version> </parent>父项目中的java子项目可以直接使用son extends fatherMaven环境优化修改web.xml为最新的<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> </web-app>将maven的结构搭建完整编写一个Servlet程序编写一个普通类实现Servlet接口,这里我们直接继承HttpServlet public class HelloServlet extends HttpServlet { //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //ServletOutputStream outputStream = resp.getOutputStream(); PrintWriter writer = resp.getWriter(); //响应流 writer.print("Hello,Serlvet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } 编写Servlet的映射 为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需 要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径; <!--注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.kuang.servlet.HelloServlet</servlet-class> </servlet> <!--Servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>配置Tomcat 注意:配置项目发布的路径就可以了 启动测试,OK! 6.3、Servlet原理Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会: 6.4、Mapping问题一个Servlet可以指定一个映射路径 <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>一个servlet可以指定多个映射路径 <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello4</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello5</url-pattern> </servlet-mapping> 一个servlet可以指定通用映射路径 <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>默认请求路径 <!--默认请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>指定一些后缀或者前缀等等… <!--可以自定义后缀实现请求映射 注意点,*前面不能加项目映射的路径 hello/sajdlkajda.qinjiang --> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.qinjiang</url-pattern> </servlet-mapping>优先级问题 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求; <!--404--> <servlet> <servlet-name>error</servlet-name> <servlet-class>com.kuang.servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> 6.5、ServletContextweb容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;1、共享数据我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //this.getInitParameter() 初始化参数 //this.getServletConfig() Servlet配置 //this.getServletContext() Servlet上下文 ServletContext context = this.getServletContext(); String username = "秦疆"; //数据 context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username } } public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String username = (String) context.getAttribute("username"); resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); resp.getWriter().print("名字"+username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.kuang.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet> <servlet-name>getc</servlet-name> <servlet-class>com.kuang.servlet.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getc</servlet-name> <url-pattern>/getc</url-pattern> </servlet-mapping>测试访问结果;2、获取初始化参数 <!--配置一些web应用初始化参数--> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/mybatis</param-value> </context-param>protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); String url = context.getInitParameter("url"); resp.getWriter().print(url); }3、请求转发@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); System.out.println("进入了ServletDemo04"); //RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径 //requestDispatcher.forward(req,resp); //调用forward实现请求转发; context.getRequestDispatcher("/gp").forward(req,resp); } 4、读取资源文件 Properties在java目录下新建properties在resources目录下新建properties发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath: 思路:需要一个文件流username=root12312 password=zxczxczxcpublic class ServletDemo05 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties"); Properties prop = new Properties(); prop.load(is); String user = prop.getProperty("username"); String pwd = prop.getProperty("password"); resp.getWriter().print(user+":"+pwd); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } 访问测试即可ok;6.6、HttpServletResponseweb服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest 对象,代表响应的一个HttpServletResponse;如果要获取客户端请求过来的参数:找HttpServletRequest如果要给客户端响应一些信息:找HttpServletResponse1、简单分类负责向浏览器发送数据的方法 servletOutputstream getOutputstream() throws IOException; Printwriter getwriter() throws IOException;负责向浏览器发送响应头的方法void setCharacterEncoding(String var1); void setContentLength(int var1); void setContentLengthLong(long var1); void setContentType(String var1); void setDateHeader(String varl,long var2) void addDateHeader(String var1,long var2) void setHeader(String var1,String var2); void addHeader(String var1,String var2); void setIntHeader(String var1,int var2); void addIntHeader(String varl,int var2);响应的状态码 2、下载文件向浏览器输出消息(一直在讲,就不说了)下载文件要获取下载文件的路径下载的文件名是啥?设置想办法让浏览器能够支持下载我们需要的东西获取下载文件的输入流创建缓冲区获取OutputStream对象将FileOutputStream流写入到bufer缓冲区使用OutputStream将缓冲区中的数据输出到客户端! @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1.待下载文件的路径和文件名 String filePath = "C:\\Users\\itrb\\Desktop\\数据标注\\res.jpg"; String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1); // 2.设置让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); // 3.获取待下载文件的输入流 FileInputStream fileInputStream = new FileInputStream(filePath); //4.创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; // 5.获取输出流 OutputStream out = resp.getOutputStream(); // 6.往输出流写入文件 while ((len=fileInputStream.read(buffer))>0){ out.write(buffer); } // 7.关闭流 fileInputStream.close(); out.close(); }3、验证码功能验证怎么来的?前端实现后端实现,需要用到Java的图片类,生产一个图片package top.inat.servlet; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; public class ImageServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //让浏览器3秒自动刷新一次; resp.setHeader("refresh","3"); //在内存中创建一个图片 BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB); //得到图片 Graphics2D g = (Graphics2D) image.getGraphics(); //笔 //设置图片的背景颜色 g.setColor(Color.white); g.fillRect(0,0,80,20); //给图片写数据 g.setColor(Color.BLUE); g.setFont(new Font(null,Font.BOLD,20)); g.drawString(makeNum(),0,20); //告诉浏览器,这个请求用图片的方式打开 resp.setContentType("image/jpeg"); //网站存在缓存,不让浏览器缓存 resp.setDateHeader("expires",-1); resp.setHeader("Cache-Control","no-cache"); resp.setHeader("Pragma","no-cache"); //把图片写给浏览器 ImageIO.write(image,"jpg", resp.getOutputStream()); } //生成随机数 private String makeNum(){ Random random = new Random(); String num = random.nextInt(9999999) + ""; StringBuffer sb = new StringBuffer(); for (int i = 0; i < 7-num.length() ; i++) { sb.append("0"); } num = sb.toString() + num; return num; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }<servlet> <servlet-name>image</servlet-name> <servlet-class>top.inat.servlet.ImageServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>image</servlet-name> <url-pattern>/image</url-pattern> </servlet-mapping> 常见场景:用户登录 void sendRedirect(String var1) throws IOException;测试:@override protected void doGet(HttpservletRequest req, HttpservletResponse resp) throws ServletException, IOException { resp. sendRedirect("/r/img");//重定向 /* resp. setHeader("Location","/r/img"); resp. setstatus (302); */ } index.jsp<html> <head> <meta charset="GBK"> <title>Login Test</title> </head> <body> <h2>Hello World!</h2> <%--这里提交交的路径,需要寻找到项目的路径--%> <%--${pageContext.request.contextPath}代表当前的项目--%> <form action="${pageContext.request.contextPath}/login" method="get"> username: <input type="text" name="username"> <br> password: <input type="password" name="password"> <br> <input type="submit"> </form> </body> </html>RequestTest.javapackage top.inat.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //处理方求 String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username + ":" + password); resp.sendRedirect("/success.jsp"); } }重定向页面success.jsp<%@ page contentType="text/html; charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>success</h1> </body> </html>web.xml配置<servlet> <servlet-name>login</servlet-name> <servlet-class>top.inat.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>导入依赖的jar包<dependencies> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> </dependencies>6.7、HttpServletRequestHttpServletRequest代表客户端的请求,用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息; 获取参数,请求转发 自己创建类,且需要继承HttpServlet类@Override protected void doGet(HttpservletRequest req. HttpservletResponse resp) throws ServletException, IOException { req. setcharacterEncoding("utf-8"); resp.setcharacterEncoding("utf-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobbys = req.getParameterValues("hobbys"); System.out.println("=========="); //后台接收中文乱码问题 System. out.println(username); System. out.println(password); System. out.println(Arrays.tostring(hobbys)); System. out.println("============"); system. out.println(req.getContextPath()); //通过请求转发 //这里的/代表当前的web应用 req.getRequestDispatcher("/success.jsp").forward(req,resp); }7、Cookie、Session7.1、会话会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话;有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话;你能怎么证明你是西开的学生?发票 西开给你发票学校登记 西开标记你来过了一个网站,怎么证明你来过?客户端 服务端服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了; cookie服务器登记你来过了,下次你来的时候我来匹配你; seesion7.2、保存会话的两种技术cookie客户端技术 (响应,请求)session服务器技术,利用这个技术,可以保存用户的会话信息? 我们可以把信息或者数据放在Session中!常见常见:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!7.3、Cookie从请求中拿到cookie信息服务器响应给客户端cookieCookie[] cookies = req.getCookies(); //获得Cookie cookie.getName(); //获得cookie中的key cookie.getValue(); //获得cookie中的vlaue new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie cookie.setMaxAge(24*60*60); //设置cookie的有效期 resp.addCookie(cookie); //响应给客户端一个cookiecookie:一般会保存在本地的 用户目录下 appdata;一个网站cookie是否存在上限!聊聊细节问题一个Cookie只能保存一个信息;一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;Cookie大小有限制4kb;300个cookie浏览器上限删除Cookie;不设置有效期,关闭浏览器,自动失效;设置有效期时间为 0 ;编码解码:URLEncoder.encode("秦疆","utf-8") URLDecoder.decode(cookie.getValue(),"UTF-8")7.4、Session(重点) 什么是Session:服务器会给每一个用户(浏览器)创建一个Seesion对象;一个Seesion独占一个浏览器,只要浏览器没有关闭,这个Session就存在;用户登录之后,整个网站它都可以访问!–> 保存用户的信息;保存购物车的信息……Session和cookie的区别:Cookie是把用户的数据写给用户的浏览器,浏览器保存 (可以保存多个)Session把用户的数据写到用户独占Session中,服务器端保存 (保存重要的信息,减少服务器资源的浪费)Session对象由服务创建;使用场景:保存一个登录用户的信息;购物车信息;在整个网站中经常会使用的数据,我们将它保存在Session中;设置Session:package top.inat.servlet; import top.inat.pojo.Person; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class SetSession extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //解决乱码问题 req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=utf-8"); //得到Session HttpSession session = req.getSession(); //给Session中存东西 session.setAttribute("user",new Person("秦疆",1)); //获取Session的ID String sessionId = session.getId(); resp.getWriter().write("session创建成功,ID:"+sessionId); //Session创建的时候做了什么事情; //Cookie cookie = new Cookie("JSESSIONID",sessionId); //resp.addCookie(cookie); } }获取Session:package top.inat.servlet; import top.inat.pojo.Person; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.URLEncoder; public class GetSession extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //得到Session HttpSession session = req.getSession(); Object sessionData = session.getAttribute("user"); if(sessionData!=null){ Person person = (Person)sessionData; System.out.println(person.toString()); resp.setCharacterEncoding("UTF-8"); resp.getWriter().write("session is : "+person.toString()); }else { resp.setCharacterEncoding("UTF-8"); resp.getWriter().write("session is : null"); } } }注销Session:HttpSession session = req.getSession(); session.removeAttribute("user"); //手动注销Session session.invalidate();会话自动过期:web.xml配置<!--设置Session默认的失效时间--> <session-config> <!--15分钟后Session自动失效,以分钟为单位--> <session-timeout>15</session-timeout> </session-config>8、JSP8.1、什么是JSPJava Server Pages : Java服务器端页面,也和Servlet一样,用于动态Web技术!最大的特点:写JSP就像在写HTML区别:HTML只给用户提供静态的数据JSP页面中可以嵌入JAVA代码,为用户提供动态数据;8.2、JSP原理思路:JSP到底怎么执行的!代码层面没有任何问题服务器内部工作tomcat中有一个work目录;IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目录我电脑的地址:C:\Users\Administrator.IntelliJIdea2018.1\system\tomcat\Unnamed\_javaweb-session-cookie\work\Catalina\localhost\ROOT\org\apache\jsp发现页面转变成了Java程序! 浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!JSP最终也会被转换成为一个Java类!JSP 本质上就是一个Servlet//初始化 public void _jspInit() {} //销毁 public void _jspDestroy() {} //JSPService public void _jspService(.HttpServletRequest request,HttpServletResponse response){}判断请求内置一些对象final javax.servlet.jsp.PageContext pageContext; //页面上下文 javax.servlet.http.HttpSession session = null; //session final javax.servlet.ServletContext application; //applicationContext final javax.servlet.ServletConfig config; //config javax.servlet.jsp.JspWriter out = null; //out final java.lang.Object page = this; //page:当前 HttpServletRequest request //请求 HttpServletResponse response //响应输出页面前增加的代码response.setContentType("text/html"); //设置响应的页面类型 pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;以上的这些个对象我们可以在JSP页面中直接使用!在JSP页面中;只要是 JAVA代码就会原封不动的输出;如果是HTML代码,就会被转换为:out.write("<html>\r\n");这样的格式,输出到前端!8.3、JSP基础语法任何语言都有自己的语法,JAVA中有,。 JSP 作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java所有语法都支持!JSP表达式 <%--JSP表达式 作用:用来将程序的输出,输出到客户端 <%= 变量或者表达式%> --%> <%= new java.util.Date()%>jsp脚本片段<%--jsp脚本片段--%> <% int sum = 0; for (int i = 1; i <=100 ; i++) { sum+=i; } out.println("<h1>Sum="+sum+"</h1>"); %>脚本片段的再实现 <% int x = 10; out.println(x); %> <p>这是一个JSP文档</p> <% int y = 2; out.println(y); %> <hr> <%--在代码嵌入HTML元素--%> <% for (int i = 0; i < 5; i++) { %> <h1>Hello,World <%=i%> </h1> <% } %>JSP声明 <%! static { System.out.println("Loading Servlet!"); } private int globalVar = 0; public void kuang(){ System.out.println("进入了方法Kuang!"); } %>JSP声明:会被编译到JSP生成Java的类中!其他的,就会被生成到\_jspService方法中!在JSP,嵌入Java代码即可!<%%> <%=%> <%!%> <%--注释--%>JSP的注释,不会在客户端显示,HTML就会!8.4、JSP指令<%@page args.... %> // 定制错误页面等 <%@include file=""%> <%--@include会将两个页面合二为一--%> <%@include file="common/header.jsp"%> <h1>网页主体</h1> <%@include file="common/footer.jsp"%> <hr> <%--jSP标签 jsp:include:拼接页面,本质还是三个 --%> <jsp:include page="/common/header.jsp"/> <h1>网页主体</h1> <jsp:include page="/common/footer.jsp"/>8.5、9大内置对象PageContext 存东西Request 存东西ResponseSession 存东西Application 【SerlvetContext】 存东西config 【SerlvetConfig】outpage ,不用了解exceptionpageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效 request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据 session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器 application.setAttribute("name4","秦疆4号"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;8.6、JSP标签、JSTL标签、EL表达式<!-- 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>EL表达式: ${ }获取数据执行运算获取web开发的常用对象JSP标签<%--jsp:include--%> <%-- http://localhost:8080/jsptag.jsp?name=kuangshen&age=12 --%> <jsp:forward page="/jsptag2.jsp"> <jsp:param name="name" value="kuangshen"></jsp:param> <jsp:param name="age" value="12"></jsp:param> </jsp:forward>JSTL表达式JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!格式化标签SQL标签XML 标签核心标签 (掌握部分)JSTL标签库使用步骤引入对应的 taglib使用其中的方法在Tomcat 也需要引入 jstl的包,否则会报错:JSTL解析错误c:if<head> <title>Title</title> </head> <body> <h4>if测试</h4> <hr> <form action="coreif.jsp" method="get"> <%-- EL表达式获取表单中的数据 ${param.参数名} --%> <input type="text" name="username" value="${param.username}"> <input type="submit" value="登录"> </form> <%--判断如果提交的用户名是管理员,则登录成功--%> <c:if test="${param.username=='admin'}" var="isAdmin"> <c:out value="管理员欢迎您!"/> </c:if> <%--自闭合标签--%> <c:out value="${isAdmin}"/> </body>c:choose c:when<body> <%--定义一个变量score,值为85--%> <c:set var="score" value="55"/> <c:choose> <c:when test="${score>=90}"> 你的成绩为优秀 </c:when> <c:when test="${score>=80}"> 你的成绩为一般 </c:when> <c:when test="${score>=70}"> 你的成绩为良好 </c:when> <c:when test="${score<=60}"> 你的成绩为不及格 </c:when> </c:choose> </body>c:forEach<% ArrayList<String> people = new ArrayList<>(); people.add(0,"张三"); people.add(1,"李四"); people.add(2,"王五"); people.add(3,"赵六"); people.add(4,"田六"); request.setAttribute("list",people); %> <%-- var , 每一次遍历出来的变量 items, 要遍历的对象 begin, 哪里开始 end, 到哪里 step, 步长 --%> <c:forEach var="people" items="${list}"> <c:out value="${people}"/> <br> </c:forEach> <hr> <c:forEach var="people" items="${list}" begin="1" end="3" step="1" > <c:out value="${people}"/> <br> </c:forEach> 9、JavaBean实体类JavaBean有特定的写法:必须要有一个无参构造属性必须私有化必须有对应的get/set方法;一般用来和数据库的字段做映射 ORM;ORM :对象关系映射表—>类字段–>属性行记录---->对象people表idnameageaddress1秦疆1号3西安2秦疆2号18西安3秦疆3号100西安class People{ private int id; private String name; private int id; private String address; } class A{ new People(1,"秦疆1号",3,"西安"); new People(2,"秦疆2号",3,"西安"); new People(3,"秦疆3号",3,"西安"); }过滤器文件上传邮件发送JDBC 复习 : 如何使用JDBC , JDBC crud, jdbc 事务10、MVC三层架构什么是MVC: Model view Controller 模型、视图、控制器10.1、以前的架构用户直接访问控制层,控制层就可以直接操作数据库;servlet--CRUD-->数据库 弊端:程序十分臃肿,不利于维护 servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码 架构:没有什么是加一层解决不了的! 程序猿调用 ↑ JDBC (实现该接口) ↑ Mysql Oracle SqlServer ....(不同厂商)10.2、MVC三层架构![[(img-BWDJGUCN-1588757845419)(JavaWeb.assets/1568424227281.png)]](/usr/uploads/auto_save_image/9592f95019658738dc15d361abdf4563.png)Model业务处理 :业务逻辑(Service)数据持久层:CRUD (Dao - 数据持久化对象)View展示数据提供链接发起Servlet请求 (a,form,img…)Controller (Servlet)接收用户的请求 :(req:请求参数、Session信息….)交给业务层处理对应的代码控制视图的跳转登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库11、Filter (重点)比如 Shiro安全框架技术就是用Filter来实现的Filter:过滤器 ,用来过滤网站的数据;处理中文乱码登录验证….(比如用来过滤网上骂人的话,我***我自己 0-0) Filter开发步骤:导包编写过滤器导包不要错 (注意)![[(img-HHsC3JBD-1588757845420)(JavaWeb.assets/1568425162525.png)]](/usr/uploads/auto_save_image/d77950ebea39793fce0f02c34f7dd8d5.png)实现Filter接口,重写对应的方法即可 public class CharacterEncodingFilter implements Filter { //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现! public void init(FilterConfig filterConfig) throws ServletException { System.out.println("CharacterEncodingFilter初始化"); } //Chain : 链 /* 1. 过滤中的所有代码,在过滤特定请求的时候都会执行 2. 必须要让过滤器继续同行 chain.doFilter(request,response); */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=UTF-8"); System.out.println("CharacterEncodingFilter执行前...."); chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止! System.out.println("CharacterEncodingFilter执行后...."); } //销毁:web服务器关闭的时候,过滤器会销毁 public void destroy() { System.out.println("CharacterEncodingFilter销毁"); } } 在web.xml中配置 Filter <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <!--只要是 /servlet的任何请求,会经过这个过滤器--> <url-pattern>/servlet/*</url-pattern> <!--<url-pattern>/*</url-pattern>--> <!-- 别偷懒写个 /* --> </filter-mapping>12、监听器实现一个监听器的接口;(有n种监听器)编写一个监听器实现监听器的接口…依赖的jar包//统计网站在线人数 : 统计session public class OnlineCountListener implements HttpSessionListener { //创建session监听: 看你的一举一动 //一旦创建Session就会触发一次这个事件! public void sessionCreated(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); System.out.println(se.getSession().getId()); Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(1); }else { int count = onlineCount.intValue(); onlineCount = new Integer(count+1); } ctx.setAttribute("OnlineCount",onlineCount); } //销毁session监听 //一旦销毁Session就会触发一次这个事件! public void sessionDestroyed(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(0); }else { int count = onlineCount.intValue(); onlineCount = new Integer(count-1); } ctx.setAttribute("OnlineCount",onlineCount); } /* Session销毁: 1. 手动销毁 getSession().invalidate(); 2. 自动销毁 */ } web.xml中注册监听器<!--注册监听器--> <listener> <listener-class>com.kuang.listener.OnlineCountListener</listener-class> </listener>看情况是否使用!13、过滤器、监听器常见应用监听器:GUI编程中经常使用;public class TestPanel { public static void main(String[] args) { Frame frame = new Frame("中秋节快乐"); //新建一个窗体 Panel panel = new Panel(null); //面板 frame.setLayout(null); //设置窗体的布局 frame.setBounds(300,300,500,500); frame.setBackground(new Color(0,0,255)); //设置背景颜色 panel.setBounds(50,50,300,300); panel.setBackground(new Color(0,255,0)); //设置背景颜色 frame.add(panel); frame.setVisible(true); //监听事件,监听关闭事件 frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { super.windowClosing(e); } }); } }用户登录之后才能进入主页!用户注销后就不能进入主页了!用户登录之后,向Sesison中放入用户的数据进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; if (request.getSession().getAttribute(Constant.USER_SESSION)==null){ response.sendRedirect("/error.jsp"); } chain.doFilter(request,response);14、JDBC什么是JDBC : Java连接数据库!![[(img-rZzTXmtn-1588757845422)(JavaWeb.assets/1568439601825.png)]](/usr/uploads/auto_save_image/db8ad90b34dbe3b84a5f730e5148e3ab.png)需要jar包的支持:java.sqljavax.sqlmysql-conneter-java… 连接驱动(必须要导入)实验环境搭建 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','zs@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; 导入数据库依赖<!--mysql的驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>IDEA中连接数据库:![[(img-XErw4ElS-1588757845423)(JavaWeb.assets/1568440926845.png)]](/usr/uploads/auto_save_image/c0a6ec2b544b455988beeb40af2afae8.png)JDBC 固定步骤:加载驱动连接数据库,代表数据库向数据库发送SQL的对象Statement : CRUD编写SQL (根据业务,不同的SQL)执行SQL关闭连接(先开的后关)public class TestJdbc { public static void main(String[] args) throws ClassNotFoundException, SQLException { //配置信息 //useUnicode=true&characterEncoding=utf-8 解决中文乱码 String url="jdbc:mysql://localhost:3306/jdbc?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,PreparedStatement : CRUD 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("name="+rs.getObject("name")); System.out.println("password="+rs.getObject("password")); System.out.println("email="+rs.getObject("email")); System.out.println("birthday="+rs.getObject("birthday")); } //6.关闭连接,释放资源(一定要做) 先开后关 rs.close(); statement.close(); connection.close(); } } 预编译SQLpublic class TestJDBC2 { public static void main(String[] args) throws Exception { //配置信息 //useUnicode=true&characterEncoding=utf-8 解决中文乱码 String url="jdbc:mysql://localhost:3306/jdbc?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) values (?,?,?,?,?);"; //4.预编译 PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1,2);//给第一个占位符? 的值赋值为1; preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java; preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456; preparedStatement.setString(4,"24736743@qq.com");//给第四个占位符? 的值赋值为1; preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime()); //5.执行SQL int i = preparedStatement.executeUpdate(); if (i>0){ System.out.println("插入成功@"); } //6.关闭连接,释放资源(一定要做) 先开后关 preparedStatement.close(); connection.close(); } } 事务要么都成功,要么都失败!ACID原则:保证数据的安全。开启事务 事务提交 commit() 事务回滚 rollback() 关闭事务 转账: A:1000 B:1000 A(900) --100--> B(1100) Junit单元测试依赖<!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>简单使用@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!@Test public void test(){ System.out.println("Hello"); }![[(img-OsUubVNQ-1588757845424)(JavaWeb.assets/1568442261610.png)]](/usr/uploads/auto_save_image/df333138d8696914cc043efe81cf1c40.png)失败的时候是红色:![[(img-qv2oTEGI-1588757845425)(JavaWeb.assets/1568442289597.png)]](/usr/uploads/auto_save_image/05bc8e3d626d91daf31b62ef3b779101.png)搭建一个环境CREATE TABLE account( id INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(40), money FLOAT ); INSERT INTO account(`name`,money) VALUES('A',1000); INSERT INTO account(`name`,money) VALUES('B',1000); INSERT INTO account(`name`,money) VALUES('C',1000); @Test public void test() { //配置信息 //useUnicode=true&characterEncoding=utf-8 解决中文乱码 String url="jdbc:mysql://localhost:3306/jdbc?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(); connection.commit();//以上两条SQL都执行成功了,就提交事务! 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(); } } }15、SMBMS(超市管理项目)完结
2022年04月18日
739 阅读
0 评论
0 点赞
2022-04-17
python 抓取豆瓣影视数据
python 抓取豆瓣影视数据1.代码import re douban_id = 6965622 import requests from bs4 import BeautifulSoup headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36' } url = "https://movie.douban.com/subject/%s/" % douban_id html = requests.get(url=url,headers=headers) soup = BeautifulSoup(html.text) data = soup.find_all("script",{"type":"application/ld+json"})[0].string data = data.replace("\n"," ") data =eval(data) data_handle = {} data_handle["name"] = data["name"] data_handle["image"] = data["image"] director_str = "" for director in data["director"]: director_str += director["name"].split(" ")[0]+";" data_handle["director"] = director_str actor_str = "" for actor in data["actor"]: actor_str += actor["name"].split(" ")[0]+";" data_handle["actor"] = actor_str author_str = "" for author in data["author"]: author_str += author["name"].split(" ")[0]+";" data_handle["author"] = author_str genre_str = "" for genre in data["genre"]: genre_str += genre+";" data_handle["genre"] = genre_str data_handle["datePublished"] = data["datePublished"] data_handle["year"] = data["datePublished"].split("-")[0] data_handle["avg_score"] = data["aggregateRating"]["ratingValue"] data_handle["description"] = data["description"] if re.findall("<span class=\"pl\">又名:</span>(.*?)<br/>",html.text): data_handle["sub"] = re.findall("<span class=\"pl\">又名:</span>(.*?)<br/>",html.text)[0] if re.findall("<span class=\"pl\">语言:</span>(.*?)<br/>",html.text): data_handle["lang"] = re.findall("<span class=\"pl\">语言:</span>(.*?)<br/>",html.text)[0] if re.findall("<span class=\"pl\">集数:</span>(.*?)<br/>",html.text): data_handle["total"] = re.findall("<span class=\"pl\">集数:</span>(.*?)<br/>",html.text)[0] if re.findall("<span class=\"pl\">制片国家/地区:</span>(.*?)<br/>",html.text): data_handle["area"] = re.findall("<span class=\"pl\">制片国家/地区:</span>(.*?)<br/>",html.text)[0] print(data_handle)2.执行结果{ 'name': '悬崖', 'image': '/usr/uploads/auto_save_image/35191c14b33cceb1e4d4d49bb49781c8.jpg', 'director': '刘进;', 'actor': '张嘉益;宋佳;程煜;李洪涛;咏梅;姬他;孙浩;徐程;林源;林龙麒;马丽;杨一威;封柏;刘宸希;涩谷天马;林千雯;张东升;孙鹏;施琅;钱漪;王兴君;宋家腾;张瀚文;', 'author': '全勇先;', 'genre': '剧情;历史;战争;悬疑;', 'datePublished': '2012-01-01', 'year': '2012', 'avg_score': '8.5', 'description': '上世纪30年代末,古老的中华大地正经受着最为苦难的时刻。外有日寇铁蹄进犯,内有不同派别势力的斗争碾压,战火连绵,生灵涂炭。为了获取重要的情报,共产党方面派出周乙(张嘉译 饰)和顾秋妍(宋佳 饰)假扮夫...', 'sub': ' The Brink', 'lang': ' 汉语普通话', 'total': ' 40', 'area': ' 中国大陆' }
2022年04月17日
627 阅读
0 评论
0 点赞
2022-04-14
密码学与网络安全第七版部分课后习题答案
第0章 序言1.课后题汇总(仅部分)第一章 思考题:1、2、4、5第二章 习题:10、12、16第三章 习题:9第四章 思考题:4、5、6第五章 习题:11第六章 习题:2、6第七章 思考题:2、3、4 习题:4、7、8第八章 习题:2第九章 思考题:5、6 习题:2、3第十章 习题:1、2第十一章 思考题:1、2、3第十二章 思考题:1、3、4、7第十三章 思考题:5第十四章 思考题:2、7、10、11第十五章 思考题:2、5第十七章 思考题:3、8、9第二十章 思考题:2、3、4、5、8第1章 计算机与网络安全的概念1.什么是OSI安全架构?(p6)OSI 安全框架是提供安全的一种组织方法,而且因为这个框架是作为国际标准而开发的, 所有计算机和通信商已经在他们的产品和服务上开发了这些安全特性,这些产品和服务与安 全服务是和安全机制的结构化定义相关联的。OSI安全框架主要关注安全攻击、机制和服务。安全攻击:任何危及信息系统安全的行为安全机制:用来检测、阻止攻击或从攻击状态恢复到正常状态的过程(或实现该过程的设备)。安全服务:加强数据处理系统和信息传输的安全性的一种处理过程或通信服务,目的在于利用一种或多种安全机制进行反攻击。2.被动安全威胁与主动安全威胁有何区别?(书上没找着,参考p6-p7的主动攻击和被动攻击)被动威胁的本质是窃听或监视数据传输,主动威胁包含数据流的改写和错误数据流的添加。3.列出并简要定义安全服务的种类。(p8)①认证:保证通信的实体是它所声明的实体②访问控制:阻止对资源的非授权使用(即这项服务控制谁能访问资源,在什么条件下可以访问,这些访问的资源可用于做什么)③数据保密性:保护数据免于非授权泄露④数据完整性:保证收到的数据的确是授权实体发出的数据(即未修改、插入、删除或重播)⑤不可否认性:防止整个或部分通信过程中,任一通信实体进行否认的行为。4.列出并简要定义安全机制的种类。(p10)①特定安全机制:可以并入适当的安全协议层提供一些OSI安全服务②普遍的安全机制:不局限与任何特定的OSI安全服务或协议层的机制第2章 数论基础1.求$Z_5$中各非0元素的乘法逆元。(p25)参考答案:STEP1:列出 $x \times y \ mod \ 5$ 并记录结果为1的情况x/y0123400000010$\color{red}{1}$2342024$\color{red}{1}$3303$\color{red}{1}$424043 $\color{red}{1}$STEP2:由此得到$Z_5$中的各非0元素的乘法逆元分别为涉及知识:①什么是$Z_5$?比n小的非负整数的集合为$Z_n,Z_n={0,1,…,(n-1)}$,这个集合称为类集,或者模n的剩余类。②什么是乘法逆元?简单来说就是这样:在$(mod \ p)$意义下($p$是素数),如果$a*a'=1$,那么我们就说$a'$是$a$的逆元。当然啦,反过来,$a$也是$a'$的逆元。也就是说,如果$(a*a')mod p=1$,那么我们就说$a'$是$a$的逆元。求法:列表就行Eg:求Z8中各元素的乘法逆元STEP1:模8乘法 $(x*y \ mod \ 8)$ STEP2:模8乘法的逆2.求gcd(24140,16762)和gcd(4655,12075)(p22-p23)gcd(24140,16762)被除数除数商余数241401676217378167627378220067378200631306200613061646130664626864668934683420因此$gcd(24140,16762)=34$gcd(4655,12075)被除数除数商余数120754655227654655276511890276518901875189087521408751406351403540因此$(4655,12075)=35$3.用扩展欧几里得算法求下列乘法逆元(p29)核心公式:$q_i=r_i-2/r_i-1$$r_i=r_i-2-r_i-1*q_i$$x_i=x_i-2-q_i*x_i-1$$y_i=y_i-2-q_i*y_i-1$解题模板参考下题(a)(a)1234mod4321(b)24140mod40902i$r_i$$q_i$$x_i$$y_i$-140902 10024140 0111676211-1273781-123200633-5413603-10175646113-226682-36617349337-571802 因为无余数($r_i$)为0,所以无乘法逆元。(c)550mod1769i$r_i$$q_i$$x_i$$y_i$-11769 100550 01111931-32744-41334515-164291-929516114-456131-237473137-1198$\color{red}{1}$4-171$\color{red}{550}$903 验证:$$ 550 \times 550 + (-171) \times 1769 = 1 $$所以550为550mod1769的乘法逆元。第3章 传统加密技术1. Playfair密码解密当海军上尉John F.Kennedy 管理的美国巡逻船PT-109被日本毁灭者击沉时,位于澳大利亚的一个无线站截获了一条用Playfair密码加密的消息:KXJEY UREBE ZWEHE WRYTU HEYFS KREHE GOYFI WTTTU OLKSY CAJPO BOTEI ZONTX BY_BWT GONEY CUZWR GDSON SXBOU YWRHE BAAHY USEDQ密钥为roy_al new Zealand navy.请解密这条消息,将TT换为tt.STEP1:构造密匙字母矩阵方法:构造5X5的字母矩阵,先将密匙中包含的字母挨个填入字母矩阵(不重复),入上图的下划线部分,再把剩下的继续按A-Z的顺序填入字母矩阵,I/J算同一个STEP2:分解字母对STEP3:解密方法:每个密文字母都取其对应的明文字母①若两个字母处于字母矩阵的同一行,则每个字母都取其左边的一个字母,最左边字母取最右边的。②若两个字母处于字母矩阵的同一列,则每个字母都取其上面的一个字母,最上边字母取最下边的。③若两个字母不同行业不同列,那就各反取对角,明文字母和密文字母在同一行STEP4:提取信息PT BOAT ONE OWE NINE LOST IN ACTION IN BLACKETT ATART TWO MILES SW MERESU COVE X CREW OF TWELVE X REQUEST ANY INFORMATION X第4章 分组密码和数据加密标准1.什么是乘积密码(p74)乘积密码是指依次使用两个或两个以上的基本密码,所得结果的密码强度将强与所有单个密码的强度.2.混淆和扩散的区别(p75)扩散(Diffusion):明文的统计结构被扩散消失到密文的,使得明文和密文之间的统计关系尽量复杂.即让每个明文数字尽可能地影响多个密文数字混淆(confusion):使得密文的统计特性与密钥的取值之间的关系尽量复杂,阻止攻击者发现密钥3.哪些参数与设计决定了实际的Feistel密码算法?(p75-p77)①分组长度:分组越长意味着安全性越高,但是会降低加/解密的速度。②密钥长度:密钥越长意味着安全性越高,但是会降低加/解密的速度。③迭代轮数:Feistel密码的本质在于单轮不能提供足够的安全性,而多轮加密可- 取的很高的安全性。④子密钥产生算法:子密钥产生越复杂,密码分析就越困难。⑤轮函数:轮函数越复杂,抗攻击能力就越强⑥快速软件加/解密:加密算法被嵌入到应用程序中,以避免硬件实现的麻烦,因此,算法执行的速度很重要。⑦简化分析难度:如果算法描述起来简洁清楚,那么分析其脆弱性也就容易一些,因而可以开发出更强的算法。第5章 有限域1.求x3+x+1在GF(24)里的乘法逆元,模m(x)=x4+x+1参考答案+解题模板:计算优化核心公式:$q_i(x)=r_{i-2}(x)/r_{i-1}(x)$$r_i(x)=r_{i-2}(x)-r_{i-1}(x)*q_i(x)$$v_i=v_i-2-q_i*v_i-1$$w_i=w_i-2-q_i*w_i-1$注意:$GF(2^n)$上所有的运算皆为模2运算第6章 高级加密标准1.在GF$(2^8)$上{01}的逆是什么?注意:$GF(2^8)$上的运算都是模2运算参考答案:注意:01为16进制使用拓展欧几里得算法28=256∴在GF(28)上{01}的逆是{01}拓展求$GF(2^8)$上{95}的逆(注意:95为16进制)使用拓展欧几里得算法$\color{red}{拓展题-典型错误解法}:$28=256 95H=149拓展题-正确解法--$GF(2^N)$上的运算都是模2运算特别注意--GF(28)的既约多项式为x8+x4+x3+x+1∴$GF(2^8)$上{95}的逆是{8A}2.验证{01}在S盒中的项(p115,p117)涉及知识①怎么验证看课表p117②S盒和逆S盒在p1153. 对如下所述的DES中的元素,指出AES中与之相对应的元素,或解释AES中为什么不需要该元素:①f函数的输入与子密钥相异或;轮密匙加②f函数的输出与分组最左的部分相异或;不需要,∵每轮都使用代替和混淆将整个数据细分为一个单一的矩阵处理③f函数字节代替、行移位、列混淆、轮密匙加④置换P;行移位⑤交换分组长度相等的两部分不需要,∵每轮都使用代替和混淆将整个数据细分为一个单一的矩阵处理第7章 分组加密的工作方式1.什么是中间相遇攻击?(p137)是密码学上以空间换取时间的一种攻击。中途相遇攻击(meet-in-the-middle attack)可成倍减少解密已被多个密钥加密的文本所进行的蛮力排列操作。这种攻击可以使入侵者更容易获取数据。2.在三重加密中一个用到了几个密匙(p138)2个3.为什么3DES的中间部分采用了解密而不是加密?(p138)第二步采用解密运算并没有什么密码学上的含义,这仅仅是为了使用三重DES的用户可以利用该算法解密单DES加密的数据。4. DES的ECB模式和CBC模式在DES的ECB模式中,若在密文的传输过程中,某一块发生错误则只有相应的明文分组会有影响。然而,在CBC模式中,这种错误具有扩散性。比如,图7.4中传输C1时发生的错误将会影响明文分组P1,P2a.P2以后的所有块是否会受到影响b.假设P1本来就有一位发生了错误。则这个错误要扩散至多少个密文分组?对接收者解密后的结果有什么影响参考答案a.不会受到影响b.会在加密过程中传递到每一个密文分组。对接收者解密后,P1与加密前一样有一位的错误,而对其他Ci能够解密得到无错误的密文。5. DES的CBC模式和CFB模式参考答案安全性,密文分组是否会泄露关于明文分组的信息等6. 在8位的cfb模式中,若传输中一个密文字符发生了一位错,这个错误将传播多远参考答案9个明文字符受到影响,因为除了与密文字符和对应的一个明文字符受影响外,受影响的该明文字符进入移位寄存器,直到接下来的8个字符处理完毕后才移出。第8章 伪随机数的产生和流密码1.伪随机数发生器a.下述的伪随机数发生器可获得的最大周期是多少?$X_n+1=(a*X_n) mod 24$参考答案:最大周期为4b.这时a为多少?参考答案:3、5、11、13c.对种子有什么要求?参考答案:种子必须为奇数,即$X_0$=1,3,5,7,9,11,13,15第9章 公钥密码学与RSA1.什么是单向函数?(p198-p199)课本上自己画2.什么是单向陷门函数?(p199)课本上自己画3.RSA秘钥生成及加密解密的计算涉及知识(打印版看不清可以看课本p201)题目-用RSA实现加密和解密:a.p=3;q=11;e=7;M=5密钥产生:①$n=p*q=3*11=33$②$φ(n)=(p-1)*(q-1)=2*10=20$③$d≡1modφ(n)即7d=1mod20$=>d=3所以,公钥PU={7,33},私钥PR={3,33}加密:$C=Me mod n=57 mod 33=14$---注意怎么算的解密:$M=Cd mod n=143 mod 33=5$---注意怎么算的4.在使用RSA的公钥体制中,已截获发给用户的密文C=10,该用户的公钥e=5,n=35,那么明文M是多少参考答案欧拉函数$φ(n)=24$$dmod24=1$可得$d=5$$M=Cd mod n=105 mod 35=5$---注意怎么算的第10章 密钥管理和其他公钥密码体制1.用户A和B在使用Diffie-Hellman密匙交换技术来交换密匙,设公钥的素数q=71,本原根α=7a.若用户A的私钥XA=5,则A个公钥$Y_A$为多少?参考答案:$Y_A=75mod71=51$b.若用户B的私钥XB=12,则B个公钥$Y_B$为多少?参考答案:$Y_B=712mod71=4$c.共享密钥为多少?参考答案:$K= (Y_A^XB)mod71=5112mod71=30$或者:$K= (Y_B^XA)mod71=45mod71=30$2.设Diffie-Hellman方法中,公钥素数q=11,本原根α=2。a.证明2是11的本原根参考答案:$2^1 mod 11=2$$2^2 mod 11=4$$2^3 mod 11=8$$2^4 mod 11=5$$2^5 mod 11=10$$2^6 mod 11=9$$2^7 mod 11=7$$2^8 mod 11=3$$2^9 mod 11=6$$2^{10} mod 11=1$∴2是11的本原根b.若用户A的公钥Y_A=9,则A个私钥XA为多少?参考答案:(2^XA) mod 11=9 ∴XA=6c.若用户B的公钥Y_B=3,则共享密钥K为多少?参考答案:K= (Y_B^XA)mod11=36 mod 11=3第11章 密码学Hash函数1.安全Hash函数需要具有哪些特征?(p240)①输入长度可变②输出长度固定③效率④抗原像攻击(单向性)⑤抗第二原像攻击(抗弱碰撞性)⑥抗碰撞攻击(抗强碰撞性)⑦伪随机性2.抗弱碰撞性和抗强碰撞之间的区别是什么?(p240)见课本3.Hash函数的压缩函数的作用是什么?压缩函数将一个较长的、固定长度的输入处理后返回一个较短的、固定长度的输出。第12章 消息认证码1.消息认证是为了对付哪些类型的攻击?(p264-p265)①伪装②内容修改③顺序修改④计时修改2.产生消息认证有哪些方法?(p265)①Hash函数②消息加密③消息认证码(MAC)3.对称加密和错误控制码一起用于消息认证时,这两个函数必须以何种顺序执行?先错误控制码,后对称加密4.为提供消息认证,应以何种方式保证Hash值的安全?a.用对称密码对消息及附加在其后的Hash码加密。b.用对称密码仅对Hash加密。c.用公钥密码和发送方的密钥仅对Hash加密。d.若寄希望保证保密性有希望有数字签名,则先用发送方的密钥对Hash码加密e.该方法使用Hash函数但不使用加密函数来进行消息认证。f.如果对整个消息和Hash码加密,则(e)中的方法可提供保密性。第13章 数字签名1.签名函数和保密函数应以何种顺序作用与消息?为什么?先执行签名函数,再执行加密函数。这样在发生争执时,第三方可以查看消息及其签名。这种先后次序非常重要,如果先对消息加密,然后再对消息的密文签名,那么第三方必须知道解密密钥才能读取原始消息。第14章 密钥管理和分发1.会话密钥和主密钥之间有什么不同?主密钥是被客户机和服务器用于产生会话密钥的一个密钥。这个主密钥被用于产生客户端读密钥,客户端写密钥,服务器读密钥,服务器写密钥。主密钥能够被作为一个简单密钥块输出。会话密钥是指:当两个端系统希望通信,他们建立一条逻辑连接。在逻辑连接持续过程中,所以用户数据都使用一个一次性的会话密钥加密。在会话和连接结束时,会话密钥被销。2.公钥目录的必要要素是什么?一是目录管理员的私钥安全,二是目录管理员保存的记录安全。3.X.509标准的用途是什么?(p319)X.509标准是一个广为接受的方案,用来规范公钥证书的格式。证书在大部分网络安全应用中都有使用,包括IP安全、传输层安全(TLS)和S/MIME。4.什么是证书链?数字证书由颁发该证书的签名。多个证书可以绑定到一个信息或交易上形成证书链,证书链中每一个证书都由其前面的数字证书进行鉴别。最高级的必须是受接受者信任的、独立的机构。第15章 用户认证1.列出三个常用的防止重放攻击的方法(p332)①对每一个用于认证交互的消息附上一个序列号。②时间戳:只有当消息中包含一个时间戳时,A才接收该消息。③挑战/应答:A想要一个来自B的新消息,首先发给B一个临时交互号,并要求后面从B收到的消息(回复)中包含正确的临时交互号。2.在网络或者Internet上,和用户认证相关联的三个威胁是什么?①用户可能通过某种途径进入工作站并假装成其他用户操作工作站。②用户可以通过变更工作站的网络地址,从该机上发送伪造的请求。③用户可以静听信息或使用重放攻击,以获得服务或破坏正常操作。第17章 传输层安全1.TLS连接和TLS会话的区别是什么?(p381)书上自己画2.HTTPS的目的是什么?在 http 的基础上结合 ssl 来实现网络浏览器和服务器的安全通信。3.哪些应用程序可以使用SSH?远程登录工具,文件传输工具等第20章 IP安全性1.IPSec提供哪些服务?①访问控制②连接完整性③数据源认证④拒绝重放包(部分顺序完整性格式)⑤保密性(加密)⑥限制流量保密性2.哪些参数标识SA,哪些参数刻画一个特定SA的本质?由安全参数索引、IP目的地址、安全协议标识三个参数确定一个SA。由“序列号计数器,序列计数器溢出,反重放窗口,AH信息,ESP信息,此安全关联的生存期,IPSec 协议模式,最大传输单元路径”等参数表示一个特定的SA。3.指出传输模式和隧道模式的区别传输模式是对IP数据包的载荷(上层协议)、IPV6报头的扩展部分进行保护和认证;隧道模式是对整个内部IP包、IPV6报头的扩展部分进行保护和认证。4.什么是重放攻击?重放攻击就是一个攻击者得到了一个经过认证的包的副本,稍后又将其传送到其希望被传送到的目的的站点的攻击。5.IPSec中的Oakley密钥确定协议和ISAKMP的作用是什么?IPSec的密钥管理部分包括密钥的确定和分发。分手动密钥管理和自动密钥管理两种类型。Oakley和ISAKMP就是IPSec的自动密钥管理协议。
2022年04月14日
2,064 阅读
1 评论
0 点赞
2022-04-13
CommentToMail:给博客添加评论邮箱提醒功能
1.下载安装首先下载插件再上传到/usr/plugins目录解压,博客后台启用并配置插件。下载地址:CommentToMail2.配置邮箱smtp地址:smtp.qq.com(我用的QQ邮箱)SMTP端口:465SMTP用户:自己的邮箱账户SMTP密码:开启smtp时获取的授权码(QQ在设置-账户里面,其他百度)STMP验证:服务器需要验证、ssl加密全打勾3.美化代码3.1步骤一依次打开:博客后台 -> 控制台 -> 评论邮件提醒 -> 编辑邮件模板3.2步骤二将以下代码复制粘贴到guest.html<table style="width: 99.8%;height:99.8% "><tbody><tr><td style="background:#fafafa url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAy0lEQVQY0x2PsQtAYBDFP1keKZfBKIqNycCERUkMKLuSgZnRarIpJX8s3zfcDe9+794du+8bRVHQOI4wDAOmaULTNDDGYFkWMVVVQUTQdZ3iOMZxHCjLElVV0TRNYHVdC7ptW6RpSn3f4wdJkiTs+w6WJAl4DcOAbdugKAq974umaRAEARgXn+cRW3zfFxuiKCJZloXGHMeBbdv4Beq6Duu6Issy7iYB8Jbnucg8zxPLsggnj/zvIxaGIXmeB9d1wSE+nOeZf4HruvABUtou5ypjMF4AAAAASUVORK5CYII=')"> <div style="border-radius: 10px 10px 10px 10px;font-size:13px; color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"> <div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"> <p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="https:"> {siteTitle} </a>上的留言有新回复啦! </p> </div> <div style="margin:40px auto;width:90%"> <p>{author_p} 您曾在文章《{title}》上发表评论:</p> <p style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">{text_p}</p> <p>{author} 给您的回复如下:</p> <p style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">{text}</p> <p>您可以点击 <a style="text-decoration:none; color:#12addb" href="{permalink}">查看回复的完整內容 </a>,欢迎再次光临 <a style="text-decoration:none; color:#12addb" href="https:"> {siteTitle} </a>。</p> <style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style> </div> </div> </td></tr></tbody></table>3.3步骤三接着将以下代码复制粘贴到owner.html<style> .wrap span { display: inline-block; } .w260{ width: 260px;} .w20{ width: 20px;} .wauto{ width: auto;} </style> <table style="width: 99.8%;height:99.8% "><tbody><tr><td style="background:#fafafa url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAy0lEQVQY0x2PsQtAYBDFP1keKZfBKIqNycCERUkMKLuSgZnRarIpJX8s3zfcDe9+794du+8bRVHQOI4wDAOmaULTNDDGYFkWMVVVQUTQdZ3iOMZxHCjLElVV0TRNYHVdC7ptW6RpSn3f4wdJkiTs+w6WJAl4DcOAbdugKAq974umaRAEARgXn+cRW3zfFxuiKCJZloXGHMeBbdv4Beq6Duu6Issy7iYB8Jbnucg8zxPLsggnj/zvIxaGIXmeB9d1wSE+nOeZf4HruvABUtou5ypjMF4AAAAASUVORK5CYII=')"> <div style="border-radius: 10px 10px 10px 10px;font-size:13px; color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"> <div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"> <p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您的<a style="text-decoration:none;color: #ffffff;" href="https:"> {siteTitle} </a>上有新的评论啦! </p> </div> <div style="margin:40px auto;width:90%"> <p>{author} 在您文章《{title}》上发表评论:</p> <p style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">{text}</p> <p class="wrap" style="text-decoration:none"><span class="w260">时间:{time}</span><span class="w20"> </span><span class="wauto"> IP:{ip}</span></p> <p class="wrap" style="text-decoration:none"><span class="w260">邮箱:{mail}</span><span class="w20"> </span><span class="wauto">状态:{status}</span></p> <p><a style="text-decoration:none; color:#12addb" href="{permalink}" target='_blank'>[查看评论]</a> | <a style="text-decoration:none; color:#12addb" href="{manage}" target='_blank'>[管理评论] </a></p> <style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style> </div> </div> </td></tr></tbody></table>注意:要把里面的链接改为自己的哦3.4美化效果被评论:被回复:
2022年04月13日
609 阅读
0 评论
0 点赞
2022-04-13
cmake使用及如何编写CMakeLists.txt文件
1.cmake 简介CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。2.CMake 操作流程CMake的所有的语句都写在一个叫:CMakeLists.txt的文件中。当CMakeLists.txt文件确定后,可以用ccmake命令对相关 的变量值进行配置。这个命令必须指向CMakeLists.txt所在的目录。配置完成之后,应用cmake命令生成相应的makefile(在Unix like系统下)或者 project文件(指定用window下的相应编程工具编译时)。其基本操作流程为:$ ccmake directory $ cmake directory $ make其中directory为CMakeList.txt所在目录;第一条语句用于配置编译选项,如VTK_DIR目录 ,一般这一步不需要配置,直接执行第二条语句即可,但当出现错误时,这里就需要认为配置了,这一步才真正派上用场;第二条命令用于根据CMakeLists.txt生成Makefile文件;第三条命令用于执行Makefile文件,编译程序,生成可执行文件;CMake的执行就是这么简单,其难点在于如何编写CMakeLists.txt文件3.如何编写CMakeLists.txt文件3.1 开头通用模块make版本要求cmake_minimum_required( VERSION 2.8 )工程文件名-可任取project(project)编译模式# 设置为 Release 模式 SET(CMAKE_BUILD_TYPE Release) # 设置为 debug 模式 SET(CMAKE_BUILD_TYPE debug) # 打印设置的编译模型信息 MESSAGE("Build type: " ${CMAKE_BUILD_TYPE})检查C++版本# Check C++11 or C++0x support include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") add_definitions(-DCOMPILEDWITHC11) message(STATUS "Using flag -std=c++11.") elseif(COMPILER_SUPPORTS_CXX0X) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") add_definitions(-DCOMPILEDWITHC0X) message(STATUS "Using flag -std=c++0x.") else() message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif()3.2 项目文件配置模块如果仅包含OpenCV库时备注:这里的OpenCV包含目录为含有OpenCVConfig.cmake的路径。set(OpenCV_DIR "/usr/local/include/opencv3.2.0/share/OpenCV") find_package(OpenCV REQUIRED) include_directories( ${OpenCV_INCLUDE_DIRS} )生成可执行文件ADD_EXECUTABLE( 目标文件(可执行文件) 依赖文件(.cpp))add_executable(${PROJECT_NAME} src/loop_closure.cpp ) target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})包含第三库的头文件#设置.h文件对应的路径 set( DBoW2_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/ThirdParty/DBow-master/include/) #包含.h文件路径 include_directories( ${OpenCV_INCLUDE_DIRS} ${DBoW2_INCLUDE_DIRS} ${DBoW2_INCLUDE_DIRS}/DBoW2/) 包含第三方库的cpp文件set(DBoW2_SRCS "${PROJECT_SOURCE_DIR}/ThirdParty/DBow-master/src") #生成可执行文件 -- 使用空格分割cpp文件路径 add_executable(${PROJECT_NAME} src/loop_closure.cpp src/run_main.cpp ${DBoW2_SRCS}/BowVector.cpp ${DBoW2_SRCS}/FBrief.cpp ${DBoW2_SRCS}/FeatureVector.cpp ${DBoW2_SRCS}/FORB.cpp ${DBoW2_SRCS}/FSurf64.cpp ${DBoW2_SRCS}/QueryResults.cpp ${DBoW2_SRCS}/ScoringObject.cpp)3.3 一个简单的CMakeLists.txt文件democmake_minimum_required( VERSION 2.8 ) project( loop_closure ) #set(CMAKE_BUILD_TYPE Debug) IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE Release) ENDIF() MESSAGE("Build type: " ${CMAKE_BUILD_TYPE}) # Check C++11 or C++0x support include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") add_definitions(-DCOMPILEDWITHC11) message(STATUS "Using flag -std=c++11.") elseif(COMPILER_SUPPORTS_CXX0X) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") add_definitions(-DCOMPILEDWITHC0X) message(STATUS "Using flag -std=c++0x.") else() message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif() #opencv #set(OpenCV_DIR "/usr/local/include/opencv3.2.0/share/OpenCV") set(OpenCV_DIR "/opt/ros/kinetic/share/OpenCV-3.3.1-dev") find_package(OpenCV REQUIRED) set( DBoW3_INCLUDE_DIRS "/usr/local/include") set( DBoW2_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/ThirdParty/DBow-master/include/) message(${DBoW2_INCLUDE_DIRS}) #important #file(GLOB DBoW2_SRCS ${PROJECT_SOURCE_DIR}/ThirdParty/DBow-master/src/*.cpp) #message(${DBoW2_SRCS}) set(DBoW2_SRCS "${PROJECT_SOURCE_DIR}/ThirdParty/DBow-master/src") message(${DBoW2_SRCS}) find_package(DLib QUIET PATHS ${DEPENDENCY_INSTALL_DIR}) if(${DLib_FOUND}) message("DLib library fo NDENCY_DIR} GIT_REPOSITORY http://github.com/dorian3d/DLib GIT_TAG master INSTALL_DIR ${DEPENDENCY_INSTALL_DIR} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>) add_custom_target(Dependencies ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR} DEPENDS DLib) else() message(SEND_ERROR "Please, activate DOWNLOAD_DLib_dependency option or download manually") endif(${DOWNLOAD_DLib_dependency}) endif(${DLib_FOUND}) include_directories( ${OpenCV_INCLUDE_DIRS} ${DBoW3_INCLUDE_DIRS} ${DBoW2_INCLUDE_DIRS} ${DBoW2_INCLUDE_DIRS}/DBoW2/) message("DBoW3_INCLUDE_DIRS ${DBoW3_INCLUDE_DIRS}") message("DBoW2_INCLUDE_DIRS ${DBoW2_INCLUDE_DIRS}") message("opencv ${OpenCV_VERSION}") # dbow3 # dbow3 is a simple lib so I assume you installed it in default directory set( DBoW3_LIBS "/usr/local/lib/libDBoW3.a") add_executable(${PROJECT_NAME} src/loop_closure.cpp src/run_main.cpp ${DBoW2_SRCS}/BowVector.cpp ${DBoW2_SRCS}/FBrief.cpp ${DBoW2_SRCS}/FeatureVector.cpp ${DBoW2_SRCS}/FORB.cpp ${DBoW2_SRCS}/FSurf64.cpp ${DBoW2_SRCS}/QueryResults.cpp ${DBoW2_SRCS}/ScoringObject.cpp ) message(${DBoW2_SRCS}/BowVector.cpp) target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ${DLib_LIBS} ${DBoW3_LIBS} )参考资料cmake使用方法详解快速了解如何编写CMakeLists.txt文件?
2022年04月13日
1,900 阅读
2 评论
0 点赞
1
...
9
10
11
...
24