栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring、Mybatis、Mybatis-plus

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring、Mybatis、Mybatis-plus

Spring 一、简介

1、概述:是分层地JavaSE/EE应用full-stack轻量级开源框架,以IOC和AOP为内核
2、优点
        (1)、方便解耦,简化开发
        (2)、Aop编程支持
        (3)、声明式事务的支持
        (4)、方便程序的测试
        (5)、方便集成各种优秀框架
        (6)、降低JavaEEAPI的使用难度
        (7)、java源码是经典学习范例
3、开发步骤
        (1)、导入Spring开发的基本包坐标
        (2)、编写Dao接口和实现类
        (3)、创建Spring核心配置文件
        (4)、在Spring配置文件中配置Dao接口的实现类
        (5)、使用Spring的API获取Bean实例
4、依赖

 
     org.springframework
     spring-context
     5.3.18
 
二、IOC (一)、Bean

1、概述:是一个被实例化,组装,并通过Spring IOC容器所管理的对象
2、属性
        (1)、id:在spring容器中的唯一标识
        (2)、class:Bean的全类路径
        (3)、scope:对象的作用范围

取值范围说明
singleton默认值,单例的;核心配值文件加载,就实例化Bean实例
prototype多例的;调用getBean是,就创建新的实例化Bean
requestweb项目中。spring创建一个Bean对象,将对象存入到request域中
sessionweb项目中。spring创建一个Bean对象,将对象存入到session域中
global sessionweb项目中。应用在Portlet环境中,若没有Portlet环境,那么global session就相当于session

        (4)、init-method:指定类型初始化方法名称,方法名称随意 ​
        (5)、destroy-method:指定类型销毁方法的名称,方法名称随意
3、子属性 ​
        (1)、property:依赖注入,set方法 ​
                ①、name:属性名称 ​
                ②、value:注入的普通属性值 ​
                ③、ref:注入对象的引用值 ​
        (2)、constructor-arg::依赖注入,有参构造

(二)、实例化

1、无参构造方法实例化

 

2、工厂静态方法实例化

 

3、工厂实例方法实例化

 
 
(三)、依赖注入

1、概述:是Spring框架核心的IOC的具体实现
2、方式
        (1)、set
                ①、普通类型

 
     
 

                ②、引用类型

 
 
     
 

                ③、集合

 
     
     
         
             Java
             Mysql
         
     
     
     
         
             Python
             Php
         
     
     
     
         
             html
             js
         
     
     
     
         
             
             
         
     
     
     
         
             
             
         
     
     
     
         
             spring
             springmvc
         
     
 
 
 
     
 
 
     
 

        (2)、有参构造 ​
                ①、普通类型

 
     
 

                ②、引用类型

 
 
     
 

                ③、集合

(四)、引入外部模块

1、概述:将主配置文件进行分模块的拆解,通过标签引入即可 2、标签

 
(五)、相关API

1、ApplicationContext
        (1)、概述:接口,文件的上下文
        (2)、实现类
                ①、CalssPathXmlApplicationContext:是从类的跟路径下加载配置文件
                ②、FileSystemXmlApplicationContext:从磁盘路径下加载配置文件
                ③、AnnotaionConfigApplicationContext:注解配置容器对象是,用来读取注解的
2、getBean
        (1)、getBean(String name):通过Id获取,可以不是唯一的类型,需要强制转换
        (2)、getBean(Class requireType):通过类型,但是只能是一个唯一的类型,不需要强制转换

(六)、数据源

1、概述:提供了应用程序所需要数据的位置
2、作用:简化开发,提升性能
3、常见数据源:DBCP、C3P0、BoneCP、Druid...
4、开发步骤
        (1)、导入数据源的坐标和数据驱动坐标
        (2)、创建数据源对象
        (3)、设置数据源的基本连接数据
        (4)、使用数据源获取连接资源和归还资源
5、C3P0
        (1)、导入依赖

 
     c3p0
     c3p0
     0.9.1.2
 

        (2)、传统案例

 public void c3p0() throws Exception {
     ComboPooledDataSource dataSource = new ComboPooledDataSource();
     dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
     dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mysql");
     dataSource.setUser("root");
     dataSource.setPassword("root");
     Connection connection = dataSource.getConnection();
     System.out.println(connection);
     connection.close();
 }

        (3)、抽取配置消息

 driver=com.mysql.cj.jdbc.Driver
 url=jdbc:mysql://localhost:3306/mysql
 username=root
 password=root
 public void c3p0() throws Exception {
     ResourceBundle rb = ResourceBundle.getBundle(" jdbc");
     String driver = rb.getString("driver");
     String url = rb.getString("ur1");
     String username = rb.getString("username");
     String password = rb.getString("password");
     ComboPooledDataSource dataSource = new ComboPooledDataSource();
     dataSource.setDriverClass(driver);
     dataSource.setJdbcUrl(url);
     dataSource.setUser(username);
     dataSource.setPassword(password);
     Connection connection = dataSource.getConnection();
     System.out.println(connection);
     connection.close();
 }

        (4)、spring配置数据源

 driver=com.mysql.cj.jdbc.Driver
 url=jdbc:mysql://localhost:3306/mysql
 username=root
 password=root
 
 
     
     
     
     
 

6、Druid
        (1)、导入依赖

 
     com.alibaba
     druid
     1.2.8
 x

        (2)、传统案例

 public void druid() throws Exception {
     DruidDataSource dataSource = new DruidDataSource();
     dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
     dataSource.setUrl("jdbc:mysql://localhost:3306/mysql");
     dataSource.setUsername("root");
     dataSource.setPassword("root");
     DruidPooledConnection connection = dataSource.getConnection();
     System.out.println(connection);
     connection.close();
 }

        (3)、抽取配置消息

 driver=com.mysql.cj.jdbc.Driver
 url=jdbc:mysql://localhost:3306/mysql
 username=root
 password=root
 public void c3p0() throws Exception {j
     ResourceBundle rb = ResourceBundle.getBundle(" jdbc");
     String driver = rb.getString("driver");
     String url = rb.getString("ur1");
     String username = rb.getString("username");
     String password = rb.getString("password");
     DruidDataSource dataSource = new DruidDataSource();
     dataSource.setDriverClassName(driver);
     dataSource.setUrl(url);
     dataSource.setUsername(username);
     dataSource.setPassword(password);
     DruidPooledConnection connection = dataSource.getConnection();
     System.out.println(connection);
     connection.close();
 }

        (4)、spring配置数据源

 driver=com.mysql.cj.jdbc.Driver
 url=jdbc:mysql://localhost:3306/mysql
 username=root
 password=root
 
 
     
     
     
     
 
(七)、注解开发

1、作用:简化配置,提高开发效率
2、原始注解

注解说明
@Component使用在类上用于实例化Bean
@Controller使用在web层类上用于实例化Bean
@Service使用在service层类上用于实例化Bean
@Repository使用在Dao层类上用于实例化Bean
@Autowired使用在字段上用于根据类型依赖注入
@Qualifier结合@Autowired一起使用用于根据名称进行依赖注入
@Resource相当于@Autowired+@Qualifier,安装名称进行注入
@Value注入普通属性
@Scope标注Bean的作用范围
@PostConstruct使用在方法上标注该方法是Bean的初始化方法
@PreDestroy使用在方法上标注该方法是Bean的销毁方法

3、注意事项:使用注解式开发时,要在spring的核心配置文件中,加入注解扫描器

 
 

4、新注解

注解说明
@Configuration用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解
@ComponentScan用于指定Spring在初始化容器时要扫描的包
@Bean使用在方法上,标注将该方法的返回值存储到Spring容器中
@PropertySource用于加载properties文件中的位置
@Import用于导入其它配置类
三、JDBCTemplate

