==配置拦截器==

  • 编写一个拦截器实现HandlerInterceptor接口
  • 拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
  • 指定拦截规则(如果是拦截所有是(”/**”),静态资源也会被拦截
1
2
3
4
5
6
7
8
9
10
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有请求都被拦截包括静态资源
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求
}
}

实现HandlerInterceptor接口举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 登录检查
* 1、配置好拦截器要拦截哪些请求
* 2、把这些配置放在容器中
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

/**
* 目标方法执行之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String requestURI = request.getRequestURI();
log.info("preHandle拦截的请求路径是{}",requestURI);

//登录检查逻辑
HttpSession session = request.getSession();

Object loginUser = session.getAttribute("loginUser");

if(loginUser != null){
//放行
return true;
}

//拦截住。未登录。跳转到登录页
request.setAttribute("msg","请先登录");
// re.sendRedirect("/");
request.getRequestDispatcher("/").forward(request,response);
return false;
}

/**
* 目标方法执行完成以后
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle执行{}",modelAndView);
}

/**
* 页面渲染以后
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion执行异常{}",ex);
}
}

==@RequestPart==

和文件上传有关,和@RequestParam类似

==proxyBeanMethods==

@Configuration(proxyBeanMethods = true) :保证依赖的组件始终是单实例的

配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式

@Configuration(proxyBeanMethods = false):多例模式

配置 类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断

==/*和/**的区别==

都是表示当前目录下的所有文件,/*是用在servlet中的, /**是用在spring等框架中的

==slf4j==

SLF4J支持{}作为占位符,等价于C语言中的%s,而不必再进行字符串的拼接,效率有显著的提高。

==@RestController==

RestController的作用相当于Controller加ResponseBody共同作用的结果,但采用RestController请求方式一般会采用Restful风格的形式。

Controller的作用:声明该类是Controller层的Bean,将该类声明进入Spring容器中进行管理

ResponseBody的作用:表明该类的所有方法的返回值都直接进行提交而不经过视图解析器,且返回值的数据自动封装为json的数据格式

RestController的作用:包含上面两个的作用,且支持Restful风格的数据提交方式

Restful风格:

get:获取数据时用的请求方式

post:增加数据时的请求方式

put:更新数据时的请求方式

delete:删除数据时的请求方式

==@Component==

@component是spring中的一个注解,它的作用就是实现bean的注入。在Java的web开发中,提供3个@Component注解衍生注解(功能与@component一样)分别是:

1、@Controller 控制器(注入服务) 用于标注控制层,相当于struts中的action层。

2、@Service 服务(注入dao) 用于标注服务层,主要用来进行业务的逻辑处理

3、@Repository(实现dao访问) 用于标注数据访问层,也可以说用于标注数据访问组件,即DAO组件

而@Component泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。

==@Mapper与MapperScan的使用==

  • @Mapper与@MapperScan不可同时使用
  • @Mapper用于注解单个Mapper接口(是在Mapper接口中添加)
  • @MapperScan用于批量注解Mapper接口(是在启动类中添加)

==Springboot2笔记==

尚硅谷

==Mybatis与Springboot混合模式使用==

  • 引入mybatis-starter
  • 配置application.yaml中,指定mapper-location位置即可
  • 编写Mapper接口并标注@Mapper注解
  • 简单方法直接注解方式
  • 复杂方法编写mapper.xml进行绑定映射
  • @MapperScan(“com.atguigu.admin.mapper”) 简化,其他的接口就可以不用标注@Mapper注解

==@TableField和@TableName==

整合mybatis-plus时,实体类中没有的字段需注明@TableFiels(exist = false),否则报错;实体类中的类名和数据库中的表明不是一样时,需要注明@TableName(“”)注解,””中写的是数据库中的表名。

==thymleaf语法==

表达式名字 语法 用途
变量取值 ${…} 获取请求域、session域、对象等值
选择变量 *{…} 获取上下文对象值
消息 #{…} 获取国际化等值
连接 @{…} 生成连接
片段表达式 ~{…} jsp:include作用,引入公共页面片段

行内写法:[[表达式]],在标签外使用表达式,需要这样写才能生效,否则就成了字符串

==转发和重定向==

做增、删、改的时候最好用重定向,因为如果不用重定向,每次刷新页面就相当于再请求一次,就可能会做额外的操作,导致数据不对。

java重定向问答题

转发是向服务器请求了一次,在这个过程中request都有效,而重定向就不一样了,重定向其实是向服务器请求了两次,第一次向服务器请求,服务器给客户端一个响应码,客户端带着这个响应码再向服务器请求一次,request在第一次请求时有效,在第二次请求时request已被销毁,所以无效。

转发和重定向的区别
  • 重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。

  • 转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。

==RedirectAttributes==

​ 因为使用重定向的跳转方式的情况下,跳转到的地址无法获取 request 中的值。RedirecAtrributes 很好的解决了这个问题。

redirectAttributes.addAttributie(“param”, value);

这种方法相当于在重定向链接地址追加传递的参数。以上重定向的方法等同于 return "redirect:/hello?param=value" ,注意这种方法直接将传递的参数暴露在链接地址上,非常的不安全,慎用。

redirectAttributes.add*Flash*Attributie(“param”, value);

这种方法是隐藏了参数,链接地址上不直接暴露,但是能且只能在重定向的 “页面” 获取 param 参数值。其原理就是将设置的属性放到 session 中,session 中的属性在跳到页面后马上销毁

注意:这种方式在页面中可以正常获取,但是跳转目标是控制器方法的情 况下,需要使用 @ModelAttribute 注解绑定参数后才能获取。

==Jedis和Lettuce的区别==

  • jedis客户端连接方式是基于tcp的阻塞式连接方式。
  • lettuce客户端连接方式是基于netty的多路复用异步非阻塞的连接方案。

jedis和Lettuce都是Redis的客户端,它们都可以连接Redis服务器,但是在SpringBoot2.0之后默认都是使用的Lettuce这个客户端连接Redis服务器。

redis客户端比较:

[参考博客](http s://www.jianshu.com/p/ee30c184c854)

==Filter和Interceptor的区别==

Filter是Servlet定义的原生组件。好处,脱离Spring应用也能使用

Interceptor是Spring定义的接口。可以使用Spring的自动装配等功能

Junit5常用注解

  • **@Test :**表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
  • **@ParameterizedTest :**表示方法是参数化测试,下方会有详细介绍
  • **@RepeatedTest :**表示方法可重复执行,下方会有详细介绍
  • **@DisplayName :**为测试类或者测试方法设置展示名称
  • **@BeforeEach :**表示在每个单元测试之前执行
  • **@AfterEach :**表示在每个单元测试之后执行
  • **@BeforeAll :**表示在所有单元测试之前执行
  • **@AfterAll :**表示在所有单元测试之后执行
  • **@Tag :**表示单元测试类别,类似于JUnit4中的@Categories
  • **@Disabled :**表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
  • **@Timeout :**表示测试方法运行如果超过了指定时间将会返回错误
  • **@ExtendWith :**为测试类或测试方法提供扩展类引用

如果要使用spring容器,就要加上@SpringbootTest注解

==Lambda表达式==

形如:(o1, o2) -> Integer.compare(o1, o2)

左边 -> 右边

  • ->被称为lambda操作符或箭头操作符
  • 左边:lambda形参列表(其实就是接口中的抽象方法的形参列表)
  • lambda体(其实就是重写的抽象方法的方法体)
1
2
3
4
5
6
7
8
9
10
11
12
public void test06(){
Consumer<String> consumer = s->{System.out.println(s);};//类型推断
consumer.accept("留下少年漂流的痕迹");
}
//此时一个参数,自动推断参数类型,并且可以省略形参括号

public void test04(){
Comparator<Integer> comparator = (o1,o2)-> Integer.compare(o1,o2);
int compare = comparator.compare(32,23);
System.out.println(compare);
}
//当lambda体只有一条语句时,return与大括号都可以省略

==配置文件的加载优先级==

配置文件的加载优先级 properties(最高)>yml>yaml(最低)

不同配置文件中相同的配置,按优先级高的指定,不同配置文件

如果有不同的配置,则全部保留

==@SpringBootApplication==

@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(“com.atguigu.boot”)

==@Configuration注解==

这相当于以前的一个xml文件,然后在方法上加上@Bean注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
//@ConditionalOnBean(name = "tom")
@ConditionalOnMissingBean(name = "tom")
public class MyConfig {


/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/

@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}

@Bean("tom22")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}

==@Import==

给容器中引入组件

1
2
3
4
5
6
7
8
 * 4@Import({User.class, DBHelper.class})
* 给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
*/

@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}

==@ImportResource==

引入xml中的资源

1
2
3
4
5
6
7
8
@ImportResource("classpath:beans.xml")
public class MyConfig {}

======================测试=================
boolean haha = run.containsBean("haha");
boolean hehe = run.containsBean("hehe");
System.out.println("haha:"+haha);//true
System.out.println("hehe:"+hehe);//true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
======================beans.xml=========================
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<bean id="haha" class="com.atguigu.boot.bean.User">
<property name="name" value="zhangsan"></property>
<property name="age" value="18"></property>
</bean>

<bean id="hehe" class="com.atguigu.boot.bean.Pet">
<property name="name" value="tomcat"></property>
</bean>
</beans>