diff --git a/Java基础教程/Java工具教程/2 idea教程.md b/Java基础教程/Java工具教程/2 idea教程.md index efe21b4f..355aeb8f 100644 --- a/Java基础教程/Java工具教程/2 idea教程.md +++ b/Java基础教程/Java工具教程/2 idea教程.md @@ -515,7 +515,7 @@ F3选中文件/文件夹/代码行,添加/取消书签 * 缩进 tap * 推缩进 shift tap -### 浏览操作 +### Navigate浏览操作 > 用于阅读代码,实现快速的跳转和导航。 > edit中的find是基于文本内容的搜索。 > navigate中的浏览功能是基于java语义的分析。例如可以检索class、method这种需要语义翻译的东西。 diff --git a/Java基础教程/Java语言基础/12 Java注解.md b/Java基础教程/Java语言基础/12 Java注解.md index 02375fd6..56820b18 100644 --- a/Java基础教程/Java语言基础/12 Java注解.md +++ b/Java基础教程/Java语言基础/12 Java注解.md @@ -13,10 +13,11 @@ public @interface 注解名称{ ``` ### 分类 -根据其定义者的角色可以分为以下三种: -1. 标准注解:JDK内置的注解 -2. 自定义注解:用户自定义的注解 -3. 第三方框架提供的注解 +根据其定义者的角色可以分为以下四种种: +1. 元注解:修饰注解的注解 +2. 标准注解:JDK内置的注解 +3. 框架注解:第三方框架提供的注解 +4. 自定义注解:用户自定义的注解 > 还可以根据其出现的位置分为类、方法、变量和形参的注解。也可以其作用范围分为标准注解、元注解、自定义注解。 @@ -299,14 +300,104 @@ public class Demo { 一种信息性注解类型,用于指示接口类型声明旨在成为 Java 语言规范定义的功能接口。从概念上讲,函数式接口只有一个抽象方法。由于默认方法有一个实现,它们不是抽象的。如果接口声明了一个覆盖java.lang.Object的公共方法之一的抽象方法,这也不会计入接口的抽象方法计数,因为接口的任何实现都将具有来自java.lang.Object或其他地方的实现(接口的实现是类,所有类的父类都是Object)。 请注意,函数式接口的实例可以使用 lambda 表达式、方法引用或构造函数引用来创建。 如果使用此注解类型对类型进行注解,则编译器需要生成错误消息,除非: -该类型是接口类型,而不是注解类型、枚举或类。 -带注解的类型满足功能接口的要求。 +* 该类型是接口类型,而不是注解类型、枚举或类。 +* 带注解的类型满足功能接口的要求。 + 但是,无论接口声明中是否存在FunctionalInterface注释,编译器都会将满足功能接口定义的任何接口视为功能接口。 - - ​ 在学习Lambda表达式时,我们了解过函数式接口(接口中只有个一个抽象方法可以存在多个默认方法或多个static方法)。 @FunctionalInterface作用就是用来指定某一个接口必须是函数式接口的,所以@FunctionalInterface只能修饰接口。 +## 4 Spring框架下一个注解的实现 +> 定义注解、使用注解、实现注解。和定义接口、使用接口、实现接口。与OpenApi中定义服务、使用服务、实现服务。具有相同的含义。 + + +### 登录校验——定义注解 +模拟是否需要进行登录校验;如果方法中加上了@LoginRequired注解表示方法需要登录校验,如果没加则不需要。定义一个 +```java +@LoginRequired注解 +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public@interface LoginRequired { + +} +``` +### 登录校验——使用注解 + +定义两个简单接口,其中一个添加@LoginRequired注解表示需要登录校验 +```java +@RestController +public class UserController { + @GetMapping("/login1") + public TransDTO login1(){ + return new TransDTO<>().withMessage("访问login1成功").withCode(HttpStatus.OK.value()); + } + + @LoginRequired + @GetMapping("/login2") + public TransDTO login2(){ + return new TransDTO<>().withMessage("访问login2成功").withCode(HttpStatus.OK.value()); + } +} +``` + +### 登录校验——实现注解 + +自定义拦截器。通过拦截器和反射,实现注解的处理逻辑。 +```java +@Configuration +public class MyInterceptor implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("访问了过滤器!"); + HandlerMethod handlerMethod = (HandlerMethod) handler; + LoginRequired annotation = handlerMethod.getMethod().getAnnotation(LoginRequired.class); + if(annotation != null){ + //全局异常处理会进行处理 + throw new BusinessException("访问失败,您没有权限访问!"); + } + return true; + } + + @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 { + + } +} +``` + +配置拦截路径 +```java +@Configuration +public class InterceptorTrainConfigurer implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); + } +} +``` + +全局异常处理 +```java +@RestControllerAdvice +public class MyExceptionAdvice { + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.OK) + public TransDTO handleException(HttpServletRequest request,Exception e){ + e.printStackTrace(); + return new TransDTO().withCode(500).withSuccess(false).withMessage(e.getMessage()); + } +} +``` + +自定义注解的场景有很多,比如登录、权限拦截、日志、以及各种框架。java注解对于性能有较大的影响,但可用于软件的架构设计,实现动态加载,对于分解复杂业务有帮助。 + +### Spring框架下的另一个实现 + diff --git a/Java基础教程/Java语言基础/18 Rest接口.md b/Java基础教程/Java语言基础/18 Rest接口.md new file mode 100644 index 00000000..d2b386fe --- /dev/null +++ b/Java基础教程/Java语言基础/18 Rest接口.md @@ -0,0 +1,236 @@ +## 1 概述 + +### 基本概念 + +java.ws.rs是jax-rs规范中定义的包名。jax-rs全称Java API for RESTful Services。jax-rs规范目前版本是2.0规范文档 + +jax-rs中定义了 +* 一组启动方式 (以jee作为http容器 还是配合servlet作为http容器) +* 一组注解@GET, @POST, @DELETE, @PUT, @Consumes … 通过 POJO Resource类 提供Rest服务 + +### 实现框架 + +* Apache CXF开源的Web服务框架 +* Jersey 由Sun提供的JAX-RS的参考实现 +* RESTEasy JBoss的实现 +* Restlet 由Jerome Louvel和Dave Pawson开发 是最早的REST框架 先于JAX-RS出现 +* Apache Wink 一个Apache软件基金会孵化器中的项目 其服务模块实现JAX-RS规范 + +## 2 注解 +### @Path +注解位置 类注解 方法注解 + +标注class时 表明该类是个资源类 凡是资源类必须使用该注解 + +标注method时 表示具体的请求资源的路径 + +### @GET @POST @PUT @DELETE + +注解位置 方法注解 + +指明接收HTTP请求的方式属于get,post,put,delete中的哪一种 具体指定请求方式 是由客户端发起请求时指定 + +### @Consumes +注解位置 方法注解 + +指定HTTP请求的MIME类型 默认是*/* 表示任意的MIME类型 该注解支持多个值设定 可以使用MediaType来指定MIME类型 +``` +MediaType的类型大致有 + +application/xml +application/atom+xml +application/json +application/svg+xml +application/x-www-form-urlencoded +application/octet-stream +multipart/form-data +text/plain +text/xml +text/html +``` +```java +@Path("{username"}) +@Consumes({MediaType.APPLICATION_JSON}) +public User getUser(@PathParam("username") String userName) { + ... +} +``` + +### @Produces + +注解位置 方法注解 + +指定HTTP响应的MIME类型 默认是*/* 表示任意的MIME类型 同Consumes使用MediaType来指定MIME类型 +``` +@Path("{username"}) +@Consumes({MediaType.APPLICATION_JSON}) +@Produces(MediaType.APPLICATION_JSON) +public User getUser(@PathParam("username") String userName) { + ... +} +``` + +### @PathParam + +注解位置 参数注解 + +配合@Path进行使用 可以获取URI中指定规则的参数 + +``` +@GET +@Path("{username"}) +@Produces(MediaType.APPLICATION_JSON) +public User getUser(@PathParam("username") String userName) { + ... +} +// 浏览器请求http://ip:port/user/lilei时 userName值为lilei +``` + +### @QueryParam + +注解位置 参数注解 + +用于获取GET请求中的查询参数 实际上是url拼接在?后面的参数 +``` +@GET +@Path("/user") +@Produces("text/plain") +public User getUser(@QueryParam("name") String name, + @QueryParam("age") int age) { + ... +} + +// 浏览器请求http://ip:port/user?name=lilei&age=18时 name值为lilei age值为18 如需要为参数设置默认值 可以使用@DefaultValue +``` +### @FormParam + +注解位置 参数注解 + +用于获取POST请求且以form(MIME类型为application/x-www-form-urlencoded)方式提交的表单的参数 +``` +@POST +@Consumes("application/x-www-form-urlencoded") +public void post(@FormParam("name") String name) { + ... +} +``` + +### @FormDataParam +注解位置 参数注解 + +用于获取POST请求且以form(MIME类型为multipart/form-data)方式提交的表单的参数 通常是在上传文件的时候 + +### @HeaderParam + +注解位置 参数注解 + +用于获取HTTP请求头中的参数值 +``` +@GET +@Path("/user/get") +public Response getUser(@HeaderParam("user-agent") String userAgent) { + ... +} +// 这里获取user-agent的值 +``` +### @CookieParam + +注解位置 参数注解 + +用于获取HTTP请求cookie中的参数值 +``` +@GET +public String callService(@CookieParam("sessionid") String sessionid) { + ... +} +``` +### @MatrixParam +注解位置 参数注解 + +可以用来绑定包含多个property (属性)=value(值) 方法参数表达式 用于获取请求URL参数中的键值对 必须使用’;'作为键值对分隔符 +``` +@Path("/books") +public class BookService { + @GET + @Path("{year}") + public Response getBooks(@PathParam("year") String year, + @MatrixParam("author") String author, + @MatrixParam("country") String country) { + ... + } +} +// 请求1 "/books/2012/" 解析结果为 年份 2012 作者 null 国家 null +// 请求2 "/books/2012;author=andih" 解析结果为 年份 2012 作者 andih 国家 null +``` + +> 注意MatrixParam与QueryParam的区别 +> QueryParam请求url的格式为 url?key1=value1&key2=value2&… +> MatrixParam请求url的格式为 url;key1=value1;key2=value2;… + +### @DefaultValue + +配合前面的参数注解等使用 用来设置默认值 如果请求指定的参数中没有值 通过该注解给定默认值 + +注解位置 参数注解 +``` +@POST +@Path("/user/add") +@Consumes({MediaType.APPLICATION_FORM_URLENCODED}) +@Produces({MediaType.APPLICATION_JSON}) +public Response addUser(@FormParam("username") String userName, @DefaultValue("0") @FormParam("age") int age, @DefaultValue("1") @FormParam("sex") int sex){ + ... +} +``` + +> 注意 DefaultValue指定的值在解析过程中出错时(@DefaultValue(“test”) @QueryParam(“age”) int age) 将返回404错误 + +### @BeanParam +注解位置 参数注解 + +如果传递的较多 使用@FormParam等参数注解一个一个的接收每个参数可能显得太臃肿 可以通过Bean方式接收自定义的Bean 在自定义的Bean中字段使用@FormParam等参数注解 只需定义一个参数接收即可 +``` +public class MyBean { + @FormParam("myData") + private String data; + @HeaderParam("myHeader") + private String header; + @PathParam("id") + public void setResourceId(String id) {...} + ... +} + +@Path("myresources") +public class MyResources { + @POST + @Path("{id}") + public void post(@BeanParam MyBean myBean) { + ... + } + ... +} +``` + +### @Context +注解位置 属性注解 参数注解 + +用来用来解析上下文参数 和Spring中的AutoWired效果类似 通过该注解可以获取ServletConfig ServletContext HttpServletRequest HttpServletResponse和HttpHeaders等信息 +``` +@Path("/user") +publicclass Resource { + @Context + HttpServletRequest req; + @Context + ServletConfig servletConfig; + @Context + ServletContext servletContext; + + @GET + public String get(@Context HttpHeaders hh) { + MultivaluedMap headerParams = hh.getRequestHeaders(); + Map pathParams = hh.getCookies(); + } +} +``` + +### @Encoded +禁止解码 客户端发送的参数是什么样 服务器就原样接收 \ No newline at end of file diff --git a/Spring/Spring5/07 事件监听模型.md b/Spring/Spring5/07 事件监听模型.md new file mode 100644 index 00000000..f8a266a6 --- /dev/null +++ b/Spring/Spring5/07 事件监听模型.md @@ -0,0 +1,36 @@ +## 1 原理说明 + +### 事件驱动模型和观察者模式 +一下名称具有相同的含义,都是观察着模式在不同场景下的实现。 +* Spring的事件驱动模型 +* 设计模式中的观察者模式 +* jdk中的observable和observer +* ui中事件监听机制 +* 注册中心和消息队列的订阅发布机制 + +先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方)。当目标发送改变(发布),观察者(订阅者)就可以接收到改变。 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的), 目标无需干涉;所以就松散耦合了它们之间的关系。 + + +### Spring中实现 +![](image/2022-10-18-12-06-37.png) + + + +### 类图关系 +* 事件 + +![](image/2022-10-18-12-07-26.png) + + +* 发布(动作) + * ApplicationContext 接口继承了 ApplicationEventPublisher,并在 AbstractApplicationContext 实现了具体代码,实际执行是委托给ApplicationEventMulticaster(可以认为是多播) + +![](image/2022-10-18-12-08-25.png) + + +* 监听 + +![](image/2022-10-18-12-08-47.png) + + + diff --git a/Spring/Spring5/image/2022-10-18-12-06-37.png b/Spring/Spring5/image/2022-10-18-12-06-37.png new file mode 100644 index 00000000..463437b2 Binary files /dev/null and b/Spring/Spring5/image/2022-10-18-12-06-37.png differ diff --git a/Spring/Spring5/image/2022-10-18-12-07-26.png b/Spring/Spring5/image/2022-10-18-12-07-26.png new file mode 100644 index 00000000..fc70b960 Binary files /dev/null and b/Spring/Spring5/image/2022-10-18-12-07-26.png differ diff --git a/Spring/Spring5/image/2022-10-18-12-08-25.png b/Spring/Spring5/image/2022-10-18-12-08-25.png new file mode 100644 index 00000000..5be6de05 Binary files /dev/null and b/Spring/Spring5/image/2022-10-18-12-08-25.png differ diff --git a/Spring/Spring5/image/2022-10-18-12-08-47.png b/Spring/Spring5/image/2022-10-18-12-08-47.png new file mode 100644 index 00000000..1ad37aef Binary files /dev/null and b/Spring/Spring5/image/2022-10-18-12-08-47.png differ diff --git "a/docker/image/image\n.png" "b/docker/image/image\n.png" deleted file mode 100644 index 24978b0b..00000000 Binary files "a/docker/image/image\n.png" and /dev/null differ diff --git a/设计模式/4.7 观察者.md b/设计模式/4.7 观察者.md index c77f3a79..de5ef7e5 100644 --- a/设计模式/4.7 观察者.md +++ b/设计模式/4.7 观察者.md @@ -9,6 +9,7 @@ > * 在socket网络编程、IO编程中(netty、springWebFlux、sofarpc)就是Reactor模式 > * 在操作系统中就是IO多路复用的一种策略 > * 在UI框架中就是Listener,事件监听机制和响应机制 +> * 在Spring框架中也有事件监听模型。 > * 在web网站开发中,被称为响应式编程。 > * 在微服务中就是注册中心的发布订阅过程 > * 在消息中间件中就是发布订阅模式。