1、概述:Spring框架对JDBC进行封装,方便实现对数据库操作
2、开发步骤
        (1)、导入spring-jdbc和spring-tx的依赖

 
     org.springframework
     spring-jdbc
     5.3.18
 
 
     org.springframework
     spring-tx
     5.3.18
 

        (2)、创建数据库的表和实体 ​
        (3)、创建JDBCTemplate对象 ​
        (4)、执行数据库操作 ​
        (5)、示例

 jdbc.DriverClass=com.mysql.jdbc.Driver
 jdbc.url=jdbc.mysql://localhost:3306//user_db
 jdbc.username=root
 jdbc.password=root
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class Book {
     private String userId;
     private String userName;
     private String ustatus;
 }
 public interface BookDao{
     public void add(Book book);//添加
     public void updateBook(Book book);//修改
     public void deleteBook(String id);//删除
     public int selectCount();//返回某个值
     public Book findBookInfo();//返回一个对象
     public List findBookAll();//返回一个集合
     public void batchAddBook(List batchArgs);//批量添加
     public void batchUpdateBook(List batchArgs);//批量修改
     public void batchDeleteBook(List batchArgs);//批量删除
 }
 @Repository
 public class BookDaoImpl implements BookDao{
     @Autowired
     private JdbcTemplate jdbcTemplate;
     public void add(Book book){//添加
         String sql = "insert into book values(?,?,?)";
         Objec[] ages = {book.getUserId(),bool.getUserName(),book.getUstatus()};
         int update = jdbcTemplate.update(sql,ages);//前面是SQl,后面是变值
         System.out.println(update);
     }
     public void updateBook(Book book){//修改
         String sql = "update book set userName=?,ustatus=? where userId=?";
         Objec[] ages = {bool.getUserName(),book.getUstatus(),book.getUserId()};
         int update = jdbcTemplate.update(sql,ages);//前面是SQl,后面是变值
         System.out.println(update);
     }
     public void deleteBook(String id){//删除
         String sql = "delete from book where userId=?";
         Objec[] ages = {id};
         int update = jdbcTemplate.update(sql,ages);//前面是SQl,后面是变值
         System.out.println(update);
     }
     public int selectCount(){//返回某个值
         String sql = "select count(*) from book";
         Integer count = jdbcTemplate.queryForObject(sql,Integer.class);
         return count;
     }
     public Book findBookInfo(String id){//返回一个对象
         String sql = "select * from book where userId=?";
         Objec[] ages = {id};
         Book book = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper(Book.class),ages);
         return book;
     }
     public List findBookAll(){//返回一个集合
         String sql = "select * from book";
         List listBook = jdbcTemplate.query(sql,new BeanPropertyRowMapper(Book.class));
         return listBook;
     }
     public void batchAddBook(List batchArgs){//批量添加
         String sql = "insert into book values(?,?,?)";
         int[] update = jdbcTemplate.batchUpdate(sql,batchArgs);
         System.out.println(Arrays.toString(update));
     }
     public void batchUpdateBook(List batchArgs){//批量修改
         String sql = "update book set userName=?,ustatus=? where userId=?";
         int[] update = jdbcTemplate.batchUpdate(sql,batchArgs);
         System.out.println(Arrays.toString(update));
     }
     public void batchDeleteBook(List batchArgs){//批量删除
         String sql = "delete from book where userId=?";
         int[] update = jdbcTemplate.batchUpdate(sql,batchArgs);
         System.out.println(Arrays.toString(update));
     }
 }
 @Service
 public class BookService{
     @Autowired
     private BookDao bookDao;
     public void addBook(Book book){//添加
         bookDao.add(book);
     }
     public void updateBook(Book book){//修改
         bookDao.update(book);
     }
     public void deleteBook(String id){//删除
         bookDao.delete(id);
     }
     public int findCount(){//返回某个值
        return bookDao.selectCount();
     }
     public Book findOne(String id){//返回一个对象
         return bookDao.findBookInfo(id);
     }
     public List find(){//返回一个集合
         return bookDao.findBookAll();
     }
     public void batchAdd(List batchArgs){//批量添加
         bookDao.batchAddBook(batchArgs);
     }
     public void batchUpdate(List batchArgs){//批量修改
         bookDao.batchUpdateBook(batchArgs);
     }
     public void batchDelete(List batchArgs){//批量删除
         bookDao.batchDeleteBook(batchArgs);
     }
 }
 x
 
 
 
 
 
     
     
     
     
 
 
 
     
     
 
 public class Test{
     public static void main(String[] agrs){
         ApplicationContext context = new ClassPathXmlApplicationContext("beam.xml");
         BookService bookService = context.getBean("bookService",BookService.class);
         bookService.addBook(new Book("1","java","在学");//添加
         bookService.updateBook(new Book("1","java","完成");//修改
         bookService.deleteBook(1);//删除
         System.out.println(bookService.selectCount());//返回某个值
         System.out.println(bookService.findOne(1));//返回一个对象
         System.out.println(bookService.find());//返回一个集合
         List batchArgs = new ArrayList<>();
         Object[] o1 = {"1","Java","a"};
         Object[] o2 = {"2","mysql","b"};
         Object[] o3 = {"3","html","c"};
         batchArgs.add(o1);
         batchArgs.add(o2);
         batchArgs.add(o3);
         bookService.batchAdd(batchArgs);//批量添加
         List batchArgs = new ArrayList<>();
         Object[] o1 = {"js","d","1"};
         Object[] o2 = {"css","e","2"};
         Object[] o3 = {"mysql","f","3"};
         batchArgs.add(o1);
         batchArgs.add(o2);
         batchArgs.add(o3);
         bookService.batchUpdate(batchArgs);//批量修改
         List batchArgs = new ArrayList<>();
         Object[] o1 = {"1"};
         Object[] o2 = {"2"};
         batchArgs.add(o1);
         batchArgs.add(o2);
         batchArgs.add(o3);
         bookService.batchUpdate(batchArgs);//批量删除
     }
 }
四、AOP (一)、简介

1、概述:是通过预编译方式和运行期动态代理,实现程序功能的统一维护的一种技术
2、目的:降低业务和逻辑的耦合度,提高程序的可重用行,同时提高了开发效率
3、作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
4、优势:减少重复代码,提高开发效率,并且便于维护
5、底层原理:动态代理
6、常用的动态代理技术
        (1)、JDK代理:基于接口的动态代理技术
        (2)、cglib代理:基于父类的动态代理技术
7、术语
        (1)、目标对象:Target,代理的目标对象
        (2)、代理:Proxy,一个类被AOP织入增强时,就产生一个结果代理类
        (3)、连接点:Joinpoint,那些方法可以被增强
        (4)、切入点:Pointcut,实际真正增强的方法;execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]))
        (5)、通知:Advice,实际增强的逻辑部分
        (6)、切面:Aspect,把通知应用到切入点的过程
        (7)、织入:Weaving,把增强应用到目标对象来创建新的代理对象的过程
8、注意事项
        (1)、需要编写的内容;切点、通知、织入配置
        (2)、AOP技术实现的内容 (3)、AOP底层使用那种代理方式

(二)、AspectJ

1、概述:是一个易用的功能强大的AOP框架
2、依赖

 
     org.aspectj
     aspectjweaver
     1.8.4
 

3、xml实现

public interface TargetInterface{
     public void save();
 }
 public class Target implements TargetInterface{
     public void save(){
        System.out.println("需要增强");
     }
 }
 public class MyAspect(){
     public void before(){//前置
         System.out.println("before...");
     }
     public void afterReturning(){//后置
         System.out.println("afterReturning...");
     }
     public void after(){//最终
         System.out.println("after...");
     }
     public void afterThrowing()//异常
         System.out.println("afterThrowing...");
     }
     public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{//环绕
         System.out.println("around...前");
         proceedingJoinPoint.proceed();
         System.out.println("around...后");
     }
 }
 
 
 ​
 
 
 ​
 
     
     
     
     
         
         
         
         
         
         
         
         
         
         
     
 

