Spring

Spring,第1张

Spring

文章目录
  • Spring
    • maven创建Spring项目
  • IOC
    • xml配置文件
      • 约束
      • import标签
      • alias标签
      • bean标签
      • 读取properties配置文件
      • 启动注解
      • 启动注解自动扫描
    • DI
      • 1. xml注入
        • 1.1 Constroctur注入
        • 1.2 Setter注入
        • 1.3 注入类型
        • 1.4 p namespace
        • 1.5 c namespace
        • 1.6 Bean Scrops
        • 1.7 autowire自动装配
      • 2. annotation注入
        • 2.1 注解启动
        • 2.2 自动扫描
        • 2.3 @Autowired
        • 2.4 @Qualifier
        • 2.5 @Value
        • 2.6 @Resource
        • 2.7 @Component
        • 2.8 @Scope
    • 使用Java代码实现配置
      • 1. @Configuration
      • 2. @Bean
      • 3. @ComponentScan
      • 4. @import
  • AOP
    • 通过Advice接口实现AOP
    • 通过自定义法实现AOP
    • 通过注解实现AOP
  • Spring-Mybatis
    • 项目流程
      • 1. 创建实体类
      • 2. 创建dao接口
      • 3. 创建mapper文件
      • 4. 创建mybatis配置文件
      • 5. 创建dao配置文件
      • 6. 创建dao实体类
      • 7. 创建IOC配置文件
      • 8. 测试文件
    • spring_dao.xml配置文件
    • 配置Dao接口扫描包
  • Servlet
    • 创建流程
      • 1. 创建项目
      • 2. 导包
      • 3. 创建Servlet类
      • 4. 创建web.xml配置文件
      • 5. 配置Tomcat
    • web.xml 配置文件
    • HttpServlet类
    • GenericServlet类
    • ServletConfig类
    • ServletContext类
        • 1. 共享数据
        • 2. 获取初始化参数
        • 3. 请求转发
        • 4. 读取资源文件
        • 5. 获取项目文件路径
    • HttpServletRequest类
        • 1. 获取表单数据
        • 2. 请求转发
    • HttpServletResponse类
        • 1. 设置头部信息
        • 2. 向网页输出信息
        • 3. 重定向
        • 4. 下载文件
    • 过滤器Filter
      • 举例说明
      • Filter分析
        • init()
        • doFilter()
        • destory()
      • 处理乱码问题
      • 登录验证
    • 监听器Listener
      • 举例说明
  • SpringMVC
    • 项目流程
      • 1. 注册DispatcherServlet
      • 2. 创建IOC配置文件
      • 3. 创建Controller
        • 接口定义
        • 注解
      • 4. 创建jsp
      • 5. 补充
    • 思路分析
    • 注解开发SpringMVC
      • 1. @Controller
      • 2. @RequestMapping
      • 3. @PathVariable
      • 4. 举例
    • Controller讲解
      • 接口定义
      • 注解
    • 转发和重定向
    • 接收请求参数
    • 过滤器Filter
      • 内置乱码过滤器
      • 自定义权限过滤器
    • 拦截器Interceptor
      • 定义拦截器
      • 配置拦截器
    • 监听器Listener
  • SpringBoot
    • 快速创建
      • 1. IDEA创建SpringBoot
      • 2. 创建Controller
      • 3. 启动主程序
      • 4. maven依赖说明
      • 5. 项目打包成jar包
      • 6. 常见问题
    • 一些对框架的理解
      • 1. pom.xml文件
      • 2. 主启动类
        • 注解
        • main方法
    • yaml
      • 基本语法规则
      • 数据结构
    • SpringBoot配置文件
    • 属性注入
      • 原始方法
      • Properties注入
      • yaml注入
    • JSR303校验
    • 多环境切换
      • 配置文件优先级
      • 多环境配置
    • spring.factories分析
    • 关于WebMvc的配置
      • 静态资源路径
      • 静态资源映射规则
      • 设置首页
      • 扩展MVC
        • 源码解析
        • 自定义视图解析器
        • 配置格式转换
        • 视图跳转
        • 自定义拦截器
    • 国际化配置
      • 1. 配置文件路径
      • 2. 在网页中引入配置
      • 3. 自定义区域设置解析器
    • Thymeleaf模板
      • 导入依赖
      • 源码分析
      • 举例分析
      • 语法
    • 过滤器Filter
      • 创建过滤器Filter
      • 注册过滤器
    • 拦截器Interceptor
      • 创建拦截器
      • 注册拦截器
    • 监听器Listener
      • 创建监听器
      • 注册监听器
  • SpringBoot-JDBC
    • 项目流程
      • 1. 导入依赖
      • 2. 配置数据源
      • 3. 测试数据库连接
      • 4. 创建Dao层
    • JdbcTemplate模板
  • SpringBoot-Mybatis
    • 项目流程
      • 1. 导入依赖
      • 2. Mybatis配置
      • 3. 创建Pojo实体对象
      • 4. 创建dao接口
      • 5. 创建Dao映射文件
      • 6. 测试
    • 配置Mapper接口
  • SpringBoot-Mybatis-Plus
    • 项目流程
      • 1. 导入依赖
      • 2. Mybatis-plus配置
      • 3. 创建Pojo实体类
      • 4. 创建dao接口
      • 5. 配置扫描mapper包
      • 6. 测试
    • 配置日志
    • 主键生成策略
    • 自动填充处理
    • 悲观锁
    • 乐观锁
      • 实现方式
      • 举例
    • 分页查询
    • 逻辑删除
    • 条件构造器
    • CRUD
      • 1. insert
      • 2. select
      • 3. update
      • 4. delete
    • 代码自动生成器
      • 项目流程
        • 1. 导入依赖
        • 2. 配置数据源
        • 3. 编写自动生成器
        • 4. 配置并测试dao接口
        • 5. 编写Service层
      • 解说
  • SpringSecurity
    • 项目流程
      • 1. 导入依赖
  • SpringCloud

Spring

简介:???

优点:???

组成:

七大模块
  • Spring Croe
  • Spring AOP
  • Spring ORM
  • Spring DAO
  • Spring Web
  • Spring Context
  • Spring MVC

三大思想

  • DI(依赖注入)
  • IOC(控制反转)
  • AOP(面向切面)
maven创建Spring项目
    
        
            org.springframework
            spring-core
            5.2.3.RELEASE
        
        
            org.springframework
            spring-context
            5.2.3.RELEASE
        
        
            org.springframework
            spring-beans
            5.2.3.RELEASE
        
    
IOC

简介:控制反转(Inversion of Control,缩写IOC)。把对象的创建和获取交给第三方来控制,第三方的主要手段是XML或注解。在spring中IOC容器的实现方法 是依赖注入(Dependency Injection,缩写DI)

使用到的技术:工厂模式 + 反射 + XML

测试:获取ApplicationContext对象,调用getBean()方法获取bean

public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplication("applicationContext.xml");
    Student student = applicationContext.getBean("student1", StudentDao.class);
}
xml配置文件

spring配置文件,命名任意,一般为applicationContext.xml,路径一般在classpath(即resources目录)

xml配置文件的根元素是

约束

配置文件的约束时xml Schema




import标签

作用:导入。导入其他xml配置文件


alias标签

作用:别名。

 
bean标签 

作用:注册实体类,又IOC容器管理这些bean实例

bean实例对象的属性通过DI(Dependency Injection 依赖注入)来赋值

读取properties配置文件

启动注解

启动注解自动扫描

DI

简介:DI(dependency Injection 依赖注入)

  • 注入方式
    • xml注入
      • Constructor注入
      • setter注入
    • annotation注入
  • 注入类型
    • 基本类型注入
    • list注入
    • map注入
    • 引用注入
1. xml注入 Setter InjectionConstructor Injection条件有setter方法、无参构造函数有参构造函数格式在bean内, 或
在bean内, 或
1.1 Constroctur注入

按参数顺序注入


    
    

按参数名注入


    
    

1.2 Setter注入

    
    

1.3 注入类型

基本类型注入:value属性


    
    

list注入:list子元素、value子元素(文本)


    			
        
            北京
            上海
            广东
        
    

map注入:map子元素、entry子元素(key、value属性)


    			
        
            
            
            
        
    

引用注入:ref属性


	
        
    




	


1.4 p namespace
  • 实现条件:在约束中加入xmlns:p="http://www.springframework.org/schema/p"

  • 作用:可以使子元素变成属性来使用


    




	



