Starter--开箱即用
Spring Boot为了简化配置,提供了非常多的starter,实现了开箱即用。
它先打包好与常用模块相关的所有JAR包,并完成自动配置,然后组装成Starter。这使得在开发业务代码时不需要过多关注框架配置,只需要关注业务逻辑即可。
通过在pom.xml添加依赖之后,使用@Autowired引入,即可使用。
URI与URL
URI(Universal Resource Identifier):统一资源标识符
URL():统一资源定位符
控制器
在Spring MVC中,控制器负责处理由DispatcherServlet接收并分发过来的请求。它把用户请求的数据通过业务处理层封装成一个Model,然后把Model返回给对应的View进行展示。
处理HTTP请求的方法
GET:获取资源
DELETE:删除资源,要判断是否成功
POST:提交资源
PUT:更新资源
PATCH:局部更新资源,比如更新一条数据的一个字段。
在方法中使用参数
//获取路径中的值,(http://localhost/article/123)
@GetMapping("article/{id}")
public ModelAndView getArticle(@PathVariable("id") Integer id){
//..........
}
//获取路径中的参数(http://localhost/user/?username=www)
@RequestMapping("/addUser")
public String addUser(String username){
//..........
}
//通过Bean接收HTTP提交的对象
public String addUser(UserModel user)
//用注解@ModelAttribute获取参数
@RequestMapping(value="addUser", method=RequestMethod.POST)
public String addUser(@ModelAttribute("user") UserModel user)
//通过HttpServletRequest接收参数
@RequestMapping("/addUser")
public String addUser(HttpServletRequest request){
request.GETParameter("username");
}
//用@RequestParam绑定入参
@RequestParam(value="username", required=false)
//用@RequestBody接收JSON数据
@RequestMapping(value="addUser",method={RequestMethod.POST})
@ResponseBody
public void saveUser(@RequestBody List<User> users){
}
//上传文件MultipartFile
public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes){
}
//上传图片
@PostMapping("/upload")
@ResponseBody
public Map<String,Object> singleFileUpload(@RequestParam("upload") MultipartFile file,RedirectAttributes redirectAttributes){
}
响应式编程Webflux
与Spring MVC不同,WebFlux不需要Servlet API,完全异步无阻塞,并且通过Reactor项目实现Reactive Streams规范。
可以在有限资源的情况下提高系统吞吐量和伸缩性(不是提高性能)。这意味着在资源相同的情况下,WebFlux可以处理更多的请求(不是业务)。
WebFlux除支持RESTful Web服务之外,还可以用于提供动态HTML内容。
WebFlux可以立即响应,返回数据与函数的组合(Mono或者Flux,不是结果),然后将收到的请求转发给Work线程去处理。WebFlux只会对Work线程形成阻塞,如果再来请求也可以处理。
Mono和Flux
是Reactor中的两个概念,都属于事件发布者,当有事件发生时,Mono或Flux会回调消费者的相应方法,然后通知消费者相应的事件。
用于处理异步数据流,将异步数据流包装成Mono或者Flux对象。
Mono返回单个数据,Flux返回多个数据。
注解式开发WebFlux
package com.testboot.testx.controller;
import com.testboot.testx.webflux.entity.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/user")
public class UserController {
Map<Long, User> users = new HashMap<>();
@PostConstruct
public void init() throws Exception{
users.put(Long.valueOf(1), new User(1,"lzh",28));
users.put(Long.valueOf(2), new User(2,"lzr",2));
}
@GetMapping("/list")
public Flux<User> getAll(){
return Flux.fromIterable(users.entrySet().stream()
.map(entry -> entry.getValue())
.collect(Collectors.toList()));
}
@GetMapping("/{id}")
public Mono<User> getUser(@PathVariable Long id){
return Mono.justOrEmpty(users.get(id));
}
@PostMapping("")
public Mono<ResponseEntity<String>> addUser(User user){
users.put(user.getId(), user);
return Mono.just(new ResponseEntity<>("tjcg", HttpStatus.CREATED));
}
@PutMapping("/{id}")
public Mono<ResponseEntity<User>> putUser(@PathVariable Long id, User user){
user.setId(id);
users.put(id, user);
return Mono.just(new ResponseEntity<>(user, HttpStatus.CREATED));
}
}
响应式开发WebFlux
(书中的代码失效,估计是版本的事)
Spring AOP
AOP,面向切面编程,把业务功能分为核心,非核心两部分。
核心业务功能:用户登录,增加数据,删除数据。
非核心业务功能:性能统计,日志,事务管理。
AOP将非核心业务功能定义为切面。核心业务功能和切面功能先被分别进行独立开发,然后再把切面功能和核心业务功能编织在一起。
AOP将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,以减少系统的重复代码,降低模块间的耦合度,利于未来的扩展和维护。
切入点:在哪些类,哪些方法上切入。
通知:在方法前,方法后,方法前后做什么。
切面:切面=切入点+通知。即在什么时机,什么地方,做什么。
织入:把切面加入对象,并创建出代理对象的过程。
环绕通知:AOP中最强大,灵活的通知,它集成了前置和后置通知,保留了连接点原有的方法。
package com.testboot.testx.log;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
public class AopLog {
private Logger logger = LoggerFactory.getLogger(this.getClass());
ThreadLocal<Long> startTime = new ThreadLocal<>();
@Pointcut("execution(public * com.testboot..*.*(..))")
public void aopWebLog(){
}
@Before("aopWebLog()")
public void doBefore(JoinPoint joinPoint){
startTime.set(System.currentTimeMillis());
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
System.out.println("URL:" + request.getRequestURL().toString());
logger.info("URL:" + request.getRequestURL().toString());
logger.info("Http方法:" + request.getMethod());
logger.info("IP地址:" + request.getRemoteAddr());
logger.info("类的方法:" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
logger.info("参数:" + request.getQueryString());
}
@AfterReturning(pointcut = "aopWebLog()", returning = "retObject")
public void doAfterReturning(Object retObject) throws Throwable{
System.out.println("应答值:" + retObject);
logger.info("应答值:" + retObject);
logger.info("费时:" + (System.currentTimeMillis() - startTime.get()));
}
@AfterThrowing(pointcut = "aopWebLog()", throwing = "ex")
public void addAfterThrowingLogger(JoinPoint joinPoint,Exception ex) throws Throwable{
System.out.println("执行" + "异常"+ex);
logger.error("执行" + "异常",ex);
}
}
Aspect注解声明其为切面类
Component注解将切面类加入IoC容器
Pointcut定义切点
IoC容器和Servlet容器
IoC容器,控制反转。它将程序中创建对象的控制权交给Spring框架来管理,以便降低耦合度。
IoC实现方式之一:依赖注入。由IoC在运行期间动态地将某种依赖关系注入对象之中。
IoC容器在主对象中设置Setter方法,通过调用Setter方法或构造方法传入所需引用(即依赖注入)。要使用某个对象,只需要从IoC中获取需要使用的对象,不需要关心对象创建过程,即把程序中创建对象的控制权交给Spring框架来管理。
IoC的实现方法:依赖注入,依赖查找。
依赖注入:IoC容器通过类型或名称等信息将不同对象注入不同属性中。组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。
依赖查找:使用API来管理依赖创建,查找资源和组装对象。
Servlet容器
可以实现拦截与监听。
用IoC管理Bean
package com.testboot.testx.bean;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private int id;
private String name;
}
package com.testboot.testx.config;
import com.testboot.testx.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean("user1")
public User user(){
User user = new User();
user.setId(1);
user.setName("dsd");
return user;
}
}
package com.testboot.testx.test;
import com.testboot.testx.bean.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class IoCTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testIoC(){
User user = (User) applicationContext.getBean("user1");
System.out.println(user);
}
}
Servlet
package com.testboot.testx.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//ServletDemo02下的所有子路径
@WebServlet("/ServletDemo02/*")
public class ServletDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
resp.getWriter().print("Servlet ServletDemo02");
}
}
package com.testboot.testx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class TestxApplication {
public static void main(String[] args) {
SpringApplication.run(TestxApplication.class, args);
}
}
过滤器和监听器
过滤器:在数据传输时剔除我们不想要的数据,使用fliter来处理,额外的优点是省去了重复代码。
1 新建类继承Filter抽象类(javax.servlet.annotation.WebFilter;)(这里的WebFilter注解中的urlPattern,代表经过哪些路径时会进行过滤)
2 重写 init,doFilter,destroy
3 添加注解@ServletComponentScan
监听器:用于监听Web应用程序中某些对象或信息的创建,销毁,增加等,然后做出相应的处理。
ServletContextListener – 监听servletContext对象的创建以及销毁
HttpSessionListener – 监听session对象的创建以及销毁
ServletRequestListener – 监听servletRequest对象的创建以及销毁
ServletContextAttributeListener – 监听servletContext对象中属性的改变
HttpSessionAttributeListener --监听session对象中属性的改变
ServletRequestAttributeListener --监听request对象中属性的改变
HttpSessionBindingListener --监听HttpSession,并绑定以及解除锁定
HttpSessionActivationListener --监听钝化和活动的HttpSession状态改变
也需要@ServletComponentScan
package com.testboot.testx.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class listenerDemo02 implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext chushihua");
System.out.println(sce.getServletContext().getServerInfo());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext xiaohui");
}
}
自动配置原理
注解EnableAutoConfiguration借助注解@Import,将所有符合自动配置条件的Bean都加载到IoC容器中,
@EnableAutoConfiguration借助导入AutoConfigurationImportSelector.class,调用SpringFactoriesLoader的loadFactoryNames方法,从classpath中寻找所有的META-INF/spring.factories配置文件,再借助AutoConfigurationImportSelector,将所有符合条件的@Configuration配置都加载到IoC中。
SpringFactoriesLoader类从classpath中寻找所有的META-INF/spring.factories配置文件。
元注解
@Target(告诉Java将自定义注解放在什么地方,修饰什么内容)
@Retention(自定义注解生命周期)
@Inherited(表明被标记的类型可以被继承)
@Documented(是否将注解信息添加在Java文档)
@interface(声明一个注解)
package com.testboot.testx.aop;
import com.testboot.testx.annotation.MyTestAnnotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class TestAnnotationAspect {
@Pointcut("@annotation(com.testboot.testx.annotation.MyTestAnnotation)")
public void myAnnotationPointCut(){
}
@Before("myAnnotationPointCut()")
public void before(JoinPoint joinPoint) throws Throwable{
MethodSignature sign = (MethodSignature) joinPoint.getSignature();
Method method = sign.getMethod();
MyTestAnnotation annotation = method.getAnnotation(MyTestAnnotation.class);
System.out.println("TestAnno canshu: " + annotation.value());
}
}
package com.testboot.testx.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyTestAnnotation {
String value();
}
异常
spring使用控制器通知,使用切面技术来实现
(@ControllerAdvice(可以声明限定方式,比如注解,包名,类型)和@RestcontrollerAdvice)
package com.testboot.testx.exception;
public class BusinessException extends RuntimeException {
private Integer code;
public BusinessException(int code, String msg){
super(msg);
this.code = code;
}
public Integer getCode(){
return code;
}
public void setCode(Integer code){
this.code = code;
}
}
package com.testboot.testx.controller;
import com.testboot.testx.exception.BusinessException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping("/BussinessException")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
if(i == 0){
throw new BusinessException(600, "elns");
}
return "succ";
}
}
ORM
将数据库中的表和内存中的对象建立起映射关系,主要包括JPA和Mybatis,
JPA是一个规范化接口,封装了Hibernate的操作作为默认实现。
RESTFUL API
Spring Security
提供了声明式的安全访问控制解决方案。基于spring aop 和 servlet。
Spring Security 有三个核心概念。
Principle:用户的对象,可以用于验证的设备。
Authority:用户的角色,比如管理员或者会员。
Permission:权限。
验证步骤:
用户名密码登录。
过滤器获取用户名,密码,然后封装成Authentication
AuthenticationManager认证token
AuthenticationManager认证成功,返回一个封装了用户权限信息的Authentication对象等。
Authentication对象赋值给当前的SecurityContext,建立用户的安全上下文。
用户在进行一些涉及到安全的操作的时候,访问控制器会根据安全上下文来进行判断。
Spring Cache
Redis:分布式Session,高并发读写,计数器,排行榜。
RabbitMQ
消息延迟:订单,支付过期定时取消。
交换机:交换机将消息路由到一个或多个Queue中,或丢弃。
交换机(Exchange)有四种类型:direct,topic,fanout,headers
绑定:binding key,routing key
6种工作模式:简单模式,工作队列模式,交换机模式,Routing转发模式,主题转发模式,RPC模式