4、注解实现

public interface TargetInterface{
     public void save();
 }
 @Component("target")
 public class Target implements TargetInterface{
     public void save(){
        System.out.println("需要增强");
     }
 }
 @Component("myAspect")
 @Aspect
 public class MyAspect(){
     @Pointcut(value="execution(*[路径].User.add(...))")//相同切入点抽取
     public void pointdemo(){}
     @Before("execution(* com.spring.aop.Target.save())")
     public void before(){//前置
         System.out.println("before...");
     }
     @AfterReturning("execution(* com.spring.aop.Target.save())")
     public void afterReturning(){//后置
         System.out.println("afterReturning...");
     }
     @After("execution(* com.spring.aop.Target.save())")
     public void after(){//最终
         System.out.println("after...");
     }
     @AfterThrowing("execution(* com.spring.aop.Target.save())")
     public void afterThrowing(){//异常
         System.out.println("afterThrowing...");
     }
     @Around("execution(* com.spring.aop.Target.save())")
     public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{//环绕
         System.out.println("around...前");
         proceedingJoinPoint.proceed();
         System.out.println("around...后");
     }
 }
 @Configuration
 @ComponentScan(basePackages={"com.spring5"})
 @EnableAspectJAutoProxy(proxyTargetClass=true)
 public class ConfigAop{}
五、事务控制 (一)、编程式事务控制

1、PlatformTransactionManager:事务管理器,操作事务的方法
        (1)、获取事务:TransactionStatus getTransaction(TransactionDefinition definition)
        (2)、提交事务:void commit(TransactionStatus status)
        (3)、回滚事务:void rollback(TransactionStatus status)
2、TransactionDefinition:定义了事务的基本信息
        (1)、获取事务定义名称:String getName()
        (2)、获取事务的读写属性:boolean isReadOnly()
        (3)、获取事务隔离级别:int getIsolationLevel()
        (4)、获事务超时时间:int getTimeout()
        (5)、获取事务传播行为特征:int getPropagationBehavior()
3、TransactionStatus:事务在执行过程中某个时间点上的状态信息及对应的状态操作
        (1)、获取事务是否处于新开启事务状态:boolean isNewTransaction()
        (2)、获取事务是否处于已完成状态:boolean isCompleted()
        (3)、获取事务是否处于回滚状态:boolean isRollbackOnly()
        (4)、刷新事务状态:void flush()
        (5)、获取事务是否具有回滚存储点:boolean hasSavepoint()
        (6)、设置事务处于回滚状态:void setRollbackOnly()

(二)、声明式事务控制

1、概述:采用声明的方式来处理事务,指在配置文件中声明
2、作用
        (1)、事务管理不侵入开发的组件
        (2)、维护方便
3、xml

 
 
 
 
     
     
     
     
 
 
 
     
     
 
 
 
     
     
 
 
 
     
     
         
         
     
 
 
 
     
     
     
     
 

4、注解

 @Configuration//配置类
 @ComponentScan(basePackages="com.spring5")//组件扫描
 @EnableTransactionManagement//开启事务
 public class TxConfig{
     @Bean
     public DruidDataSource getDruidDataSource(){ //创建链接池
         DruidDataSource dataSource = new DruidDataSource();
         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
         dataSource.setUrl("jdbc:mysql://user_db");
         dataSource.setUsername("root");
         dataSource.setPassword("root");
         return dataSource;
     }
     @Bean
     public JdbcTemolate getJdbcTemolate(DataSource dataSource){//创建JDBCTemolate对象
         JdbcTemolate jdbcTemolate = new JdbcTemolate();
         //注入DataSource
         JdbcTemolate.setDataSource(dataSource);
         return jdbcTemolate;
     }
     @Bean //创建事务管理对象
     public DataSourceTransacrionManager getDataSourceTransacrionManager(DataSource dataSource){
         DataSourceTransacrionManager transacrionManager = new DataSourceTransacrionManager();
         transacrionManager.setDataSource(dataSource);
         return transacrionManager;
     }
 }
六、集成 (一)、web环境

1、三层架构
2、ContextLoaderListener

 WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext (servletContext);
 
     contextConfigLocation
     classpath:applicationContext.xml
 
 ​
 
     org.springframework.web.context.ContextLoaderListener
 

3、步骤
        (1)、导依赖
        (2)、配置ContextLoaderListener监听器
        (3)、使用 WebApplicationContextUtils获取应用上下文

(二)、Junit

1、导入依赖的坐标

 
     junit
     junit
     4.13.1
     test
 
 
     org.springframework
     spring-test
     5.3.18
 

2、使用@Runwith注解替换原来的运行期
3、使用@ContextConfiguration指定配置文件或配置类
4、使用@Autowired注入需要测试的对象
5、测试
6、示例
        (1)、整合Junit4

 @RunWith(SpringJUnit4ClassRunner.class)
 @ContestConfiguration("classpath:bean.xml")
 public class JTest4{
     @Autowired
     private UserService userService;
     @Test
     public void test(){
         userService.addMoney();
     }
 }

        (2)、整合Junit5

@ExtendWith(SprintExtension.class)
 @ContextConfiguration("classpath:bean.xml")
 或
 @SpringJunitConfig(locations="classpath:bean.xml")
 public class Jtest5{
     @Autowired
     private UserService userService;
     @Test
     public void test(){
         userService.addMoney();
     }
 }
SpringMVC 一、简介

1、概述:是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架
2、特点
        (1)、Spring家族原生产品,与IOC容器等基础设施无缝对接
        (2)、基于原生地Servlet,通过了功能强大地前端控制器DispatcherServlet,对请求和响应进行统一处理
        (3)、表述层各细分邻域需要解决的问题全方位覆盖,提供全面解决方案
        (4)、代码清新简洁,大幅度提升开发效率
        (5)、内部组件化程序高,可插拔式组件即插即用,想要什么功能配置相应组件即可
        (6)、性能卓越,尤其适合现代大型、超大型互联网项目要求
3、优点
        (1)、清晰地角色划分,Spring MVC 在 Model、View 和 Controller 方面提供了一个非常清晰的角色划分,这 3 个方面真正是各司其职,各负其责。
        (2)、灵活的配置功能,可以把类当作 Bean 通过 XML 进行配置。
        (3)、提供了大量的控制器接口和实现类,开发者可以使用 Spring 提供的控制器实现类,也可以自己实现控制器接口。
        (4)、真正做到与 View 层的实现无关。它不会强制开发者使用 JSP,可以根据项目需求使用 Velocity、FreeMarker 等技术。
        (5)、国际化支持
        (6)、面向接口编程
        (7)、与 Spring 框架无缝集成

二、搭建框架

1、开发环境
        (1)、IDE:IntelliJ IDEA 2021.1.2
        (2)、构建工具:apache-maven-3.8.2
        (3)、服务器:apache-tomcat-8.5.70
        (4)、Spring版本:
2、创建工程(手动)

 
 
     4.0.0
     com.springmvc
     springmvc
     1.0-SNAPSHOT
     war
     
         
         
             org.springframework
             spring-webmvc
             5.3.1
         
         
         
             ch.qos.logback
             logback-classic
             1.2.3
         
         
         
             javax.servlet
             javax.servlet-api
             3.1.0
             provided
         
         
         
             org.thymeleaf
             thymeleaf-spring5
             3.0.12.RELEASE
         
     
 

3、添加Web模板
        (1)、创建webapp文件夹,创建web.xml文件
        (2)、配置web.xml文件

 
 
     
     
         springMVC
         org.springframework.web.servlet.DispatcherServlet
         
         
             contextConfigLocation
             classpath:springMVC.xml
         
         
         1
     
     
         springMVC
         /
     
 