1.5 c namespace
  • 实现条件:在约束中加入xmlns:c="http://www.springframework.org/schema/c"
  • 作用:同p namespace,把构造器属性constructor-arg子元素转换成属性来使用

    
    




    
    



1.6 Bean Scrops
  • singleton:单例模式。bean默认是单例的

    • 图解:

    • 代码举例:

      
      
      // 测试文件
      ApplicationContext beans = new ClassPathXmlApplicationContext("beans.xml");
      Date date1 = beans.getBean("date", Date.class);
      Date date2 = beans.getBean("date", Date.class);
      System.out.println(date1 == date2);
      
      
  • protoType:原型模式

    • 图解:

    • 代码举例

      
      
      // 测试文件
      ApplicationContext beans = new ClassPathXmlApplicationContext("beans.xml");
      Date date1 = beans.getBean("date", Date.class);
      Date date2 = beans.getBean("date", Date.class);
      System.out.println(date1 == date2);
      
      
  • request

  • session

  • application

  • websocket

1.7 autowire自动装配
  • 简介:bean的一个属性autowire

  • 作用:控制是否启动自动装配功能

  • 取值:

    • default:有效的默认值是"no"
    • no:不启动
    • byName:启动,查找容器中,bean的id与setter方法的形参名相同的bean,有则注入
    • byType:启动,查找容器中,bean的class与setter方法的形参类型相同的bean,有则注入(class不能重复,否则报错)
    • constructor:启动,查找容器中,bean的class与constructor方法的形参类型相同的bean,有则注入(class不能重复,否则报错)
  • 注意:property和constructor-arg子元素,可以覆盖autowire自动装配

2. annotation注入 2.1 注解启动

导入约束xmlns:context="http://www.springframework.org/schema/context"

配置注解支持context:annotation-config




    


2.2 自动扫描

    
    

2.3 @Autowired
  • 自动装配引用类型属性

  • 使用方法:

    • setter上
    • constructor上
    • method上
    • fields上
    • **fields[]**上:匹配容器中,所有class相同的,都加入到数组中
  • 效果:在容器中,先匹配bean的class,再匹配id,匹配成功则注入(即,若class匹配到多个,则选id匹配的)(即先bytype,后byname

  • 注意:@Autowired有一个required()方法,默认为true,若**@Autowired(required=false)**,表示非必要,即,若在容器中,没有匹配到bean,也正常运行,不会报错

  • @Autowired(required=false)等价于@Autowired @Nullable,即给参数添加@Nullable注解

  • java的原注解**@Resource**等价于@Autowired

2.4 @Qualifier
  • 简介:指定装配引用类型属性

  • 使用环境:自动装配环境很复杂时,可以使用@Qualifier配合@Autowired

  • @Qualifier(value=“bean的id”)

    
    
    
    @Autowired					// 自动装配
    @Qualifier(value="cat1")	// 配合Autowired使用,指定id=cat1的Cat类的实例对象
    private Cat cat;
    
2.5 @Value
  • 简介:装配基础类型属性

  • 使用方法:

    • Field上
    • setter上
  • @Value(“值”)

    @Value("hexu")
    private String name;
    
2.6 @Resource
  • 简介:装配引用类型属性

  • 使用方法:

    • Field上
    • setter上
  • @Resource(name=“bean id”)

    @Resource(name = "dog")
    private Dog dog;
    
  • 注意:@Resource需要包javax.annotation-api的支持,maven导入如下

    
        javax.annotation
        javax.annotation-api
        1.3.2
    
    
2.7 @Component
  • 作用:定义bean。启动bean扫描时,容器扫描带有**@Component**注解的类,创建bean对象

  • bean id设置:

    • 默认是类名小写
    • @Component(value=“bean id”)
  • bean属性注入:

    • 基础类型注入

      • 添加==@Value(“属性值”)==到Field字段或setter方法上
    • 引用注入

      • 添加==@Resource(name=“bean id”)==到Field字段或setter方法上

      • 添加==@Autowired==到Field字段或setter方法上,自动装配

      • 添加==@Autowired==和@==Qualifier(value=“bean id”)==到Field字段或setter方法上,指定装配

  • 衍生注解:@Repository、@Service、@Controller

2.8 @Scope
  • 作用:设置bean作用域

  • 取值:

    • singleton
    • prototype
  • 举例:

    @Component
    @Scope(value="singleton")
    public class People() {
        // ...
    }
    
使用Java代码实现配置

使用Java文件进行spring的配置,不使用xml文件配置

测试文件

  • 使用初始化AnnotationConfigApplicationContext(java配置类.class)获取ApplicationContext对象,调用==getBean()==方法获取bean
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
    Dog dog = ctx.getBean("getDog", Dog.class);
}
1. @Configuration

Annotating a class with @Configuration indicates that its primary purpose is as a source of bean definitions

标注@Configration注解的类,是spring的配置类

@Configuration
public class SpringConfig() {
    // ...
}

等价于


	...

2. @Bean

The @Bean annotation is uesd to indicate that a method instantiates, configures, and initializes a new object to be managed by the Spring IOC container.

标注@Bean注解的方法,表示初始化一个bean

@Bean
public Dog getDog() {
    return new Dog("cc1", 1);
}

等价于


注意:方法名相当于bean id,返回类型相当于bean class(即id=“getDog”, class=“Dog”)

3. @ComponentScan

启动注解扫描

@Configuration
@ComponentScan(value = "com.hexu.bean")
public class SpringConfig {
    // ...
}

等价于


	

4. @import

导入其他java配置文件,与Configuration同用

@Configuration
@import(value = "SpringConfig2.class")
public class SpringConfig {
    // ...
}
AOP

AOP(Aspect Oriented Programming),面向切面变成

提供声明事务,允许用户自定义切面

使用到的技术:预编译 + 动态代理模式

好处:降低耦合,提高程序可重用性

AOP名词

  • 横切关注点:应用在多个模块的方法或功能。即,与业务逻辑无关,如日志、安全、缓存、事务。
  • 切面(Aspect):横切关注点被模块化的特殊对象。即,一个类。
  • 通知(Advice):切面必须要完成的工作。即,类的方法
  • 目标(Target):被通知的对象。
  • 代理(Proxy):
  • 切入点(PointCut):切面通知(类方法)执行的地方的定义
  • 连接点(JointPoint):

通知(Advice)分类:

通知类型连接点实现接口前置通知方法前org.springframework.aop.MethodBeforeAdvice后置通知方法后org.springframework.aop.AfterReturningAdvice环绕通知方法前后org.springframework.aop.MethodInterceptor异常抛出通知方法抛出异常org.springframework.aop.ThrowsAdvice引介通知类中增加新的方法属性org.springframe.work.aop.IntroductionInterceptor

maven项目导入依赖包


    org.aspectj
    aspectjweaver
    1.9.5

spring配置

  • aop约束配置



execution表达式

 

execution():表达式的主题

参数一:表示返回值类型,*是任意类型

参数二:表示包名,com.hexu.service表示这个包的路径

参数三:类名,*表示所有类

参数四:方法,*表示所有方法

参数五:()表示参数,…表示任意类型

AOP实现方法

  • 通过实现Advice接口,定义通知,定义切入点,通知-切入点关联
  • 自定义切面
  • 注解
通过Advice接口实现AOP

即实现通知(Advice)的五个分类:

  • 前置通知:org.springframework.aop.MethodBeforeAdvice
  • 后置通知:org.springframework.aop.AfterReturningAdvice
  • 环绕通知:org.springframework.aop.MethodInterceptor
  • 异常抛出通知:org.springframework.aop.ThrowsAdvice
  • 引介通知:org.springframework.aop.IntroductionInterceptor

真实的对象(如Service服务类)

public interface IUserService {
    public void create();
    public void retrieve();
    public void update();
    public void delete();
}
public class UserService implements IUserService{
    @Override
    public void create() {
        System.out.println("新增一个用户");
    }

    @Override
    public void retrieve() {
        System.out.println("查找一个用户");
    }

    @Override
    public void update() {
        System.out.println("更新一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除一个用户");
    }
}

定义通知类型

// 定义前置通知BeforeAdvice
// method:接口的方法对象method
// objects:
// target:实现接口的真实对象
public class Log implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object target) throws Throwable {
        String targetClassName = target.getClass().getName();
        String interfaceName = method.getDeclaringClass().getName();
        String methodName = method.getName();
        System.out.println("执行" + targetClassName + "类的" + methodName + "方法");
    }
}

