
如果你觉得使用官网来创建太慢了,那你直接把以前项目的依赖粘过来就行了:
一个是父工程的依赖:
<!--指定了一个父工程,父工程中的东西在该工程中可以继承过来使用--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version></parent><!--JDK 的版本--><properties><java.version>8</java.version></properties>
一个是常用的web依赖和测试依赖:
<dependencies><!--该依赖就是我们在创建 SpringBoot 工程勾选的那个 Spring Web 产生的--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--这个是单元测试的依赖,我们现在没有进行单元测试,所以这个依赖现在可以没有--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
最后一个是打包的插件:
<build><plugins><!--这个插件是在打包时需要的,而这里暂时还没有用到--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
然后写一个启动类就行,这里为了效果,我再写一个Controller:
@SpringBootApplication
@RestController
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class,args);}@GetMapping("/hello")public String test1(){System.out.println(123);return "123";}
}
注意:
Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package.至于打包发布,直接maven package就行,然后在对应的目录java -jar即可。前提是要有我们上面那个打包插件,否则会运行不了。
这个插件的作用:
- 把项目打包成一个可执行的超级JAR(uber-JAR),包括把应用程序的所有依赖打入JAR文件内,并为JAR添加一个描述文件,其中的内容能让你用java -jar来运行应用程序。
- 搜索public static void main()方法来标记为可运行类。
spring-boot-starter-web默认集成了tomcat,假如我们想把它换为jetty,可以在l中spring-boot-starter-web下排除tomcat依赖,然后手动引入jetty依赖:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency>
</dependencies>
在SpringBoot中有如下几种配置形式:
读取配置文件的形式:
注意:
提一嘴:
@ConfigurationProperties(prefix=“xxx”)和@ConfigurationProperties(“xxx”)是一个效果,我们可以看看源码:
@AliasFor注解的作用就是可以给一个属性创建一个别名,从而绑定到同一个外部属性上。
application全局配置文件能配置的属性:
application.properties中可配置所有官方属性
接下来我们一个个演示一下:
全局配置文件
这里我们使用@Value以及自定义对象的形式去拿到属性值:
server.port=8888
属性类:
@Component
@ConfigurationProperties(prefix="server")
public class PortConfig {private int port;public int getPort() {return port;}public void setPort(int port) {this.port = port;}
}
@SpringBootApplication
@RestController
public class MyApplication {public static void main(String[] args) {SpringApplication springApplication = new SpringApplication();SpringApplication.run(MyApplication.class,args);}@Value("${server.port}")private int port;@Resourceprivate PortConfig portConfig;@GetMapping("/hello")public String test1(){System.out.println(port); //结果8888System.out.Port()); //结果8888return "123";}
}
自定义配置文件
这里我创建一个自定义的配置文件myapplication.yaml:
server:port: 8888
我们要读取他,首先就要将这个配置文件加入到上下文中,那么就要使用到@PropertySource这个注解。这里有两个注意点:
第一个就是@PropertySource搜索区间问题:
@PropertySource 默认是在以下三个地方搜索配置文件:
注意你必须标明是哪一类中去寻找,他并没有找不到就切换区间尝试的机制。
这也就是为什么我们一般在使用这个注解的时候会在前面加上classpath:
@PropertySource("classpath:myapplication.yaml")
当然这里我们这样还是读取不到配置文件的,接下来我们再看第二点:SpringBoot中@PropertySource的默认实现是properties类型文件的解析
我们自定义的配置文件使用的是yaml类型的,所以这里是没办法解析的,解决办法就是:实现PropertySourceFactory接口,实现一个解析yaml文件的工具类。
public class YamlPropertySourceFactory implements PropertySourceFactory {@Overridepublic PropertySource<?> createPropertySource(String s, EncodedResource encodedResource) throws IOException {return new YamlPropertySourceLoader().load(Resource()).get(0);}
}
接下来我们使用Environment的方法去读取:
@SpringBootApplication
@RestController
@PropertySource(value = "classpath:myapplication.yaml",factory = YamlPropertySourceFactory.class)
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class,args);}@Value("${server.port}")private int port;@Resourceprivate PortConfig portConfig;@Resourceprivate Environment environment;@GetMapping("/hello")public String test1(){System.out.println(port); //结果8888System.out.Port()); //结果8888System.out.Property("server.port")); //结果8888return "123";}
}
命令行配置
在运行Spring Boot jar文件时,可以使用命令java -jar xxx.jar --server.port=8081来改变端口的值。这条命令等价于我们手动到application.properties中修改(如果没有这条属性的话就添加)server.port属性的值为8081。
如果不想项目的配置被命令行修改,可以在入口文件的main方法中进行如下设置:
public static void main(String[] args) {SpringApplication app = new SpringApplication(Application.class);app.setAddCommandLineProperties(false);app.run(args);
}
profile多环境配置
Profile用来针对不同的环境下使用不同的配置文件,多环境配置文件必须以application-{profile}.{properties|yml|yaml}的格式命名,其中{profile}为环境标识。
至于哪个具体的配置文件会被加载,需要在application.properties文件中通过spring.profiles.active属性来设置,其值对应{profile}值。
如:spring.profiles.active=dev就会加载application-dev.properties配置文件内容。可以在运行jar文件的时候使用命令java -jar xxx.jar --spring.profiles.active={profile}切换不同的环境配置。
我们来演示一下:
application-dev.properties:
server.port=8888
application-prod.properties:
server.port=9999
外部配置文件
在前一种情况的基础上,我们在当前jar包的同一目录下放一个配置文件application.properties:
内容如下:
spring.profiles.active=prod
然后我们运行jar包,这次我们不添加命令行参数:
这里我们就介绍一种最常用的方式 @ControllerAdvice+@ExceptionHandler处理全局异常:
@RestController
public class ExceptionTestController {@GetMapping("/ex")public String testException(){//抛出一个自定义的异常throw new MyException();}
}
//assignableTypes指定处理哪个Controller中的异常,不加代表处理所有Controller
@ControllerAdvice(assignableTypes = {ExceptionTestController.class})
public class MyExceptionHandler {//指定处理哪一类异常@ExceptionHandler(Exception.class)//返回Json数据@ResponseBody//指定异常处理方法返回的HTTP状态码@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public Map<String, Object> handleUserNotExistsException(Exception e) {Map<String, Object> map = new HashMap<>();map.put("message", e.getMessage());return map;}
}
首先我们用最简单的话弄清楚过滤器和拦截器的区别:
这里我们先说说过滤器怎么实现,两种方式:
第一种
我们首先实现一个自己的Filter:
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("当前请求的ip地址为" + LocalAddr());//对请求进行放行filterChain.doFilter(servletRequest,servletResponse);}
}
然后再配置类中进行Filter注册:
@Configuration
public class ApplicationConfig {@Beanpublic FilterRegistrationBean<MyFilter> filterFilterRegistrationBean(){FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();filterRegistrationBean.setFilter(new MyFilter());//可以使用filterRegistrationBean.setUrlPatterns配置要拦截的路径return filterRegistrationBean;}
}
如果有多个Filter,想定义顺序:
第二种
在自己的过滤器的类上加上@WebFilter 然后在这个注解中通过它提供好的一些参数进行配置
@WebFilter(filterName = "MyFilter",urlPatterns = "/*")
//这里的urlPatterns支持的是Ant风格的路径
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("当前请求的ip地址为" + LocalAddr());//对请求进行放行filterChain.doFilter(servletRequest,servletResponse);}
}
另外,为了能让 Spring 找到它,你需要在启动类上加上 @ServletComponentScan 注解
如果你需要自定义 Interceptor 的话必须实现 org.springframework.web.servlet.HandlerInterceptor接口或继承 org.springframework.web.servlet.handler.HandlerInterceptorAdapter类,并且需要重写下面下面3个方法:
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler, //就是控制器方法HandlerMethodModelAndView modelAndView)public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)
注意: preHandle方法返回 true或 false。如果返回 true,则意味着请求将继续到达 Controller 被处理。
处理顺序如下:
注意:postHandle只有当被拦截的方法没有抛出异常成功时才会处理,afterCompletion方法无论被拦截的方法抛出异常与否都会执行。
我们演示一下:
先自定义一个拦截器
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.String());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
然后再配置类中添加拦截器:
@Configuration
public class ApplicationConfig extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor());}
}
Lombok是一个Java库,它通过注解的方式来简化Java代码的编写。它的实现原理主要是通过在编译阶段的注解处理器来处理被Lombok注解标记的代码,并在编译过程中生成相应的Java代码。
具体来说,当使用Lombok注解标记一个类、字段或方法时,编译器会在编译阶段将这些被注解标记的代码传递给Lombok的注解处理器。注解处理器会根据注解的类型和参数,生成相应的Java代码,并将生成的代码插入到编译后的Java文件中。
需要注意的是,Lombok生成的代码是在编译阶段完成的,所以在源代码中看不到生成的代码。但在编译后的.class文件中,可以看到Lombok生成的代码已经被插入到相应的位置。这样,生成的代码就可以在运行时被正常调用和使用。
Lombok的注解处理器是以插件的形式集成到Java编译器中的。当使用Lombok库时,IDE或构建工具会将Lombok的注解处理器添加到编译器的处理器列表中。这样,在编译Java代码时,编译器会自动调用Lombok的注解处理器来处理被Lombok注解标记的代码。
需要注意的是,为了使Lombok的注解处理器正常工作,需要在使用Lombok的项目中添加Lombok库的依赖。这样,编译器才能正确识别和处理Lombok的注解。
所以要使用Lombok我们除了添加依赖之外,还要在自己的IDEA中安装lombok的插件:
<!-- 引入 Lombok 依赖 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
接下来我们看看这个lombok具体怎么用:
@Getter 注解,添加在类或属性上,生成对应的 get 方法。
@Setter 注解,添加在类或属性上,生成对应的 set 方法。
@ToString 注解,添加在类上,生成 toString 方法。
@EqualsAndHashCode 注解,添加在类上,生成 equals 和 hashCode 方法。
@AllArgsConstructor、@RequiredArgsConstructor、@NoArgsConstructor 注解,添加在类上,为类自动生成对应参数的构造方法。
@Data 注解,添加在类上,是 5 个 Lombok 注解的组合。
@Value 注解,添加在类上,和 @Data 注解类似,区别在于它会把所有属性默认定义为 private final 修饰,所以不会生成 set 方法。
@CommonsLog、@Flogger、@Log、@JBossLog、@Log4j、@Log4j2、@Slf4j、@Slf4jX 注解,添加在类上,自动为类添加对应的日志支持。
@NonNull 注解,添加在方法参数、类属性上,用于自动生成 null 参数检查。若确实是 null 时,抛出 NullPointerException 异常。
@Cleanup 注解,添加在方法中的局部变量上,在作用域结束时会自动调用 #close() 方法,来释放资源。例如说,使用在 Java IO 流操作的时候。
@Builder 注解,添加在类上,给该类加个构造者模式 Builder 内部类。
@Synchronized 注解,添加在方法上,添加同步锁。
@SneakyThrows 注解,添加在方法上,给该方法添加 try catch 代码块。
@Accessors 注解,添加在方法或属性上,并设置 chain = true,实现链式编程。
我们来看看其中三个比较常用的: @Data 和 @Slf4j、@NonNull
@Data
@Data
public class Person {private String name;private int age;}
@EqualsAndHashCode(callSuper = true)
@Data
@ToString(callSuper = true)
public class Student extends Person{private int studyId;private int className;
}
反编译后的Student类:
public class Student extends Person {private int studyId;private int className;public boolean equals(final Object o) {if (o == this) {return true;} else if (!(o instanceof Student)) {return false;} else {Student other = (Student)o;if (!other.canEqual(this)) {return false;} else if (!super.equals(o)) {return false;} else if (StudyId() != StudyId()) {return false;} else {ClassName() == ClassName();}}}protected boolean canEqual(final Object other) {return other instanceof Student;}public int hashCode() {int PRIME = true;int result = super.hashCode();result = result * 59 + StudyId();result = result * 59 + ClassName();return result;}public Student() {}public int getStudyId() {return this.studyId;}public int getClassName() {return this.className;}public void setStudyId(final int studyId) {this.studyId = studyId;}public void setClassName(final int className) {this.className = className;}public String toString() {return "Student(super=" + String() + ", studyId=" + StudyId() + ", className=" + ClassName() + ")";}
}
如果使用 @Data 注解的类,继承成了其它父类的属性,最好额外添加 @ToString(callSuper = true) 和 @EqualsAndHashCode(callSuper = true) 注解。因为默认情况下,@Data 注解不会处理父类的属性。所以需要我们通过 callSuper = true 属性,声明需要调用父类对应的方法。
@Slf4j
你使用的日志门面以及日志实现的依赖依旧照常导入,不能省略。
@Slf4j 注解,添加在类上,给该类创建 Slf4j Logger 静态属性。
@NonNull 注解
@NonNull 注解,添加在方法参数、类属性上,用于自动生成 null 参数检查。若确实是 null 时,抛出 NullPointerException 异常。
其好处就是: IDEA HTTP Client 采用后缀为 .http 的文本文件,可以和 Java 代码一起使用 Git 进行版本管理,从而实现团队协作的共享。同时因为内置在了IDEA中,不需要切换软件去进行接口测试,比较方便。
.http文件我们在Idea中右键就可以创建,也可以直接在Controller中自动生成:
进去之后可以看到右上角有几个选项,示意如下:
首先我们来说明三种比较常见的情况:
POST 请求 + Form
@PostMapping("/user/login")
public Map<String, Object> login(@RequestParam("username") String username,@RequestParam("password") String password) {if ("yudaoyuanma".equals(username) && "123456".equals(password)) {Map<String, Object> tokenMap = new HashMap<>();tokenMap.put("userId", 1);tokenMap.put("token", "token001");return tokenMap;}throw new RuntimeException("小朋友,你的账号密码不正确哟!");
}
对应的 IDEA HTTP Client 的代码如下:
### 测试 /user/login:登陆成功
POST 127.0.0.1:8080/user/login
Content-Type: application/x-www-form-urlencodedusername=yudaoyuanma&password=123456
POST 请求 + JSON
@PostMapping("/user/update")
public Boolean update(@RequestBody UserUpdateVO updateVO) {logger.info("[update][收到更新请求:{}]", String());return true;
}
对应的 IDEA HTTP Client 的代码如下:
### 测试 /user/update:更新成功
POST 127.0.0.1:8080/user/update
Content-Type: application/json{"nickname": "我是昵称","gender": 1
}
GET 请求
@GetMapping("/user/get-current")
public Map<String, Object> getCurrentUser(@RequestHeader("Authorization") String authorization,@RequestParam("full") boolean full) {if ("token001".equals(authorization)) {Map<String, Object> userInfo = new HashMap<>();userInfo.put("id", 1);// full 为 true 时,获得完整信息if (full) {userInfo.put("nickname", "芋道源码");userInfo.put("gender", 1);}return userInfo;}throw new RuntimeException("小朋友,你没有登录哟!");
}
对应的 IDEA HTTP Client 的代码如下:
### 测试 /user/get-current:获取成功
GET 127.0.0.1:8080/user/get-current?full=true
Authorization: token001
如果想要了解更多,可以参考下面的文章:
芋道 Spring Boot API 接口调试 IDEA HTTP Client
本文发布于:2024-02-13 12:18:18,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/1715472973252663.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
| 留言与评论(共有 0 条评论) |