4、创建控制器

 @Controller
 public class HelloController {
     @RequestMapping("/")
     public String index(){
         return "index";
     }
     @RequestMapping("/target")
     public String target(){
         return "target";
     }
 }

5、创建并配置springMVC.xml

 
 
     
     
     
     
         
         
         
         
         
         
             
                 
                     
                         
                         
                         
                         
                         
                         
                     
                 
             
         
     
 

6、访问首页和指定页面
        (1)、访问首页

 
 
 
     
     首页
 
 
 target
 
 

(2)、访问指定页面


 
 
     
     target
 
 
 HelloWorld
 
 

7、执行流程
        (1)、用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器)
        (2)、由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)
        (3)、DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器)
        (4)、HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller)
        (5)、Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息)
        (6)、HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet
        (7)、DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析
        (8)、ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet
        (9)、DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图)
        (10)、视图负责将结果显示到浏览器(客户端)

三、注解、类型 (一)、@RequestMapping

1、作用:将请求和处理请求的控制器方法进行关联
2、位置
        (1)、类:设置映射请求的路径的初始信息
        (2)、方法:设置映射请求路径的具体信息
3、属性
        (1)、value:通过请求的地址匹配进行映射,可以匹配多个地址进行映射,且必须设置该属性

 @RequestMapping(value="/userAdd")
 public String userAdd(){
     return "add";
 }

        (2)、method:通过请求方式匹配请求映射,可以匹配多种请求方式,不满足就报:405 - Request method "POST" not supported

 @RequestMapping(value="/userAdd",method=RequestMethod.POST)
 public String userAdd(){
     return "add";
 }

        (3)、params:通过请求的请求参数匹配请求,可以匹配多种请求参数,且要同时满足

 @RequestMapping(value="/userAdd",params={"username"})
 public String userAdd(){
     return "add";
 }

        (4)、headers:通过请求的请求头信息匹配映射

 @RequestMapping(value="/userAdd",headers="Host:localhost:8080")
 public String userAdd(){
     return "add";
 }

4、派生注解
        (1)、@GetMapping:处理get请求映射
        (2)、@PostMapping:处理post请求映射
        (3)、@DeleteMapping:处理delete请求映射
        (4)、@PutMapping:处理put请求映射

(二)、@RequestParam

1、作用:将请求参数和控制器方法的形参进行映射关系
2、示例

 @RequestMapping(value="/userAdd")
 public String userAdd(@RequestParam("name")String username,@RequestParam("pwd")String password){
     return "add";
 }
(三)、@RequestHesder

1、作用:将请求头信息和控制器方法的形参进行映射关系
2、示例

 @RequestMapping(value="/userAdd")
 public String userAdd(@RequestHesder("host")String username){
     return "add";
 }
(四)、@CookieValue

1、作用:将cookie数据信息和控制器方法的形参进行映射关系
2、示例

 @RequestMapping(value="/userAdd")
 public String userAdd(@RequestHesder("cookie")String cookie){
     return "add";
 }
(五)、@RequestBody

1、作用:将请求的请求体和当前注解所标识的形参赋值
2、示例

@RequestMapping("/param")
 public String testRequestBody(@RequestBody String requestBody){
     System.out.println("requestBody"+requestBody);
     return "param";
 }
(六)、RequestEnitty

1、作用:在控制器方法的形参设置该类型时,请求报文信息会自动赋值
2、示例

 @RequestMapping("/param")
 public String testRequestEntity(RequestEntity requestEntity){
     System.out.println("请求头"+requestEntity.getHeaders());
     System.out.println("请求体"+requestEntity.getBodty());
     return "param";
 }
(七)、@ResponseBody

1、作用:在控制器方法上标识,可以将方法的返回值直接作为响应体响应打浏览器中
2、示例

 @RequestMapping("/param")
 @ResponseBody
 public String testResponseBody(){
     return "param";
 }
(八)、@RestController

1、作用:给当前类所有的方法加上@ResponseBody
2、示例

 @RestController
 public class EmployeeController {
     @RequestMapping("/param")
     public String testResponseBody(){
         return "param";
     }
     @RequestMapping("/param")
     public String testRequestEntity(RequestEntity requestEntity){
         System.out.println("请求头"+requestEntity.getHeaders());
         System.out.println("请求体"+requestEntity.getBodty());
         return "param";
     }
 }
(九)、ResponseEntity

1、作用:用于控制器方法的返回值类型,该类型是返回值就是响应到浏览器的响应报文
2、示例

@RequestMapping("/hello") 
 public ResponseEntity hello() {
     return new ResponseEntity<>("Hello World!", HttpStatus.OK);
 }
四、域对象 (一)、Repuest

1、servletAPI

 @RequestMapping("/param")
 public String testServletAPI(HttpServletRequest request){
     request.setAttribute("Scoke","servletAPI");
     return "param";
 }

2、ModelAndView

 @RequestMapping("/param")
 public ModelAndView testModelAndViewI(){
     //创建ModelAndView对象
     ModelAndView mav = new ModelAndView();
     //向请求域共享数据
     mav.addObject("Scoke","ModelAndView");
     //设置视图,实现页面跳转
     mav.setViewName("param");
     return mav;
 }

3、Model

 @RequestMapping("/param")
 public String testModel(Model model){
     model.addAttriubute("Scoke","Model");
     return "param";
 }

4、Map

 @RequestMapping("/param")
 public String testMap(Map map){
     map.put("Scoke","Map");
     return "param";
 }

5、ModelMap

 @RequestMapping("/param")
 public String testModelMap(ModelMap modelMap){
     modelMap.addAttriubute("Scoke","ModelMap");
     return "param";
 }
(二)、Session
 @RequestMapping("/param")
 public String testSession(HttpSession Session){
     session.setAttriubute("Scoke","Session");
     return "param";
 }
(三)、Application
 @RequestMapping("/param")
 public String testApplication(HttpSession Session){
     ServletContext application = session.getServletContext();
     application.setAttriubute("Scoke","Application");
     return "param";
 }
五、视图 (一)、Thymeleaf
 @RequestMapping("/param")
 public String testThymeleaf(){
     return "param";
 }
(二)、InternalResourceView
 @RequestMapping("/param")
 public String testForward(){
     return "forward:/param";
 }
(三)、RedirectView
 @RequestMapping("/param")
 public String testRedirectf(){
     return "redirect:/param";
 }
(四)、view-controller
 
 
 ​
 
 
(六)、InternalResourceViewResolver
 
 
     
     
 
六、RESTFurl (一)、简介

1、概述:是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义
2、特点
        (1)、每一个URI代表1种资源;
        (2)、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作
        (3)、通过操作资源的表现形式来操作资源;
        (4)、资源的表现形式是XML或者HTML
        (5)、客户端与服务端之间的交互在请求之间是无状态的
        3、资源:看待服务器的方式,即将服务器看作很多高校的资源组成
        4、资源表述:是一段对于资源在某个特定时刻的状态的描述
        5、状态转移:指客户端和服务器端之间转移,实现操作资源的目的

(二)、实现

1、基本操作:GET(获取)、POST(新建)、PUT(更新)、DELETE(删除)
2、示例