xml配置文件




    
    
    

测试代码

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext beans = new ClassPathXmlApplicationContext("aop_beans.xml");
        IUserService userService = beans.getBean("userService", IUserService.class);// 注意,这里一定要用接口,因为返回的是一个proxy
        userService.create();
    }
}

通过自定义法实现AOP

定义通知类型:不用实现advice接口

public class Log {
    public void after() {
        System.out.println("=====前置通知=====");
    }

    public void before() {
        System.out.println("=====后置通知=====");
    }
}

xml配置文件




    
    
    

    
    
        
        
            
            
            
            
            
        
    


通过注解实现AOP

注解创建切面

@Aspect
public class AnnotationLog {
    @Before("execution(* com.hexu.service.UserService.*(..))")
    public void before() {
        System.out.println("这是注解实现的前置通知");
    }
}

xml配置文件




    
    
    

    
    
    	

Spring-Mybatis

maven创建Spring-Mybatis


    org.mybatis
    mybatis-spring
    2.0.3

项目流程

项目结构如下

maven项目导入依赖包

1. 创建实体类

创建持久层的com.hexu.bean.User实体类

public class User {
    private int id;
    private String userName;
    private String password;
    // Constructor、Getter&Setter、toString方法
}
2. 创建dao接口

创建持久层的com.hexu.dao.IUserDao接口

public interface IUserDao {    
    List selectUser();    
    User selectUserById(int id);    
    int insertUser(User user);    
    void updateUser(User user);    
    void deleteUser(int id);
}
3. 创建mapper文件

创建映射文件:user_mapper.xml




    
        select * from login_user where id=#{id};
    

    
        insert into login_user (id, userName, password)
        value (#{id}, #{userName}, #{password});
    

    
        update login_user set userName=#{userName}, password=#{password} where id=#{id};
    

    
        delete from login_user where id=#{id};
    

4. 创建mybatis配置文件

创建mybatis配置文件:mybatis_config.xml






    
        
    

    
        
    


5. 创建dao配置文件

创建spring_dao.xml配置文件

主要用于创建数据源dataSource和工厂Factory两个bean

详细请看spring_dao.xml配置文件

6. 创建dao实体类

创建dao实体类com.hexu.dao.UserDao

注入SqlSession,用于执行sql

方法一:原始方法,注入SqlSessionTemplate属性

package com.hexu.dao;

import com.hexu.bean.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserDao implements IUserDao{

    SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List selectUser() {
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        return userDao.selectUser();
    }
	// .....如此类推
}

方法二:继承SqlSessionDaoSupport类,注入SqlSessionTemplate属性或SqlSessionFactory属性

public class UserDao2 extends SqlSessionDaoSupport implements IUserDao {
    @Override
    public List selectUser() {
        IUserDao userDao = getSqlSession().getMapper(IUserDao.class);
        return userDao.selectUser();
    }
    // .....如此类推
}
7. 创建IOC配置文件

创建applicationContext.xml配置文件




    
    

    
        
    

    
        
    


8. 测试文件
@Test
public void testSelectUser() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    IUserDao userDao = applicationContext.getBean("userDao", IUserDao.class);
    List users = userDao.selectUser();
    for (User user: users) {
        System.out.println(user);
    }
}
spring_dao.xml配置文件

主要内容:数据源dataSource + 工厂Factory

可选内容:properties配置文件的读取 + SqlSession

创建工厂时,需要传入数据源和mybatis_config配置文件路径、可选着是否传入mapper文件路径

# database.properties
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/dee
jdbc.username = root
jdbc.password = root


	
    
    
	
    
    
        
        
        
        
    
	
    
    
        
        
        
        
        

    
	
    
    
        
    


配置Dao接口扫描包

创建一个bean,配置dao接口扫描包,动态的实现了Dao接口可以注入到Spring IOC 容器中

即无需创建dao实体类(用于获取SqlSession对象然后执行sql返回结果的)

MapperScannerConfigurer类为每个映射接口(interface dao/mapper)创建了实体类,在Service中使用注解@Autowired自动注入即可




    

    
        
        
        
        
    

    
        
        
    
    
    
    
        
        
        
        
    

@Service
public class UserService implements IUserService{

    @Autowired
    private IUserDao userDao;

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public List selectUser() {
        return userDao.selectUser();
    }
    // ...其他照常
}

Servlet

Server Applet,简称Servlet,称为小程序服务,用Java编写的服务器端程序

作用:接收Client Request请求,返回Server Response响应。

必备知识:Tomcat

Tomcat

Tomcat是一个Servlet容器

Tomcat的lib目录下,有一个jar包servlet-api.jar,这是Tomcat和Servlet的接口

Tomcat目录:

  • bin:存放启动、关闭等脚本文件
  • conf:配置
  • lib:插件、依赖包
  • logs:日志
  • temp:临时文件
  • webapps:存放网页文件
  • work:工作文件

servlet生命周期

  1. 创建:执行init()初始化方法
  2. 运行:tomcat接收Http请求,解析后创建ServletRequest和ServletResponse,传递给Servlet.service()方法,service()中处理请求并返回相应结果
  3. 销毁:执行destroy方法
创建流程 1. 创建项目

创建Maven项目,导入Web框架

导入Web框架后,项目结构会多出一个Web文件夹,图标上带有蓝色小圆点

2. 导包

servlet-api 和 jsp-api

    
    javax.servlet    
    servlet-api    
    2.5

    
    javax.servlet.jsp    
    jsp-api    
    2.0

3. 创建Servlet类

Servlet类必须**实现Servlet接口**。

JDK内置了抽象类HttpServlet、GenericServlet,他们都实现了Servlet接口

一般创建Servlet类的方法:继承HttpServlet类,重写doGet()和doPost()方法

public class MyServlet extends HttpServlet {    
    @Override    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        // Get请求执行的内容
    }    
    @Override    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        // Post请求执行的内容
    }
}
4. 创建web.xml配置文件

xml约束 + 注册Servler + Servlet映射



	
        
        hello								    
        com.hexu.servlet.MyServlet		
    
    
        
        hello		    
        /hello		
    

5. 配置Tomcat web.xml 配置文件

	    
        
            
        url        
        jdbc:mysql://localhost:3306/dee    
            
    
        
            
        hello        
        com.hexu.servlet.MyServlet    
        
        
            
        hello        
        /hello    
    

  • context-param元素:
    • param-name子元素:参数名
    • param-value子元素:参数值
  • servlet元素:
    • servlet-name子元素:servlet名
    • servlet-class子元素:实现了Servlet接口的类的全类名
  • servlet-mapping元素:
    • servlet-name子元素:指定servlet
    • url-pattern子元素:指定client浏览器请求地址
    • 注意:
      • 同一个servlet可以配置多个servlet-mapping。
      • *****表示通配符。
      • 固有路径比*通配符的优先级高
HttpServlet类

源码分析

继承了GenericServlet抽象类

一个public方法:servlet(),该方法指向protected的service()方法,然以后根据request的method(请求方法)的不同,来调用不同的请求方法

如doGet()、doHead()、doPost()、doPut()、doDelete()、doOptions、doTrace

GenericServlet类

实现了Servlet接口、ServletConfig接口

关键属性:ServletConfig、ServletContext

类结构如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C1GKTyV0-1635779669374)(Spring.assets/image-20210927151101918.png)]

源码分析

init()方法,表明,该方法由servlet容器(Tomcat)调用,作用是表明一个servlet称为了一个服务

并且在init时,初始化了ServletConfig属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5SMB13vq-1635779669377)(Spring.assets/image-20210927151159106.png)]

由此可知,ServletContext是由ServletConfig创建的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ozOTKxvJ-1635779669392)(Spring.assets/image-20210927151422392.png)]

ServletConfig类
  • 获取:this.getServletConfig();
ServletContext类

原:

Defines a set of methods that a servlet uses to communicate with its servlet container, for example, to get the MIME type of a file, dispatch requests, or write to a log file.

There is one context per “web application” per Java Virtual Machine.

The ServletContext object is contained within the ServletConfig object, which the Web server provides the servlet when the servlet is initialized.

译:

ServletContext定义了Servlet与Servlet容器(eg. Tomcat)交互的一系列方法