@Controller
 public class EmployeeController {
     @Autowired
     private EmployeeDao employeeDao;
     //查询所有的信息
     @RequestMapping(value = "/employee",method = RequestMethod.GET)
     public String getAllEmployee(Model model){
         Collection employeesList = employeeDao.getAll();
         model.addAttribute("employeesList",employeesList);
         return "employee_List";
     }
     //根据Id进行删除
     @RequestMapping(value = "/employee/{id}",method = RequestMethod.DELETE)
     public String deleteEmployee(@PathVariable("id")Integer id){
         employeeDao.delete(id);
         return "redirect:/employee";
     }
     //添加信息
     @RequestMapping(value = "/employee",method = RequestMethod.POST)
     public String addEmployee(Employee employee){
         employeeDao.save(employee);
         return "redirect:/employee";
     }
     //根据Id查询信息
     @RequestMapping(value = "/employee/{id}",method = RequestMethod.GET)
     public String getEmployeeById(@PathVariable("id")Integer id,Model model){
         Employee employee = employeeDao.get(id);
         model.addAttribute("employee",employee);
         return "employee_update";
     }
     //修改信息
     @RequestMapping(value = "/employee",method = RequestMethod.PUT)
     public String updateEmployee(Employee employee){
         employeeDao.save(employee);
         return "redirect:/employee";
     }
 }

3、注意事项:使用PUT和DELETE时要加入配置HiddenHttpMethodFilter过滤器,还要开始的请求方式必须为POST,还要设置_method属性,值为put或delete,大小写无所谓

 
 
     HiddenHttpMethodFilter
     org.springframework.web.filter.HiddenHttpMethodFilter
 
 
     HiddenHttpMethodFilter
     
 public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
     
     @Override
     protected Class[] getRootConfigClasses() {
         return new Class[]{SpringConfig.class};
     }
     
     @Override
     protected Class[] getServletConfigClasses() {
         return new Class[]{WebConfig.class};
     }
     
     @Override
     protected String[] getServletMappings() {
         return new String[]{"/"};
     }
     
     @Override
     protected Filter[] getServletFilters() {
         // 处理中文乱码问题
         CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
         characterEncodingFilter.setEncoding("UTF-8");
         characterEncodingFilter.setForceResponseEncoding(true);
         // 将请求方式转换
         HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
         return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
     }
 }

2、创建spring.xml的配置类

 import org.springframework.context.annotation.Configuration;
 
 @Configuration
 public class SpringConfig {
 }

3、配置springmvc.xml的配置类

 import com.springmvc.hander.FirstInterceptor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.context.ContextLoader;
 import org.springframework.web.context.WebApplicationContext;
 import org.springframework.web.multipart.MultipartResolver;
 import org.springframework.web.multipart.commons.CommonsMultipartResolver;
 import org.springframework.web.servlet.HandlerExceptionResolver;
 import org.springframework.web.servlet.ViewResolver;
 import org.springframework.web.servlet.config.annotation.*;
 import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
 import org.thymeleaf.spring5.SpringTemplateEngine;
 import org.thymeleaf.spring5.view.ThymeleafViewResolver;
 import org.thymeleaf.templatemode.TemplateMode;
 import org.thymeleaf.templateresolver.ITemplateResolver;
 import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
 import javax.servlet.ServletContext;
 import java.util.List;
 import java.util.Properties;
 
 @Configuration
 @ComponentScan("com.springmvc")
 @EnableWebMvc
 public class WebConfig implements WebMvcConfigurer {
     
     @Override
     public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
         configurer.enable();
     }
     
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
         FirstInterceptor firstInterceptor = new FirstInterceptor();
         registry.addInterceptor(firstInterceptor).addPathPatterns("
     @Override
     public void addViewControllers(ViewControllerRegistry registry) {
         registry.addViewController("").setViewName("");
     }
     
     @Bean
     public MultipartResolver multipartResolver() {
         return new CommonsMultipartResolver();
     }
     
     @Override
     public void configureHandlerExceptionResolvers(List resolvers) {
         SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
         Properties properties = new Properties();
         properties.setProperty("java.lang.ArithmeticException", "error");
         simpleMappingExceptionResolver.setExceptionMappings(properties);
         simpleMappingExceptionResolver.setExceptionAttribute("exception");
         resolvers.add(simpleMappingExceptionResolver);
     }
     
     @Bean
     public ITemplateResolver templateResolver() {
         WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
         if(webApplicationContext==null){
             return null;
         }
         ServletContext servletContext = webApplicationContext.getServletContext();
         if(servletContext==null){
             return null;
         }
         ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
         templateResolver.setPrefix("/WEB-INF/templates/");
         templateResolver.setSuffix(".html");
         templateResolver.setCharacterEncoding("UTF-8");
         templateResolver.setTemplateMode(TemplateMode.HTML);
         return templateResolver;
     }
     
     @Bean
     public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
         SpringTemplateEngine templateEngine = new SpringTemplateEngine();
         templateEngine.setTemplateResolver(templateResolver);
         return templateEngine;
     }
     
     @Bean
     public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
         ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
         viewResolver.setCharacterEncoding("UTF-8");
         viewResolver.setTemplateEngine(templateEngine);
         return viewResolver;
     }
 }
十五、SpringMVC的常用组件

1、DispatcherServlet:前端控制器
        (1)、是否需要工程师开发:不需要
        (2)、作用:统一处理请求和响应,整个流程控制的中心,由它调用其他组件处理用户的请求
2、HandlerMapping:处理器映射器
        (1)、是否需要工程师开发:不需要
        (2)、作用:根据请求的url、method等信息查找Handler,即控制器方法
3、Handler:处理器
        (1)、是否需要工程师开发:需要
        (2)、作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
4、HandlerAdapter:处理器适配器
        (1)、是否需要工程师开发:不需要
        (2)、作用:通过HandlerAapter对处理器进行执行
5、ViewResolver:视图解析器
         (1)、是否需要工程师开发:不需要
        (2)、作用:进行视图解析、的到响应的视图
6、View:视图
        (1)、是否需要工程师开发:不需要
        (2)、作用:将模型数据通过页面展示给用户

Mybatis 一、概述

1、概述:是一个基于Java的持久层框架
2、特性
        (1)、是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架
        (2)、避免了几乎所有的JDBC代码和手动设置参数以及获取结果集
        (3)、可以使用简单的XML或注解用于配置和原始映射,将接口和java的POJO映射成数据库的记录
        (4)、是一个半启动的ORM框架
3、官网:Mybatis
4、与其它持久化层技术对比 
        (1)、JDBC
                ①、SQL夹杂在Java代码中,耦合度高,导致硬编码内伤
                ②、维护不易且实际开发需求中SQL有变化,频繁修改的情况多见
                ③、代码冗长,开发效率低
        (2)、Hibemate和JPA
                ①、操作简便,开发效率高
                ②、程序中的长难度复杂的SQL需要绕过框架
                ③、内部自动生产的SQL,不容易做特殊优化
                ④、基于全映射的全自动框架,大量字段的POJO进行部分映射比较困难
                ⑤、反射操作太多,导致数据性能下降
        (3)、Mybatis
                ①、轻量级,性能出色
                ②、SQL和java代码分开,功能边界清晰,java代码专注业务、SQL语句专注数据
                ③、开发效率稍逊Hibemate,但是能完全接受
5、相应的API
        (1)、SqlSessionFactoryBuilder:工厂构建器
        (2)、SqlSessionFactory:获取工厂对象
                ①、openSession():默认开启开启一个事务,但要手动提交
                ②、openSession(boolean auto):为true时,自动提交
        (3)、SqlSession:会话对象
                ①、查询单个: T selectone (string statement, Object parameter)
                ②、查询全部: ListkselectList (String statement, object parameter)
                ③、插入数据:int insert (String statement, Object parame ter)
                ④、修改数据:int update (String statement, Object parameter)
                ⑤、删除数据:int delete (String statement, Object parameter)
                ⑥、提交事务:void commit()
                ⑦、回滚事务:void rollback()
                ⑧、获取接口的字节码文件: T getMapper(Class var1)
6、mapper接口开发规范
        (1)、Mapper.xml文件中的namespace与mapper接口的全限定名相同
        (2)、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
        (3)、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
        (4)、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

二、搭建框架

1、环境
        (1)、IDE:IDEA 2021.1.2
        (2)、构建工具:maven3.8.2
        (3)、MySQl版本:8.0
        (4)、Mybatis版本:3.5.9
2、创建maven工程


     
     
         org.mybatis
         mybatis
         3.5.9
     
     
     
         junit
         junit
         4.13.1
         test
     
     
     
         log4j
         log4j
         1.2.12
     
     
     
         org.projectlombok
         lombok
         1.18.22
     
 

3、创建数据库的表和实体

create table `user`(
     `id` int(0) not null primary key auto_increment comment '主键',
     `username` varchar(255) not null,
     `password` varchar(255) not null
 )
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
 public class User {
     private Integer id;
     private String username;
     private String password;
 }

4、创建映射文件

 
 
 
     
     
     select * from emp where 1=1
     
         and empName = #{empName}
     
     
         and age = #{age}
     
     
         and sex = #{sex}
     
     
         and email= #{email=}
     
 

2、where

 List getEmpCondition(Emp emp)
 
     select * from emp 
     
         
         
             empName = #{empName}
         
         
             age = #{age}
         
         
             sex = #{sex}
         
         
             email= #{email=}
          
     
 

4、choose、when、otherwise

 List getEmpChoose(Emp emp)
 
     select  from emp where did = #{did}
 
四、核心配置文件 (一)、模板

1、IDEA:点击File,然后在点击Settings,然后再点击Editor,再点击File and Code Templates,然后在Files下的+号进行点击,再然后Name,输入名字mybatis-config,再在Extension,输入后缀名xml,然后再在下面的输入框中输入信息,最后点击Apply,再点击OK,就完成核心配置文件的模板的创建

(二)、configuration

1、properties:属性
2、settings:设置
3、typeAliases:类型别名
4、typeHandlers:类型处理器
5、objectFactory:对象工厂
6、plugins:插件
7、environments:环境
        (1)、environment:环境变量
                ①、transactionManager:事务管理器
                ②、dataSource:数据源
8、databaseldProvider:数据库厂商标识
9、mappers:映射器

(三)、environment

1、概述:配置数据库的环境
2、属性
        (1)、id:指定当前环境的名称
3、子标签
        (1)、transactionManager:事务管理器,它的类型有以下两种
                ①、JDBC:直接使用JDBC的提交和回滚设置,依赖于数据源得到的连接来管理事务作用域
                ②、MANAGED:从来不提交或回滚连接,而是让容器管理整个生命周期,默认情况下关闭连接,需要将closeConnection属性设置为false来阻止关闭行为
        (2)、dataSource:数据源,它的类型有三种,它的标签是设置数据库的连接池的基本参数的配置
               ①、UNPOOLED:每次请求时打开和关闭连接
               ②、POOLED:实现利用"池"的概念将JDBC连接对象组织起来
               ③、JNDI:是为了能在如EJB或应用服务器这类容器中使用,容器可以集中或外部配置数据源,然后放置在一个JDNI上下文的引用

(四)、mappers

1、概述:引入映射文件的
2、加载方式
        (1)、使用相对于类路径的资源引用,例如:
        (2)、使用完全限定资源定位符(URL) ,例如:
        (3)、使用映射器接口实现类的完全限定类名,例如:
        (4)、将包内的映射器接口实现全部注册为映射器,例如:

(五)、properties

1、概述:引入外部properties文件的
2、使用:通过resource标签引入即可

(六)、typeAliases

1、概述:定义类型别名
2、已经定义好的类型别名

数据类型StringIntegrtListArrayListMapHashMapDateObject
别名stringintlistarraylistmaphashmapdateobject

3、注意实现:别名要定义在environments标签的上方

(七)、typeHandlers

1、概述:类型处理器
2、常用类型处理器

类型处理器Java类型数据库类型
BooleanTypeHandlerjava.lang.Boolean,booleanBOOLEAN
ByteTypeHandlerjava.lang.Byte,byteNUMERIC,BYTE
ShortTypeHandlerjava.lang.Short,shortNUMERTC,SHORT INTEGER
IntegerTypeHandlerjava.lang.Integer,intNUMERTC,INTEGER
LongTypeHandlerjava.lang.Long,longNUMERTC,LONGnINTEGER

3、开发步骤
         ①、定义转换类,继承类BaseTypeHandler
        ②、覆盖4个未实现的方法,其中setNonNullParameter为java程序设置数据到数据库的回调方法,getNullableResult为查询时mysql的字符串类型转换成java的Type类型的方法
        ③、在MyBatis核心配置文件中进行注册
        ④、测试转换是否正确
4、示例

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
public class DateTypeHandler extends BaseTypeHandler {
    
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
        long time = date.getTime();
        preparedStatement.setLong(i,time);
    }
    
    @Override
    public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
        long aLong = resultSet.getLong(s);
        Date date = new Date(aLong);
        return date;
    }
    
    @Override
    public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
        long aLong = resultSet.getLong(i);
        Date date = new Date(aLong);
        return date;
    }
    
    @Override
    public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        long aLong = callableStatement.getLong(i);
        Date date = new Date(aLong);
        return date;
    }
}


    
(八)、plugins

1、概述:可以使用第三方插件进行扩展
2、分页插件
        (1)、概述:使用插件获取分页数据 (
        2)、步骤
                ①、导入分页插件的坐标
                ②、配置插件
                ③、测试
        (3)、示例


    com.github.pagehelper
    pagehelper
    3.7.5


    com.github.jsqlparser
    jsqlparser
    0.9.1


    
        
    
//设置分页参数
PageHelper.startPage(1,2);

//获取分页相关参数
PageInfo pageInfo = new PageInfo(list);
System.out.println("当前页: " + pageInfo.getPageNum());
System.out.println("页显示条数: " + pageInfo.getPageSize());
System.out.println("总条数: " + pageInfo.getTotal());
System.out.println("总页数: " + pageInfo.getPages());
System.out.println("上一页: " + pageInfo.getPrePage());
System.out.println("下一页: " + pageInfo.getNextPage());
System.out.println("是否为第一页: " + pageInfo.isIsFirstPage());
System.out.println("是否为最后一页: " + pageInfo.isIsLastPage());
五、多表操作 (一)、一对一
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private Boolean age;
    private String sex;
    private StudentStatus studentStatus;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentStatus {
    private Integer id;
    private String num;
    private String major;
}

    
        
        
        
    
    
        select * from student s, student_status st where s.st_id = st.st_id
    



    
        
    
    
    
        select * from student s, class c where s.c_id = c.c_id
    

    
    
public class MybatisDemo {
    @Test
    public void TestA() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List list = sqlSession.selectList("com.mybatis.mapper.ClassMapper.findAll");
        for (Class aClass : list) {
            System.out.println(aClass);
        }
    }
}
(三)、多对多
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Course {
    private Integer cId;
    private String cName;
    private List students;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Integer sId;
    private String sName;
    private Long sAge;
    private String sSex;
    private List courses;
}

    
        
        
        
        
        
           
            
        
    
    
密码:

        (2)、登录成功页面




    
    mian


	登录成功

5、测试

三、类 (一)、UserDetailsService

1、概述:用来实现自定义登录逻辑的接口
2、loadUserByUsername:通过用户名来加载用户,并将用户传入到UserDetails接口中去

(二)、UserDetails

1、概述:是提供用户信息的核心接口
2、方法
        (1)、Collection getAuthorities():返回所有的权限
        (2)、String getPassword():获取密码
        (3)、String getUsername():货期用户名
        (4)、boolean isAccountNonExpired():判断用户是否过期
        (5)、boolean isAccountNonLocked():判断用户是否锁定
        (6)、boolean isCredentialsNonExpired():判断凭证是否过期
        (7)、boolean isEnabled():判断账号是否可用