每一个web application(web 程序),每一个Java Virtual Machine(JVM虚拟机)都只有一个ServletContext上下文

ServletContext对象包含在ServletConfig对象里面。ServletConfig对象在servlet初始化时就提供了

获取:this.getServletContext();

1. 共享数据

使用**setAttribute();getAttribute();**

// 放入数据
public class SetContextServlet extends HttpServlet {    
    @Override    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        ServletContext servletContext = this.getServletContext();                                        
        servletContext.setAttribute("name", "Dee");    
    }   
    @Override    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        doGet(req, resp);    
    }
}
// 取出数据
public class GetContextServlet extends HttpServlet {
    @Override    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        ServletContext servletContext = this.getServletContext();        
        String name = (String) servletContext.getAttribute("name");        
        PrintWriter writer = resp.getWriter();        
        writer.println(name);    
    }    
    @Override    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        doGet(req, resp);    
    }
}
2. 获取初始化参数

使用**getInitParameters()方法或setInitParameter()**方法,获取web.xml配置文件的参数


    url
    jdbc:mysql://localhost:3306/dee

ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
3. 请求转发

ServletContext的getRequestDispatcher();获取请求调度器dispatcher

指定调度器dispatcher的forward方法进行转发

注意:请求转发,client浏览器的url不变

格式:this.getServletContext.getRequestDispatcher("/xxx").forward(request, response);

public class ForwardServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        // 获取请求调度器,请求转发到/targetServlet
        this.getServletContext.getRequestDispatcher("/targetServlet").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
4. 读取资源文件

主要用到的方法:

  • 获取资源流:getResourceAsStream()
  • new Properties对象,并加载数据流load()
  • Properties对象获取参数getPropertiy()

maven项目中,recources文件夹里的资源,在编译后都会在项目路径下/WEB-INF/classes/的地方生成对应文件

public class PropertiesServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        InputStream inputStream = context.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        String userName = properties.getProperty("userName");
        String password = properties.getProperty("password");
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println("用户名:"+ userName + "密码:" + password);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
5. 获取项目文件路径

主要方法:getRealPath(String path)

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String picPath = context.getRealPath("myPic.png");
        // 输出:servlet_test_war_exploded是正在运行的项目的路径
        // G:IDEAWorkSpaceSpringWorkSpacespringmvc_testoutartifactsservlet_test_war_explodedmyPic.png
        System.out.println(picPath);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
HttpServletRequest类 1. 获取表单数据

使用request.**getParameter()**方法

可以获取post请求的表单参数,也可以获取get请求的参数,eg.http://localhost:8080/servlet_project/index.jsp?userName=root,获取参数userName为root

String userName = request.getParameter("userName");
String password = request.getParameter("password");
2. 请求转发

使用**request.getRequestDispatcher().forward()**方法

WEB-INF目录下的文件是不可被客户端直接访问的,需要通过请求servlet进行转发

request.getRequestDispatcher("/WEB-INF/main.jsp").forward(request, response);
HttpServletResponse类 1. 设置头部信息

设置contentType,使用response.**setContentType()**方法

response.setContentType("text/html;charset=UTF-8");
2. 向网页输出信息

获取**PrintWriter对象,使用resoponse.getWriter()**方法

PrintWriter writer = response.getWriter();
writer.println("Hello World");
3. 重定向

方法一

使用HttpServletResponse对象的**sendRedirect()**方法

优点:简单

缺点:只能重定向本项目

public class RedirectServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("redirectServlet");		
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

方法二

先设置response响应返回的状态码为302,即重定向

在设置头部Header的Location属性,"./"表示本服务器本项目

public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        String site = "http://www.bilibili.com";	// 重定向到其他网站
        String site2 = "./index.jsp";				// 重定向到本项目的index.jsp,即http://localhost:8080/servlet_test/index.jsp
        resp.setStatus(resp.SC_MOVED_TEMPORARILY);	// 设置状态码302,为重定向状态码,告诉浏览器,要重定向
        resp.setHeader("Location", site);			// 设置header头部的Locaton信息
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
4. 下载文件
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取下载文件路径
        String fileName = "myPic.png";
        String filePath = "G:\IDEAWorkSpace\SpringWorkSpace\springmvc_test\servlet_test\src\main\resources\pic\myPic.png";
        // 2. 使浏览器支持下载功能
        resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        // 3. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(filePath);
        // 4. 创建缓存区
        int len = 0;
        byte[] buffer = new byte[1024];
        // 5. 获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
        // 6. 将FileInputStream流写入buffer缓冲区,使用OutputStream将缓冲区的数据输出到客户端
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }
        // 7. 关闭流
        in.close();
        out.close();z
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
过滤器Filter

过滤器Filter是一个小型的Web组件

作用:拦截浏览器发送的request请求,进行预处理;拦截浏览器接收的response响应,进行后处理。

功能:限制用户访问某些资源、拦截请求并进行提前处理

实现:实现javax.servlet.Filter接口,就是Filter过滤器

举例说明

创建过滤器Filter对象

实现Filter接口

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("LoginFilter init");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("LoginFilter doFilter");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        System.out.println("LoginFilter destroy");
    }
}