3、实现类:User

(三)、PasswordEncoder

1、概述:提供的密码加密方式的接口
2、方法 (1)、String encode(CharSequence rawPassword):对密码进行加密,推荐使用BCryptPasswordEncoder加密方法 (2)、boolean matches(CharSequence rawPassword, String encodedPassword):将原始密码和加密后的密码进行匹配 (3)、default boolean upgradeEncoding(String encodedPassword):解析密码

四、自定义登录
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单提交
        http.formLogin()
                // 自定义密码和用户名的参数别名
                .usernameParameter("username")
                .passwordParameter("password")
                // 当发现是login是,就要走登录逻辑
                .loginProcessingUrl("/login")
                // 自定义登录页面
                .loginPage("/login.html")
                // 登录成功后的页面,必须是POST请求
                .successForwardUrl("/toMain")
                //登录成功处理器,不能和successForwardUrl共存
                //.successHandler(new MyAuthenticationFailureHandler("https://youdao.com/"))
                // 登录失败后的页面,必须是POST请求
                .failureForwardUrl("/toError");
                //登录失败处理器,不能和failureForwardUrl共存
                //.failureHandler(new MyAuthenticationFailureHandler("https://youdao.com/"));
        // 授权认证
        http.authorizeRequests()
                //登录页面不需要被认证
                .antMatchers("/login.html").permitAll()
                // 错误页面不需要被认证
                .antMatchers("/error.html").permitAll()
                //所有请求都必须被认证,才能访问
                .anyRequest().authenticated();
        //关闭csrf防护
        http.csrf().disable();
    }
}
@Controller
public class LoginController {
    @RequestMapping("toMain")
    public String toMain(){
        return "redirect:main.html";
    }
    @RequestMapping("toError")
    public String toError(){
        return "redirect:error.html";
    }
}
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    private String url;
    public MyAuthenticationFailureHandler(String url) {
        this.url = url;
    }
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.sendRedirect(url);
    }
}
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private String url;
    public MyAuthenticationSuccessHandler(String url) {
        this.url = url;
    }
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.sendRedirect(url);
    }
}
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String oldUserName = "admin";
        String oldPassWord = "123";
        if(!oldUserName.equals(username)){
            throw new UsernameNotFoundException("用户名不存在!");
        }
        String newPassWord = passwordEncoder.encode(oldPassWord);
        return new User(username,newPassWord, AuthorityUtils.commaSeparatedStringToAuthorityList(oldUserName));
    }
}
五、方法 (一)、授权

1、概述:本质就是请求 2、方法 (1)、anyRequest:所有请求 (2)、antMatchers:单个请求,也可以使用匹配符进行匹配 (3)、regexMathcers:使用正则表达式或者使用请求方式进行匹配 (4)、mvcMatchers:给请求加入一个前缀

(二)、访问控制

1、概述:请求的匹配符 2、方法 (1)、parmitAll:允许任何人访问 (2)、dentAll:所有人不允许访问 (3)、anonymous:匿名访问 (4)、authenticated:需要认证才可访问 (5)、fullAuthenticated:完全认证才可访问 (6)、remenberMe:规定时间内才可访问

(三)、权限判断

1、概述:用户登录后判断权限,严格区分大小写 2、方法 (1)、hasAuthority:用户是否具有特定权限就允许访问 (2)、hasAuythority:用户具有某一个权限就允许访问

(四)、角色判断

1、概述:用户登录后判断权限,严格区分大小写,在传入数据是必须要ROLE_开头才可以,后面验证不需要 2、方法 (1)、hasRole:用户是否具有特定用户就允许访问 (2)、hasAnyRole:用户具有某一个用户就允许访问

(五)、IP地址

1、概述:通过Id地址才能访问 2、方法 (1)、hasIpAddress:给定Ip地址才可访问

(六)、表达式控制

1、本质:access方法 2、作用:控制方法的访问 3、常用的表达式

表达式说明
hasRole([role])如果当前主体具有指定的角色,则返回true。默认情况下,如果提供的角色不是以'ROLE_'开头,它将被添加。这可以通过修改DefaulthebSecurityExpressionHandler上的defaultRolePrefix来定制
hasAnyRole([rolel,role2])如果当前主体具有任何提供的角色(以逗号分隔的字符串列表给出),则返回true。默认情况下,如果提供的角色不以'ROLE_'开头,则将添加该角色。这可以通过在DefaultwebSecurityExpressionHandler上修改defaultRolePrefix来定制
hasAuthority([authority1)如果当前主体具有指定的权限,则返回true。
hasAnyAuthority([authority1, authority2])如果当前主体具有任何提供的权限(以逗号分隔的字符串列表形式给出),则返回true
principal允许直接访问代表当前用户的主体对象
authentication允许直接访问从SecurityContext获得的当前Authentication对象
permitAll总是计算为true
denyAll计算结果总是为false
isAnonymous ()如果当前主体是匿名用户,则返回true
isRememberMe()如果当前主体是remember-me用户,则返回true
isAuthenticated()如果用户不是匿名的,则返回true
isFullyAuthenticated()如果用户不是匿名用户或remember-me用户,则返回true
hasPernission(Object target, Object permission)如果用户能够访问给定权限下提供的目标,则返回true。
hasPermission(Object targetId, String targetType, Object permission))如果用户有权限访问提供的目标,则返回true。为例。hasPermission (com . example。”域。消息”、“读”)

4、自定义权限控制 (1)、配置类

public interface MyService {
    boolean hasPermission(HttpServletRequest request, Authentication authentication);
}
@Service
public class MyServiceImpl implements MyService {
    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object o = authentication.getPrincipal();
        if (o instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) o;
            Collection authorities = userDetails.getAuthorities();
            return authorities.contains(new SimpleGrantedAuthority(request.getRequestURI()));
        }
        return false;
    }
}
http.authorizeRequests().anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");

(2)、注解

@Secured("ROLE_abc")
@RequestMapping("toError")
public String toError(){
    return "redirect:error.html";
}
ngBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringSecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityApplication.class, args);
    }
}
六、SpringSecurityOauth2 (一)、简介

1、授权服务器 (1)、Authorize Endpoint :授权端点,进行授权 (2)、Token Endpoint :令牌端点,进过授权拿到对应的 (3)、TokenIntrospection Endpoint :校验端点,校验Token的合法性 (4)、Revocation Endpoint :撤销端点,撤销授权 2、流程 (1)、用户访问,此时没有Token。 Oauth2RestTemplate会报错,这个报错信息会被Oauth2ClientContextFilter捕获并重定向到认证服务器 (2)、认证服务器通过Authorization Endpoint进行授权,并通过AuthorizationServerTokenServices生成授权码并返回给客户端 (3)、客户端拿到授权码去认证服务器通过Token Endpoint调用AuthorizationServerTokenServices生成Token并返回给客户端 (4)、客户端拿到Token去资源服务器访问资源,一般会通过Oauth2AuthenticationManager调用ResourceServerTokenServices进行校验。校验通过可以获取资源

(二)、授权模式

1、授权码模式


    org.springframework.cloud
    spring-cloud-starter-oauth2
    2.2.5.RELEASE



    org.springframework.cloud
    spring-cloud-starter-security
    2.2.5.RELEASE

2、密码模式

Oauth2 一、简介