注册过滤器Filter


    loginFilter
    com.hexu.filter.LoginFilter


    loginFilter
    /*

Filter分析

Filter接口有三个方法:init()、doFilter()、destory()

init()

在servlet容器(Tomcat)启动时,就执行

doFilter()

在拦截到响应的请求时,执行。eg,/*表示拦截所有请求

有三个参数:ServletRequest对象、ServletResponse对象、FilterChain对象

可以修改ServletRequest对象和ServletResponse对象,提前处理请求和响应

注意:调用FilterChain接口对象的doFilter方法,才能向后续的过滤器传递请求和响应

destory()

在Servlet容器(Tomcat)关闭时,就执行

处理乱码问题

过滤器截取http请求,把请求request的编码设置成utf-8,则Servlet获取的request请求参数就不会乱码

把响应response的ContextType设置成"text/html;charset=utf-8",则Servlet返回的响应response请求参数就不会乱码

request.setCharacterEncoding(“utf-8”);

response.setContentType(“text/html;charset=utf-8”);

public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

    characterEncodingFilter
    com.hexu.filter.CharacterEncodingFilter


    characterEncodingFilter
    /*

登录验证

判断用户名和密码,成功则继续执行,失败则重定向回登录页面login.jsp

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String userName = request.getParameter("username");
        String password = request.getParameter("password");
        if (userName.equals("Dee") && password.equals("qwe123")) {
            chain.doFilter(request, response);
        } else {
            request.setAttribute("error", "用户名或密码错误,请重试");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }

    }

    @Override
    public void destroy() {
        
    }
}
监听器Listener

监听器就是监听某个对象的状态变化的组件

事件源:被监听的对象,有三个域对象(request、session、servletContext)

监听器:监听事件源对象,事件源对象的状态变化都会触发监听器

注册监听器:讲事件源和监听器绑定

响应行为:监听器监听到事件源变化时,所执行的功能代码

分类:

​ 按监听对象划分:

​ ServletRequest域、HttpSession域、ServletContext域

​ 按监听内容划分:

​ 监听对象的创建与销毁、监听对象属性的变化

ServletRequest域HttpSession域ServletContext域域对象的创建与销毁ServletRequestListenerHttpSessionListenerServletContextListener域对象的属性变化ServletRequestAttributeListenerHttpSessionAttributeListenerServletContextAttributeListener 举例说明

创建监听器

实现监听器Listener接口

public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        String name = srae.getName();
        Object value = srae.getValue();
        System.out.println("属性添加:" + name + " = " + value);
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        String name = srae.getName();
        Object value = srae.getValue();
        System.out.println("属性删除:" + name + " = " + value);
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        String name = srae.getName();
        Object value = srae.getValue();
        System.out.println("属性改变,旧属性:" + name + " = " + value);
    }
}

注册监听器

在web.xml中注册监听器


    com.hexu.listener.MyServletRequestAttributeListener

SpringMVC

SpringMVC是一个轻量型的Web框架

M:Model模型,用于数据封装,业务逻辑处理(Bean、Dao、Service)

V:View视图,用于数据展示(前端)

C:Controller控制器,用于分发、指派工作

项目流程 1. 注册DispatcherServlet

在web.xml配置文件中,注册DispatcherServlet




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


2. 创建IOC配置文件

在resources目录下,创建Spring IOC配置文件applicationContext.xml

主要目的:注册处理器映射器(handlerMapping)、处理器适配器(handlerAdapter)、视图解析器(viewResolver)



	
    
    
    
    

    
    
        
        
    

3. 创建Controller

Controller有两种实现方法:

  • 接口定义(Implement Controller)
  • 注解(@Controller)
接口定义

实现Controller接口的xml配置方法

com.hexu.controller包下的FirstController类实现Controller接口,重写handleRequest()方法

在Spring IOC配置文件applicationContext.xml中注册FirstController Bean,id为client浏览器的url访问路径

public class FirstController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // ModelAndView 模型和视图
        ModelAndView modelAndView = new ModelAndView();
        // 封装对象,放在ModelAndView中。
        modelAndView.addObject("msg", "Hello, my first SpringMVC");
        // 封装要跳转的视图,放在ModelAndView中
        modelAndView.setViewName("hello");  // /WEB-INF/jsp.hello.jsp
        return modelAndView;
    }
}

注解

在Spring IOC配置文件中开启注解支持、自动扫描

在Controller类上添加@Controller注解,表明这是一个Controller

在Controller类的方法上添加@RequestMapping注解,并设置path属性,path属性为client浏览器的url访问路径






@Controller
public class MyController {
    @RequestMapping(path = "/hello1")
    public String hello1(Model model) {
        model.addAttribute("msg", "One");
        return "hello";
    }
}
4. 创建jsp

编写controller跳转的jsp网页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

    
        Title
    
    
    	${msg}
    

5. 补充

可能遇到的问题:404 not found,排查步骤:

  1. 查看控制台输出,看一下是不是缺少了什么jar包;
  2. 如果jar包存在,显示无法输出,在IDEA的项目发布中(Artifacts),添加lib依赖;
  3. 重启Tomcat即可解决。
思路分析
  1. url解读:假设url为:http://localhost:8080/SpringMVC/hello

    • http://localhost:8080是服务器域名
    • SpringMVC是部署在服务器上的web站点
    • hello表示控制器
  2. DispatcherServlet调用HandlerMapping(处理器映射),根据url查找Handler(即Controller的bean)。

  3. 查找到Handler为HandlerExcution。eg. 查找id为"/hello"的Handler(即Bean)

  4. HanderExcution将解析后的信息传递给DispatcherServlet

  5. DispatcherServlet获取Handler(即Bean或Controller)后,调用HandlerAdapter(处理器适配器),其按照特定的规则执行Handler

  6. Handler执行具体的Controller

  7. Controller将具体的信息(eg. ModelAndView)返回给HandlerAdapter

  8. HandlerAdapter将Model和View返回给DispatcherServlet

  9. DispatcherServlet调用ViewResolver(视图解析器)解析View数据

  10. ViewResolver将View的解析数据传给DispatcherServlet

  11. DispatcherServlet根据解析结果,调用具体视图

  12. 将视图返回给Client浏览器

注解开发SpringMVC

优点:一个Controller可以配置多个路径访问,无需编写多个Servlet

实现:在xml配置文件中启动注解驱动,并开启扫描



@Controller
@RequestMapping(path = "/myController")
public class MyController {
    @RequestMapping(path = "/add/{a}/{b}")
    public String add(@PathVariable int a, @PathVariable int b, Model model) {
        int result = a + b;
        model.addAttribute("msg", "相加的结果是: " + result);
        return "test";
    }
}
1. @Controller

作用在type level(类级别)上,标注这个类是Controller,被Spring IOC容器接管

2. @RequestMapping

作用在type level(类级别)或method level(方法级别)上,用于设置请求映射

若类添加了该注解,则类的方法要继承这个类的注解的访问路径

属性:

  • path / value:用于设置访问路径
  • method:用于设置请求方法,取值有:GET、POST、PUT、DELETE…

@RequestMapping衍生注解

  • @GetMapping:相当于@RequsetMapping(method=RequestMethod.GET)
  • @PostMapping:相当于@RequsetMapping(method=RequestMethod.POST)
  • @DeleteMapping:相当于@RequsetMapping(method=RequestMethod.DELETE)
3. @PathVariable

作用在方法的形参上。用于把参数绑定到URI模板,实现Restful风格

4. 举例

Spring IOC配置文件




    
    
    
    
    
    

    
    
        
        
    

Controller

@Controller
@RequestMapping(path = "/myController")		// 一级路径,可以无
public class MyController {
	
    // 访问路径:http://localhost:8080/annotation_springmvc/myController/hello1
    @RequestMapping(path = "/hello1")		// 二级路径,必须有,Client浏览器访问路径:
    public String hello1(Model model) {
        model.addAttribute("msg", "One");	// 只有model,没有View了,所以使用Model类,addAttribute()添加数据
        return "hello";						// 返回的视图
    }

    @RequestMapping(path = "/hello2")
    public String hello2(Model model) {
        model.addAttribute("msg", "Two");
        return "hello";
    }

    @RequestMapping(path = "/hello3")
    public String hello3(Model model) {
        model.addAttribute("msg", "Three");
        return "hello";
    }
}
Controller讲解

Controller 负责提供 Client Browser 访问Web应用程序的行为

Controller 负责解析用户的请求,并将其转换为一个模型

在Spring MVC中,一个Controller可以包含多个Method

在Spring MVC中,对于Controller的配置方法有很多种

Controller有两种实现方法:

  • 接口定义(Implement Controller)
  • 注解(@Controller)
接口定义


	
    
    
    
    

    
    
        
        
    
    
    

public class FirstController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // ModelAndView 模型和视图
        ModelAndView modelAndView = new ModelAndView();
        // 封装对象,放在ModelAndView中。
        modelAndView.addObject("msg", "Hello, my first SpringMVC");
        // 封装要跳转的视图,放在ModelAndView中
        modelAndView.setViewName("hello");  // /WEB-INF/jsp.hello.jsp
        return modelAndView;
    }
}
注解



    
    
    
    

    
    
        
        
    

@Controller
public class MyController {
    @RequestMapping(path = "/hello1")		
    public String hello1(Model model) {
        model.addAttribute("msg", "One");	
        return "hello";						
    }

    @RequestMapping(path = "/hello2")
    public String hello2(Model model) {
        model.addAttribute("msg", "Two");
        return "hello";
    }
}
转发和重定向

视图解析器没有重定向功能

没有视图解析器的转发

forward:/全路径名

@RequestMapping(path = "/forward")
public String forward(Model model) {
    model.addAttribute("msg", "执行了转发");
    return "forward:/WEB-INF/jsp/test.jsp";
}

有视图解析器的转发

视图解析器ViewResolve默认就是转发forward

@RequestMapping(path = "/forward")
public String forward(Model model) {
    model.addAttribute("msg", "执行了转发");
    return "test";
}

重定向

重定向不可以指定WEB-INF目录下的网页

@RequestMapping(path = "/redirect")
public String redirect(Model model) {
    return "redirect:/index.jsp";
}
接收请求参数

提交的域名称和参数名一致

直接获取

// 请求url为:http://localhost:8080/annotation_springmvc/getParameter1?a=1
@RequestMapping(path = "/getParameter1")
public String getParameter1(int a, Model model) {
    model.addAttribute("msg", "a = " + a);
    return "test";
}

提交的域名称和参数名不一致

使用**@RequestParam**注解

// 请求url为:http://localhost:8080/annotation_springmvc/getParameter2?value=1
@RequestMapping(path = "/getParameter2")
public String getParameter2(@RequestParam("value") int a, Model model) {
    model.addAttribute("msg", "a = " + a);
    return "test";
}

把参数封装成实体类

@Repositorypublic class User {    
    private String userName;    
    private String password;	
    // Getter&Setter方法
}
// http://localhost:8080/annotation_springmvc/login?userName=root&password=root
@RequestMapping(path = "/login")
public String login1(User user, Model model) {
    model.addAttribute("msg", "用户名:" + user.getUserName() + "n密码:" + user.getPassword());
    return "test";
}

// http://localhost:8080/annotation_springmvc/login/root/root
@RequestMapping(path = "/login/{userName}/{password}")
public String login2(User user, Model model) {
    model.addAttribute("msg", "用户名:" + user.getUserName() + "n密码:" + user.getPassword());
    return "test";
}

使用表单的Post请求

注意:表单中action属性的值,不能加"/"

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    登录界面





<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    $主界面$
  
  
  ${msg}
  

@PostMapping(path = "/formLogin")
public String formLogin(User user, Model model) {
    model.addAttribute("msg", "用户名:" + user.getUserName() + "n密码:" + user.getPassword());
    return "main";
}
过滤器Filter

过滤器Filter是一个小型的Web组件

作用:拦截浏览器发送的request请求,进行预处理;拦截浏览器接收的response响应,进行后处理。

功能:限制用户访问某些资源、拦截请求并进行提前处理

实现:实现javax.servlet.Filter接口,就是Filter过滤器

SpringMvc自定义的过滤器Filter与Servlet的过滤器一样

内置乱码过滤器

SpringMvc内置乱码过滤器CharacterEncodingFilter

其中的doFilterInternal设置了请求request和响应response的编码格式


    encodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
        encoding
        utf-8
    
    
        forceRequestEncoding
        true
    
    
        forceResponseEncoding
        true
    


    encodingFilter
    /*

自定义权限过滤器

使用cookie实现自动登录功能

除了/login或/login.jsp的URI,都进行过滤处理,获取session值,判断是否有用户信息,无则跳转到登录页面

LoginController

登录请求Servlet,若用户名和密码输入正确,则设置session,并重定向到main.jsp页面

若错误,则返回login.jsp页面

// Controller
@Controller
public class LoginController {

    @PostMapping(path = "login")
    public String loginPost (LoginUser loginUser, HttpServletRequest request) {
        String userName = loginUser.getUserName();
        String password = loginUser.getPassword();
        if (userName.equals("何煦") && password.equals("qwe123")) {
            request.getSession().setAttribute("userName", userName);
            return "redirect:/main.jsp";
        } else {
            return "redirect:/login.jsp";
        }
    }
}

LoginFilter

实现Filter接口、或**继承实现了Filter接口的OncePerRequestFilter类**

身份认证过滤器,排除/login或/login.jsp的URI,过滤其他的URI

若session存在登录信息,表明拥有权限

若session没有登录信息,表明无无权限,重定向到login.jsp

public class LoginFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 不过滤的uri
        String[] notFilters = {"/login.jsp", "/login"};
        // 请求的uri
        String uri = request.getRequestURI();
        // 是否过滤
        boolean doFilter = true;
        for (String notFilter: notFilters) {
            if (uri.contains(notFilter)) {
                doFilter = false;
                break;
            }
        }
        // 进行过滤 *** 作
        if (doFilter) {
            // 获取实体信息
            Object sessionObject = request.getSession().getAttribute("userName");
            if (sessionObject == null) {
                response.sendRedirect("./login.jsp");
            } else {
                filterChain.doFilter(request, response);
            }
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

web.xml

web配置文件,注册LoginFilter


    loginFilter
    com.hexu.filter.LoginFilter


    loginFilter
    /*

拦截器Interceptor

拦截用户的请求并做响应的处理,通常应用在权限验证、日志记录

要实现拦截器,需要定义和配置

过滤器和拦截器的区别在于:

​ 过滤器可以过滤所有请求(包括资源的请求),拦截器只拦截servlet请求(controller请求)

​ 过滤器在web.xml中配置,拦截器在spring中配置

​ 过滤器是web的概念,拦截器的spring的概念

  • 定义拦截器:

    • 方法一:实现HandlerInterceptor接口
    • 方法二:实现WebRequestInterceptor接口
  • 配置拦截器:

    • 在SpringMVC配置文件中配置
定义拦截器

实现HandlerInterceptor接口

**perHandle()**方法:在Controller前执行,返回true表示继续向下执行,返回false表示中断后续 *** 作

**postHandle()**方法:在Controller后、解析视图前执行,可以修改moduleAndView、request的属性

**afterCompletion()**方法:视图渲染后执行,可以实现资源清理、记录工作日志信息等。在preHandler()返回true才会执行

执行顺序是:【preHandle】-> 【controller】-> 【postHandle】-> 【afterCompletion】

public class MyHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

实现WebRequestInterceptor接口

public class MyWebRequestInterceptor implements WebRequestInterceptor {
    @Override
    public void preHandle(WebRequest request) throws Exception {
        
    }

    @Override
    public void postHandle(WebRequest request, ModelMap model) throws Exception {

    }

    @Override
    public void afterCompletion(WebRequest request, Exception ex) throws Exception {

    }
}
配置拦截器

表示要注册的拦截器

表示拦截的URI

mvc:exclude-mapping表示不拦截的URI




    
    
        
        

        
        
            
            
            
        
    


监听器Listener

与servlet的实现一样,实现接口

在web.xml配置文件中配置Listener

ServletRequest域HttpSession域ServletContext域域对象的创建与销毁ServletRequestListenerHttpSessionListenerServletContextListener域对象的属性变化ServletRequestAttributeListenerHttpSessionAttributeListenerServletContextAttributeListener SpringBoot

是什么?

快速创建 1. IDEA创建SpringBoot

默认是去官网https://start.spring.io(spring initializr)快速创建SpringBoot Maven项目

其中要填写相关项目信息

导入依赖选择Web -> Spring Web即可

最后设置项目路径和项目名即可

2. 创建Controller

在主程序(SpringbootApplication.java)的同级目录下,新建包controller,在包中新建Controller类

@RestController
public class HelloController {
    
    @RequestMapping(path = "/hello")
    public String hello() {
        return "Hello World";
    }
}
3. 启动主程序

查看Tomcat启动日志,确定Tomcat访问端口号

4. maven依赖说明


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.5.5
         
    
    com.hexu
    springboot
    0.0.1-SNAPSHOT
    springboot
    Demo project for Spring Boot
    
        1.8
    
    
    
        
            
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    



5. 项目打包成jar包

运行package插件,把项目打包成jar包

在target执行文件夹中,会生成对应的jar包

执行命令行:java -jar springboot-0.0.1-SNAPSHOT.jar,即可运行SpringBoot项目

6. 常见问题

打包时出现错误:

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project springboot: Fatal error compiling

解决办法:在配置打包时,跳过项目运行测试用例


    
        
            org.springframework.boot
            spring-boot-maven-plugin
            
                
                true
            
        
    

一些对框架的理解 1. pom.xml文件

父依赖

在标签中,指定了一个父依赖,主要管理项目的资源过滤以及插件

点进去,发现父依赖里面还有一个父依赖

即,pom.xml -> spring-boot-starter-parent-2.5.5.pom -> spring-boot-dependencies-2.5.5.pom

第三个文件spring-boot-dependencies-2.5.5.pom里面的元素内,记录了大量依赖包及其默认的版本号,因此。我门导入依赖时默认不需要写版本号。但是如果导入新的依赖包,则需要手动设置版本号

启动器spring-boot-starter

spring-boot-starter-xxx表示导入xxx模块正常运行所依赖的组件。eg. spring-boot-starter-web表示导入web所需组件

在spring官网有记载所有的启动器https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.build-systems.starters


    org.springframework.boot
    spring-boot-starter-web

2. 主启动类
// SpringbootApplication.java
package com.hexu.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }

}
注解

@SpringBootApplication

@SpringBootConfiguration:被@Configuration注解,表示一个配置类

@EnableAutoConfiguration:启动自动配置

@ComponentScan:启动组件扫描

@EnableAutoConfiguration

@AutoConfigurationPackage:自动配置包

​ @import({Registrar.class}):表示将主启动类所在的包及其子包下的所有bean都扫描进Spring IOC容器中

@import({AutoConfigurationimportSelector.class}):导入组件"自动配置导入选择器"

AutoConfigurationimportSelector.class

通过断言Assert可以知道, 这个类只要用于加载meta-INF/spring.factories文件

通过代码最终,最后classLoader.getResourcers(FACTORIES_RESOURECE_LOCATION);

其中FACTORIES_RESOURECE_LOCATION = “meta-INF/spring.factories”

由此可知,spring.factories时自动装配的核心配置文件

自动配置的核心包都在org.springframework.boot:spring-boot-autoconfigure:2.5.5

总结

SpringBoot在启动时,就加载**meta-INF/spring.factories**文件,获取其中的自动配置参数值

这些配置参数值就是自动配置类,SpringBoot扫描一遍后就会自动装配这些配置类

但是,配置类不一定装配成功,是否成功取决于是否导入响应的starter(启动器:用于添加依赖包)

main方法

**SpringApplication.run()**方法

yaml

“YAML Ain’t a Markup Language”(YAML不是一种标记语言)

“Yet Another Markup Language”(仍是一种标记语言)

基本语法规则
  • 大小写敏感
  • 使用缩进表示层级关系(类似python)
  • 冒号后面如果是赋值,一定要跟空格,不能是tab或其他
  • 注释使用#
  • ~表示空,但不是null
  • 日期格式:date: 1976/07/31
  • 支持EL表达式
数据结构
  • 字面量(键值对)
  • 对象
  • 数组
# key - value
name: Dee

# 对象
student:
	name: Dee
	age: 18
# 对象行内写法
student: {name: Dee, age: 3}
 
# 数组
pets:
    - cat
    - dog
    - pig
# 数组行内写法
pets: [cat, dog, pig]
SpringBoot配置文件

在recources目录下的application.properties就是SpringBoot配置文件

也可以使用yaml格式作为配置文件

修改端口号

# 默认端口号是8080
server.port=8081
server
 port: 8081

设置banner

在resources目录下新建banner.txt文件

   ___                   
  |       ___     ___   
  | |) |  / -_)   / -_)  
  |___/   ___|   ___|  
_|"""""|_|"""""|_|"""""| 
"`-0-0-'"`-0-0-'"`-0-0-' 
SpringBoot识别成功后,banner.txt文件的logo上会有SpringBoot的小标志 属性注入 原始方法
package com.hexu.springboot.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository
public class Dog {
    @Value("rifle")
    private String name;
    @Value("3")
    private int age;

	// Constructor、Getter&Setter、toString...
}
Properties注入

通过**@PropertySource**注解绑定Properties配置文件,再在属性上添加@Value绑定值,使用${xxx}格式,相当麻烦

# database.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/dee
username = root
password = root
// pojo实体类
@Repository
@PropertySource(value = "classpath:database.properties")
public class MybatisConfig {
    @Value("${driver}")
    private String driver;
    @Value("${url}")
    private String url;
    @Value("${username}")
    private String username;
    @Value("${password}")
    private String password;

    // Constructor、Getter&Setter、toString...
}
yaml注入

在配置文件application.yaml中配置对象属性,然后通过**@ConfigurationProperties**注解注入属性值,名字要对应

@ConfigurationProperties注解的prefix值,表示yaml对象的前缀

注意,要注册processor启动器才能使用yaml注入

松散绑定:即yaml文件中last-name和lastName是一样的


    org.springframework.boot
    spring-boot-configuration-processor

// pojo实体类
@Repository
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private int age;
    private boolean happy;
    private Date birthday;
    private List myList;
    private Map myMap;
    private Dog dog;
	
    // Constructor、Getter&Setter、toString...
}
 
// pojo实体类
@Repository
@ConfigurationProperties(prefix = "person.dog")
public class Dog {
    private String name;
    private int age;
    
	// Constructor、Getter&Setter、toString...
}

# application.yaml配置文件
person:
  name: Dee
  age: 18
  happy: true
  birthday: 1995/11/25
  myList:
    - code
    - girl
    - music
  mymap: {k1: v1, k2: v2}
  dog:
    name: rifle
    age: 3
    
# 其他配置...
// 测试类
@SpringBootTest
class SpringbootApplicationTests {
	@Autowired
    private Dog dog;
    @Autowired
    private Person person;

    @Test
    void contextLoads() {
        // 输出结果:Dog{name='rifle', age=3}
        System.out.println(dog);
        // 输出结果:Person{name='Dee', age=18, happy=true, birthday=Sat Nov 25 00:00:00 CST 1995, myList=[code, girl, music], myMap={k1=v1, k2=v2}, dog=Dog{name='rifle', age=3}}
        System.out.println(person);
    }

}
JSR303校验

JSR-303是Java EE 6 中的一项子规范,叫做Bean Validation。官方参考实现是Hibernate Validator

需要导包javax.validation.constraints,在SpringBoot则需要添加Validation启动器,并在类上添加**@Validated**注解

@Validated是org.springframework.validation.annotation.Validated包的

其他如@Null、@NotNull是javax.validation.constraints包的

主要配合yaml使用

Constraint详细信息@Null必须为Null@NotNull必须不为Null@NotBlank必须不为Null,且被Trim后长度大于零@NotEmpty必须不为Null、空字符串@AssertTrue必须为true@AssertFalse必须为false@Min(value)必须是数字,且大于等于value@Max(value)必须是数字,且小于等于value@Digits(integer, fraction)必须是数字,且在指定范围内@Size(min, max)验证对象长度在指定范围,用于(Array、List、Map、String)@Length(min, max)验证String长度@Past必须在当前时间之前@Future必须在当前时间之后@Pattern(value)必须复合正则表达规则value

举例


    org.springframework.boot
    spring-boot-starter-validation

@Repository
@ConfigurationProperties(prefix = "verify")
@Validated
public class VerifyDemo {
    @Null(message = "nullString只能为null")
    private String nullString;
    @NotNull(message = "notNullString 不能为null")
    private String notNullString;
    @NotBlank(message = "notBlankString 不能为null或空")
    private String notBlankString;
    @AssertTrue(message = "assertTrue 必须为true")
    private boolean assertTrue;
    @AssertFalse(message = "assertFalse 必须为false")
    private boolean assertFalse;
    @Length(min = 1, max = 4, message = "名字最少1一个字,最多4个字")
    private String username;
    @Length(min = 6, max = 11, message = "密码最少6为,最多11位")
    private String password;
    @Size(min = 1, max = 3, message = "爱好至少1个,最多3个")
    private List hobbies;
    @Past(message = "past必须是现在之前的时间")
    private Date past;
    @Future(message = "future必须是现在之后的时间")
    private Date future;
	
    // Constructor、Getter & Setter、toString
}

verify:
#  null-string: ~
  not-null-string: notNull
  not-blank-string: notBlank
  assert-true: true
  assert-false: false
  username: 何煦
  password: qwe123
  hobbies:
    - 篮球
    - 编程
    - 钢琴
  past: 2021/9/24
  future: 2021/9/26
多环境切换 配置文件优先级

按文件类型:.properties > .yaml

按位置:

  1. file: ./config/
  2. file: ./
  3. classpath: /config/
  4. classpath: /

springBoot会从这四个位置全部加载配置文件,互补配置

多环境配置

properties配置多环境

SpringBoot默认使用application.properties主配置文件

可通过spring.profiles.active配置多环境

eg.

​ application.properties 代表主配置

​ application-test.properties 代表测试环境

​ application-dev.properties 代表开发环境

默认启动端口是8080,若指定test配置文件,则端口为8081,若指定dev配置文件,则端口为8082

# application.properties文件
server.port=8080
spring.profiles.active=test
# application-test.properties文件
server.port=8081
# application-dev.properties文件
server.port=8082

yaml配置多环境

区别于properties,yaml不需要创建多个文件,在一个文件内即可完成多环境配置

配置环境间,使用**—**分隔;也可以分开不同的文件

spring: profiles: active: xxx用于指定配置环境,xxx表示配置环境名

spring: config: activate: on-profile: test 用于给配置环境赋名,eg. test为配置环境名

server:
  port: 8080
spring:
  profiles:
    active: test
    
---

server:
  port: 8081
spring:
  config:
    activate:
      on-profile: test
      
---

server:
  port: 8082
spring:
  config:
    activate:
      on-profile: dev
spring.factories分析

spring.factories配置文件,记录了自动装配的包

application.yaml配置文件中的配置内容全部由spring.factories中的包决定

Auto Configure下的包,全都以Configuration结尾

我们随便点进去看看

例子1:WebMvcAutoConfituration

@Configuration表示,这是一个的配置类

@Conditional前缀的,表示条件,满足条件,该类的自动装配才会生效

// WebMvcAutoConfiguration文件
// 配置类
@Configuration(proxyBeanMethods = false)
// 条件:基于servlet的web应用程序
@ConditionalOnWebApplication(type = Type.SERVLET)
// 条件:指定的类(Servlet.class、DispatcherServlet.class、WebMvcConfigurer.class)被加载
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
// 条件:指定的bean(即类)没由加载到Spring IOC中时
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
// 该类有装配排序
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
// 该类在指定类装配完毕后再装配
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
    // ...
}

例子2:HttpEncodingAutoConfiguration

@EnableConfigurationProperties表示,允许的配置属性,在ServerProperties.java文件内

ServerProperties类内的servlet属性是一个内置静态类Servlet,Servlet类内的encoding属性是一个Encoding类对象,Encoding类的属性就是配置文件可以配置的内容,一路下来,ServerProperties指定前缀为server,server内有Servlet类,Servlet内有Encoding类,Encoding内的属性

// HttpEncodingAutoConfiguration文件
// 配置类
@Configuration(proxyBeanMethods = false)
// 读取配置文件属性
@EnableConfigurationProperties(ServerProperties.class)
// 条件:基于Servlet的web应用程序
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
// 条件:指定类(CharacterEncodingFilter.class)被加载
@ConditionalOnClass(CharacterEncodingFilter.class)
// 条件:属性前缀必须是server.servlet.encoding
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
    // ...
}

总结

每一个xxxAutoConfiguration,都对应着不同的xxxProperties文件

xxxConfiguration自动配置,可以给xxxProperties文件设置默认值,xxxProperties也可以从application.yaml配置文件中读取配置值

debug属性

在application.yaml配置文件中,配置debug: true即可进行调试,控制台就会打印出,哪些组件装配成功,那些组件装配失败

Positive matches表示生效的组件

Negative matches表示失效的组件

debug: true
============================
ConDITIONS evalUATION REPORT
============================

Positive matches:
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
      
   ...

Negative matches:
-----------------
    XADataSourceAutoConfiguration:
          Did not match:
             - @ConditionalOnClass did not find required class 'javax.transaction.TransactionManager' (OnClassCondition)
             
   ...
Exclusions:
-----------

    None


Unconditional classes:
----------------------

    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

    org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
    
    ...
关于WebMvc的配置 静态资源路径

默认路径

WebMvcAutoConfiguration类

​ 静态内部类WebMvcAutoConfiguration

​ 重写方法addResourceHandlers()

​ 调用addResourceLocations(this.resourceProperties.getStaticLocation());

​ 得到staticLocation的默认值

​ “classpath:/resources/”、“classpath:/static/”、“classpath:/public/”

表明,静态文件可以存放在resources路径下的resoureces文件、static文件、public文件

并且,他们的优先级是:resources > static > public

手动设置路径

application.yaml配置文件设置路径后,默认的静态文件访问路径将会失效

spring:
  web:
    resources:
      static-locations: [classpath:/myStaticHtml]
静态资源映射规则

WebMvcAutoConfiguration类

​ 静态内部类WebMvcAutoConfiguration

​ 重写方法addResourceHandlers()

​ 调用this.mvcProperties.getStaticPathPattern()

​ 得到staticPathPattern的默认值

​ “/**”

表示,client浏览器可以直接访问所有静态文件,eg. http://localhost:8080/index.jsp

设置首页

WebMvcAutoConfiguration类

​ 静态内部类EnableWebMvcConfiguration

​ 重写方法getWelcomePage()

该方法遍历了所有staticLocations静态文件路径,从中寻找index.html文件,作为首页。

优先级依然是resources > static > public

扩展MVC

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

若想扩展MVC,需要创建一个类(实现WebMvcConfigurer接口),并**添加@Configuration注解**,不添加@EnableWebMvc注解

@Configuration
public class MyWebMvcConfiguration implements WebMvcConfigurer {

    // 拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

    }

    // 静态资源处理
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

    }

    // 视图跳转控制器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

    }

    // 默认静态资源处理器
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

    }

    // 视图解析器
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {

    }
}

为什么不能添加@EnableWebMvc

源码分析可知,@EnableWebMvc注解加载了一个DelegatingWebMvcConfiguration类,这个类继承了WebMvcConfigurationSupport

在WebMvcAutoConfituration自动装配类中,@ConditionalOnMissingBean表明,WebMvcConfigurationSupport类未注册成Bean时才生效

继续阅读源码可知,WebMvcConfigurationSupport是在WebMvcAutoConfiguration中注册成Bean的

DelegatingWebMvcConfiguration的setConfigurers()方法,用于夹在所有WebMvc配置

源码解析

ContentNegotiatingViewResolver uses all the other view resolvers to locate a view so it should have a high precedence

The ContentNegotiatingViewResolver does not resolve views itself, but delegates to other ViewResolver

By default, these other view resolvers are picked up automatically from the application context

though they can also be set explicitly by using the {@link #setViewResolvers viewResolvers} property.

表明ContentNegotiatingViewResolver是最高级的视图解析器

但它不解析视图,而是指派其他ViewResolver去解析

默认情况下,其他ViewResolver会自动上下文提取

自定义视图解析器

实现ViewResolver接口,即可称为视图解析器

在@Configuration配置文件中,注册视图解析器Bean

debug时,在ContentNegotiatingViewResolver视图解析器中,会遍历所有的ViewResolver,其中就有我们自定义的ViewResolver

@Configuration
public class MyWebMvcConfiguration implements WebMvcConfigurer {
    
    @Bean
    public MyViewResolver getMyViewResolver() {
        return new MyViewResolver();
    }

    // 自定义视图解析器
    static class MyViewResolver implements ViewResolver {
        @Override
        public View resolveViewName(String viewName, Locale locale) throws Exception {
            return null;
        }
    }
}
配置格式转换

FormattingConversionService是格式转换相关bean

一步一步推到可知,格式转换是WebMvcProperties默认设置的,也可以在application.yaml配置文件中配置

spring:
  mvc:
    format:
      date: yyyy-MM-dd
      time: HH:mm:ss
      date-time: yyyy-MM-dd HH:mm:ss
视图跳转

重写addViewControllers()方法

以前的SpringMVC,访问页面是,必须写Controller类,然后写一个方法跳转页面

现在的SpringBoot,重写addViewControllers()方法即可达到效果

  • 创建Controller类
@Controller
public class LoginController {

    @RequestMapping(path = {"/", "/login"})
    public String login() {
        return "login";
    }
}
  • 重写addViewControllers()方法
@Configuration
public class MyWebMvcConfiguration implements WebMvcConfigurer {
    // 视图跳转控制器
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("login");
        registry.addViewController("/login").setViewName("login");
    }
}
自定义拦截器

请跳转到SpringBoot.拦截器Interceptor章节

国际化配置

相关配置类:MessageSourceAutoConfiguration

1. 配置文件路径
# 表明MessageSource消息资源路径在classpath:i18n下的login文件
spring:
  messages:
    basename: i18n.login

源码分析

2. 在网页中引入配置

ThyMeleaf引入Message的语法是:#{...}

Please sign in

乱码问题

properties文件编码格式不对,需要在setting中配置

3. 自定义区域设置解析器

自定义LocaleResolver类

在配置文件中注册LocaleResolver Bean

public class MyLocaleResolver implements LocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String lang = request.getParameter("lang");
        Locale locale = Locale.getDefault();
        if (lang != null && !lang.equals("")) {
            String language = lang.split("_")[0];
            String country = lang.split("_")[1];
            locale = new Locale(language, country);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}
@Configuration
public class MyWebMvcConfiguration implements WebMvcConfigurer {
    
    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocaleResolver();
    }

}
Thymeleaf模板

Thymeleaf is a modern server-side Java template engine for both web and standalone environments.

Thymeleaf是用来开发Web和独立环境项目的服务器端的Java模版引擎

导入依赖

在SpringBoot中,即启动Thymeleaf启动器


    org.springframework.boot
    spring-boot-starter-thymeleaf



    org.thymeleaf
    thymeleaf-spring5


    org.thymeleaf.extras
    thymeleaf-extras-java8time

源码分析

从spring.factories配置文件中找到Thymeleaf自动配置包

org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration

ThymeleafAutoConfiguration指定了配置类ThymeleafProperties

ThymeleafProperties中的**prefix默认为"classpath:/templates/",suffix默认为".html"**

可知,视图解析器的转发路径是resources路径下的templates文件夹,并且是html格式的文件

举例分析

使用thymeleaf时,需要在html文件中导入命名空间的约束

xmlns:th="http://www.thymeleaf.org"

@Controller
public class IndexController {

    @RequestMapping(path = "/index")
    public String getIndex(Model model) {
        model.addAttribute("msg", "Hello, this is the first time I use thymeleaf");
        return "index";
    }
}


    
    Welcome to My SpringBoot


    测试页面					
										


					

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4969107.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-13
下一篇 2022-11-13

发表评论

登录后才能评论

评论列表(0条)