1、概述:是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息 2、主要角色 (1)、Resource Owner(资源所有者):用户,即资源的拥有人,想要分享某些资 源给第三方应用 (2)、Resource Server(资源服务器):放受保护资源,要访问这些资源,需要获得访问令牌 (3)、Authorization server(授权(认证)服务器):授权服务器用于发放访问令牌给客户端 (4)、Client(客户端(第三方应用)):客户端代表请求资源服务器资源的第三方程序 3、常用术语 (1)、客户凭证(client Credentials):客户端的clientld和密码用于认证客户 (2)、令牌(tokens):授权服务器在接收到客户请求后,颁发的访问令牌 (3)、作用域(scopes):客户请求访问令牌时,由资源拥有者额外指定的细分权限(permission (4)、用户代理(User Agent):用户代理。一般就是指浏览器 4、令牌类型 (1)、授权码:仅用于授权码授权类型,用于交换获取访问令牌和刷新令牌 (2)、访问令牌:用于代表一个用户或服务直接去访问受保护的资源 (3)、刷新令牌:用于去授权服务器获取一个刷新访问令牌 (4)、Bear erToken:不管谁拿到Token都可以访问资源,类似现金 (5)、Prooof of Possession(PoP) Token:可以校验client是否对Token有明确的拥有权 5、优点 (1)、更安全,客户端不接触用户密码,服务器端更易集中保护 (2)、广泛传播并被持续采用 (3)、短寿命和封装的token (4)、资源服务器和授权服务器解耦 (5)、集中式授权,简化客户端 (6)、HTTP/JSON友好,易于请求和传递token考虑 (7)、多种客户端架构场景 (8)、客户可以具有不同的信任级别 6、缺点 (1)、协议框架太宽泛,造成各种实现的兼容性和互操作性差 (2)、不是一个认证协议,本身并不能告诉你任何用户信息。

二、授权模式 (一)、授权码模式

1、概述:是功能最完整、使用最广泛、流程最严密的授权模式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌 2、步骤 (1)、用户访问客户端,客户端将用户导向授权服务器,通过用户代理(User-Agent)发送包括它的客户端标识符、请求的范围、本地状态和一个重定向URI,授权服务器在授予(或拒绝)访问权后将其发送给用户代理 (2)、授权服务器对资源所有者进行身份验证(通过用户代理,让用户输入用户名和密码),并确定资源所有者是否授予或拒绝客户端的访问请求。 (3)、用户跳转后,假如资源所有者同意授权请求,那么授权服务器将会使用前面提供的或者事先指定的重定向URI(redirection URI),重定向到客户端,并附上一个授权码(code)和一个前面提供的本地状态(state)(如果有的话,则会原值返回) (4)、客户端收到授权码,附上早先的重定向URI,向授权服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。在发出请求时,授权服务器对客户端进行身份验证。请求参数包含授权代码、用于获得验证的授权代码的重定向URI、标识客户端身份的client id和client secret (5)、授权服务器对客户端进行身份验证,验证授权代码,并确保所收到的重定向URI与用于在步骤©中对客户端重定向的URI相匹配,如果有效,授权服务器将发送访问令牌access token和刷新令牌refresh token,然后授权服务器给我们返回授权码

(二)、简化模式

1、概述:不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证 2、步骤 (1)、用户访问客户端,客户端将用户导向授权服务器,通过用户代理(User-Agent)发送包括它的客户端标识符、请求的范围、本地状态和一个重定向URI,授权服务器在授予(或拒绝)访问权后将其发送给用户代理 (2)、授权服务器对资源所有者进行身份验证(通过用户代理,让用户输入用户名和密码),并确定资源所有者是否授予或拒绝客户端的访问请求 (3)、用户跳转后,假如资源所有者同意授权请求,那么授权服务器将会使用前面提供的或者事先指定的重定向URI(redirection URI),重定向到客户端,并附上访问令牌等信息

(三)、密码模式

1、概述:用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权 2、步骤 (1)、用户访问客户端,客户端将用户导向授权服务器,然后提供URI连接包含用户名和密码信息给授权服务器 (2)、授权服务器认证用户名和密码信息正确后,然后返回客户端access_token等信息

(四)、客户端模式

1、概述:客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证 2、步骤 (1)、客户端直接向授权服务器发起认证请求 (2)、授权服务器通过认证后,直接返回客户端access_token等信息

JWT 一、简介

1、常见的认证机制 (1)、HTTP Basic Auth (2)、Cookie Auth (3)、OAuth (4)、Token Auth 2、概述:JSON网络令牌,JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式在不同实体之间安全传输信息(JSON格式)。它是在Web环境下两个实体之间传输数据的一项标准 3、官网:JWT 4、优点 (1)、jwt基于json,非常方便解析 (2)、可以在令牌中自定义丰富的内容,易扩展 (3)、通过非对称加密算法及数字签名技术,JWT防止篡改 (4)、资源服务使用JWT可不依赖认证服务即可完成授权 5、缺点:JWT令牌较长,占存储空间比较大 6、组成: (1)、头部:描述关于该JWT最基本的信息 (2)、载荷:存放有效信息的地方 (3)、签名:签证信息

二、实现 (一)、永久有效

    io.jsonwebtoken
    jjwt
    0.9.1
@Test
void getToken() {
    JwtBuilder jwtBuilder = Jwts.builder()
        // 标识
        .setId("8888")
        // 用户
        .setSubject("海")
        // 时间
        .setIssuedAt(new Date())
        .signWith(SignatureAlgorithm.HS256, "0903");
    String token = jwtBuilder.compact();
    System.out.println(token);
    String[] split = token.split("\.");
    for (String s : split) {
        System.out.println(Base64Codec.BASE64.decodeToString(s));
    }
}

@Test
void parseToken() {
    String token = "";
    Claims body = Jwts.parser()
        .setSigningKey("0903")
        .parseClaimsJws(token)
        .getBody();
    System.out.println(body.getId());
    System.out.println(body.getSubject());
    System.out.println(body.getIssuedAt());

}
(二)、超时失效

    io.jsonwebtoken
    jjwt
    0.9.1
@Test
void getToken1() {
    long now = System.currentTimeMillis();
    long exp = now + 60 * 10000;
    JwtBuilder jwtBuilder = Jwts.builder()
        // 标识
        .setId("8888")
        // 用户
        .setSubject("海")
        // 时间
        .setIssuedAt(new Date())
        .setExpiration(new Date(exp))
        .signWith(SignatureAlgorithm.HS256, "0903");
    String token = jwtBuilder.compact();
    System.out.println(token);
    String[] split = token.split("\.");
    for (String s : split) {
        System.out.println(Base64Codec.BASE64.decodeToString(s));
    }
}

@Test
void parseToken1() {
    String token = "";
    Claims body = Jwts.parser()
        .setSigningKey("0903")
        .parseClaimsJws(token)
        .getBody();
    System.out.println(body.getId());
    System.out.println(body.getSubject());
    System.out.println(body.getIssuedAt());
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println("签发时间" + simpleDateFormat.format(body.getIssuedAt()));
    System.out.println("过期时间" + simpleDateFormat.format(body.getExpiration()));
    System.out.println("当前时间" + simpleDateFormat.format(new Date()));
}
(三)、自定义声明

    io.jsonwebtoken
    jjwt
    0.9.1
@Test
void getToken2() {
    JwtBuilder jwtBuilder = Jwts.builder()
        // 标识
        .setId("8888")
        // 用户
        .setSubject("海")
        // 时间
        .setIssuedAt(new Date())
        .signWith(SignatureAlgorithm.HS256, "0903")
        //自定义声明
        .claim("roles","admin")
        .claim("logo","ss.jpg");
    String token = jwtBuilder.compact();
    System.out.println(token);
    String[] split = token.split("\.");
    for (String s : split) {
        System.out.println(Base64Codec.BASE64.decodeToString(s));
    }
}


@Test
void parseToken2() {
    String token = "";
    Claims body = Jwts.parser()
        .setSigningKey("0903")
        .parseClaimsJws(token)
        .getBody();
    System.out.println(body.getId());
    System.out.println(body.getSubject());
    System.out.println(body.getIssuedAt());
    System.out.println(body.get("logo"));
    System.out.println(body.get("roles"));

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/862783.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号