本文共 16073 字,大约阅读时间需要 53 分钟。
1、注入
1.1、Bean对象管理
Spring Boot 由于没有XML文件,所以所有的Bean管理都放入在一个配置类中实现。
配置类就是类上具有@Configuration的类。这个类就相当于之前的applicationContext.xml新建一个Java类,用来管理Bean对象。
@Configuration // => applicationContext.xmlpublic class beanConfig { @Bean // @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) // 将方法的返回值交给工厂管理,方法为public // 而方法名也就对于bean的id标识 public Calendar calendar(){ return Calendar.getInstance(); }}
而Bean对象创建好了之后,我们就可以直接在controller当中通过@Autowired注解将Bean对象注入进来。
2.2、属性注入
在开发过程当中,我们通常需要配置一些常量来作为项目当中使用到的一些数据,而这些数据有时候又是需要经常改变的,这个时候也就可以通过属性注入来解决这一问题,避免了后续需要修改java代码,而可以直接修改配置文件即可。
再配置文件当中分别定义以下数据:(字符串string、数字int、数组arr、集合List、集合map)
name=yueyueage=18date=2021/06/18 10:25:11arrs=14,54,65,87,0lists=45,84,69maps.a=1maps.b=2
而对于这些属性我们如何注入到controller控制器当中?我们可以直接使用@Value注解。使用方式@Value(“${xxx}”)
@Value("${name}") private String name; @Value("${age}") private Integer age; @Value("${date}") private Date date; @Value("${arrs}") private String[] arrs; @Value("${lists}") private Listlists;
1.3、Obj对象注入
同样的,还是先在配置文件当中定义一个obj对象的数据:
orders.id=1orders.name=yueyue
之后我们在实体类当中进行对这个obj对象进行注入,先在类上添加注释@ConfigurationProperties(value = “orders”),而这个实体类当中对应的属性,而这些属性也必须提供相关的setter方法。
// 修饰于类 将指定的对象属性进行注入// 进行属性注入必须提供 setter方法@ConfigurationProperties(value = "orders")public class injectObjController { private Integer id; private String name; public void setId(Integer id) { this.id = id; } public void setName(String name) { this.name = name; } @RequestMapping("injectObj") public String injectObj() { System.out.println(id); System.out.println(name); return "injectObj"; }}
2、JSP和Thymeleaf模板集成
SpringBoot提供了两套模板集成,也就是Jsp和thymeleaf,首先还是了解一下jsp和thymeleaf ,对于jsp来说还是比较熟悉的。
经历过传统的java Web开发的人都知道jsp是可以响应用户请求的htnl页面。我们都知道HTML页面是静态的,为什么jsp能够部署于服务器上并且响应用户请求呢?因为jsp在HTML中嵌入了java代码。所以我们可以这样认为:jsp = java + HTML因为jsp页面中掺杂着后台的代码,使得前后端整体分离的思想不能很好的实现,可能前端jsp页面的一个简单的java问题也会导致项目不能启动,整体的开发便捷程度不是很好,于是在springBoot中推荐使用新的好用的模板引擎:Thymeleaf
Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 JSP,Velocity,FreeMaker 等,它也可以轻易的与 Spring MVC 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。
2.1、Jsp集成
在进行jsp集成之前,我们可以看一下springMvc是如何做的。参考:
而在springboot当中没有相关的配置文件让我们来进行配置处理器映射器、处理器适配器、视图解析器等等,这些都是通过配置文件和注解进行统一管理。
而进行集成jsp模板主要分为以下几个步骤:
jstl jstl 1.2 org.apache.tomcat.embed tomcat-embed-jasper
# jsp前后缀spring.mvc.view.prefix=/spring.mvc.view.suffix=.jsp
@RequestMapping("/jsp") public String jsp(){ System.out.println("hello jsp"); return "index"; }
最后还有一个就是在对jsp进修改之后,我们需要实时的对jsp页面进行刷新,避免改一下又要重启项目,这时我们只需要再加一个动态刷新jsp的配置就好了。
server.servlet.jsp.init-parameters.development=true
以及项目运行可能会报404页面找不到,这是因为没有给项目设置路径,路径不对当然就会报404啦,我们只需要在启动项目的地方添加配置 $MODULE_WORKING_DIR$
指定给当前项目地址即可。
3、整合MyBatis
在进行整合mybatis框架,还是一样的,我们首先还是导入mybatis的相关依赖。这里还包括了MySQL、连接池相关依赖。
com.alibaba druid 1.2.4 mysql mysql-connector-java 8.0.19 org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.4
依赖引入之后就是进行配置了,我们需要在配置文件当中对数据源、数据库、dao、mapper、entity进行指定。
spring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/springboot?characterEncoding=UTF-8spring.datasource.username=rootspring.datasource.password=rootmybatis.mapper-locations=classpath:com/lzq/mapper/*.xmlmybatis.type-aliases-package=com.lzq.entity
之后添加对应的controller、dao、service、entity、mapper文件。这些都是和SSM框架当中一致的,在dao接口,可以在每个接口上面定义@Mapper注解进行标明,也可以在启动类上使用@MapperScan进行标识统一扫描。
4、本地测试和热部署
4.1、SpringBootTest本地测试
关于Springboot本地测试,在springboot当中提供了对应的依赖,spring-boot-starter-test。之后我们创建一个用来作为本地测试的测试类,使用@SpringBootTest注解表明当前类是一个测试类再就是使用@Test作用于方法上,之后我们就可以对这个方法进行run和dubug。
4.2、SpringBoot热部署
在实际开发过程中,每次修改代码就得将项目重启,重新部署,对于一些大型应用来说,重启时间需要花费大量的时间成本。对于进行后端开发的过程当中来说,重启过程确实很难受啊。
而在springboot当中就提供了一个关于热部署的依赖,我们直接将依赖导入之后进行设置就可以将这个springboot项目进行热部署了,之后每当我们修改了java文件之后,就会自动的将修改后的java文件进行编译成class文件,再到虚拟机当中进行替换。这样我们需要重新加载的类就少了许多,也就进一步的减少了在重启项目上浪费的时间。
首先还是导入依赖:
org.springframework.boot spring-boot-devtools true
之后在idea当中进行配置,首先File-Settings-Compiler-Build Project automatically进行勾选
其次,ctrl + shift + alt + / ,选择Registry,勾上 Compiler autoMake allow when app running 最后可能需要重启一个idea,运行项目,或者修改java文件保存后看打印输出的日志,像这里的restartedMain就表示热部署完成了。 5、日志在SpringBoot当中采用的是logback日志处理,而logback也就是对logj这个日志的进一步的优化,使得这个日志更加的轻量级。Logback是SpringBoot内置的日志处理框架,你会发现spring-boot-starter其中包含了spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback。
然后就是日志的级别:定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
级别 | 说明 |
---|---|
ALL | 最低等级的,用于打开所有日志记录。 |
TRACE | designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。 |
DEBUG | 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。 |
INFO | 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印 过多的日志。 |
WARN | 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。 |
ERROR | 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。 |
FATAL | 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。 |
OFF | 最高等级的,用于关闭所有日志记录。 |
而后在SpringBoot当中还是通过配置文件来对日志打印进行配置的。在springboot当中日志分为根日志 rootlogger 和 子日志 logger ,根日志的级别是使用的INFO。
我们可以通过 logging.leavl.root 和 logging.leavl.子包对根日志和子日志进行级别设置。以及可以将打印的日志进行保存下来,通过logging.file.name和logging.file.path设置日志文件名和地址。
# 根日志# logging.level.root = debuglogging.level.com.lzq.dao.UserDao=debug# 日志保存logging.file.name=run.log# 日志保存路径,项目路径logging.file.path=./
6、AOP切面
AOP切面:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
举一个简单的案例: 在进行实际的开发过程当中,一个系统当中的登录功能,在登录功能这里进行做后续操作,在后续的操作我们每一个controller或者是service实现方法,我们都需要对登录信息进行验证,通过之后才进行后续操作,简单的实现当然是在每一个方法当中都加上校验的代码,或者加一个方法进行封装,每个方法再调一次这个封装的方法。而AOP切面就解决了这个问题,我们在配置之后每一个方法在调用之前都会进一遍切面执行切面的方法。
关于Spring的AOP切面可以参考这篇文章:
AOP依赖引入:直接在pom文件当中引入spring-boot-starter-aop依赖。
org.springframework.boot spring-boot-starter-aop
在Springboot当中提供了注解的方式用来取代Spring当中的xml配置,在使用切面的时候,提供了一个@Aspect注解,作用与类上,用来表示这个类是一个切面类,并且我们将这个切面类也作为一个配置类,方便后续对切面的处理。
而在切面当中涉及的前置、后置、环绕通知都有对应的注解进行作用于对应的方法上进行说明。而注解里面的value值即表示对应的类或者包名采用切面。也就是所说的切入点。
在前置和后置通知我们的方法进行入参的时候都可以将一个JoinPoint对象作为入参,也就是一个连接点(附加操作或者说切面方法 和 核心方法 相交的点)并且使用这个对象所对应的getXX方法可以获取到当前这个连接点作用的类和方法名。
而有区别的就是环绕通知,在环绕通知是没有这个JoinPoint连接点的,而取而代之的是一个ProceedingJoinPoint处理中连接点,而当切面执行到这里的时候我们的程序会阻塞,调用这个ProceedingJoinPoint的proceed方法,得到一个Object的值,将这个值作为一个返回值,也就代表了环绕通知的结束,程序继续往后运行。
@Configuration@Aspect// 切面配置类public class AspectConfig { @Before("execution(* com.lzq.service.*.*(..))") public void aopBefore(JoinPoint joinPoint){ System.out.println(joinPoint); // 对应执行的类 System.out.println(joinPoint.getTarget()); // 对应执行的方法 System.out.println(joinPoint.getSignature().getName()); System.out.println("Before"); } @After("execution(* com.lzq.service.*.*(..))") public void aopAfter(){ System.out.println("After"); } @Around("execution(* com.lzq.service.*.*(..))") public Object aopAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println(proceedingJoinPoint.getTarget()); System.out.println(proceedingJoinPoint.getSignature().getName()); // 程序放行 Object proceed = proceedingJoinPoint.proceed(); System.out.println("Around"); // 类似拦截器 return proceed; }}
7、文件的上传和下载
8、拦截器
Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。对于Spring MVC 拦截器详情可以查看这篇文章:
在SSM框架当中都是使用xml配置文件进行配置拦截器,首先定义一个类进行实现HandlerInterceptor接口,重写接口当中的方法。而在springboot当中我们使用注解对xml文件进行替换。
在springboot当中提供了一个有关拦截器的配置接口,我们直接实现该接口重写内部方法。在这里的每一个 registry.addInterceptor都是添加一个我们自己定义的拦截器,并且拦截器的触发是一个栈的结构,遵循先进后出的原则,例如:添加2个拦截器,拦截器里面重写的三个方法依次为123456,如果是第一个拦截器先执行的话(即先是123的拦截器执行),那么他的输出结果就是145263
@Configurationpublic class MvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 将Interceptor类作为一个拦截器,并且使用addPathPatterns覆盖其所有路径 registry.addInterceptor(new Interceptor()).addPathPatterns("/**"); }}
而使用excludePathPatterns方法可以将部分路由进行排除,不被拦截器拦截。
registry.addInterceptor(new Interceptor()).excludePathPatterns("/file/**");
之后就是定义一个拦截器类,实现 接口以及对应方法,这个和SpringMVC当中是一致的
public class Interceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Constomer preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println(modelAndView.getViewName()); System.out.println("Constomer postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("Constomer afterCompletion"); }
9、jar包和war包的部署
9.1、War包方式
在之前的开发的过程当中,前后端没有分离,都放在同一个目录下,这个时候我们还是使用外部tomcat进行启动项目,所以在项目开发完成之后,我们都是将项目打成war包,之后将项目放到tomcat的webapp下面,之后启动这个tomcat就可以根据对应的地址进行访问我们的项目了。
而我们开发完成的项目如何打成这个war包并且放到tomcat下运行呢?
首先需要打成war包,我们需要指定打包的方式,也就是在pom当中添加打包方式
war
其次就是我们的springboot项目是内嵌tomcat的,我们就需要将内嵌的tomcat去除掉。在之前的使用jsp当中的jsp需要使用到的tomcat依赖。以及打成war包所需要将入口类进行修改配置。
org.apache.tomcat.embed tomcat-embed-jasper provided
org.springframework.boot spring-boot-maven-plugin true Dfile.encoding=UTF-8 com.lzq.SpringbootDay2Application
再者就是我们需要入口类进行重新修改,要继承至SpringBootServletInitializer类,重写configure方法:
@SpringBootApplicationpublic class SpringbootDay2Application extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(SpringbootDay2Application.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(SpringbootDay2Application.class); }}
这样修改完成之后,在maven当中对这个项目进行打包,打成一个war包,之后将这个war包放到我们的tomcat当中进行启动即可:
9.2、Jar包方式而我们这里的springboot内嵌了tomcat,所以也就更加推荐使用jar包进行打包,在前面的文章有一个创建可执行的jar,jar包打好后,直接使用 java -jar jar包的名字
进行启动,启动之后使用对应的路由进行访问。
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。
而RESTful风格在SSM框架当中就有了,这里也就不做详细编写了,简单来说就是对不同的请求进行分类,避免全部使用@RequestMapping进行路由定义,而需要给定具体的请求类型,如GET、POST、PUT、DELETE等等,可以参考这篇文章:
最后还有一个就是这样进行返回的对象是不包含状态码的,在springboot当中,也提供了一个有关网络状态码的枚举类HttpStatus,但是在这里进行返回就需要将对象进行包装一下,使用ResponseEntity返回实体类对象进行包装。
@GetMapping("/getuser/name") public ResponseEntitygetUserName(@PathVariable("name") String name){ User user = new User(); return new ResponseEntity (user, HttpStatus.OK); }
11、异常处理
11.1、Spring的异常处理
在spring当中我们需要对异常进行监听处理,使用的是通过一个被@Component注解修饰的类进行实现HandlerExceptionResolver接口,之后我们重写接口的resolveException方法,从而进行异常处理。@Componentpublic class MyExpection implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception e){ System.out.println(e); return null; }
11.2、SpringBoot的异常处理
而对于springboot当中的异常处理,提供了一个@ControllerAdvice注解,我们将这个注解添加到用来监听和处理异常的类上,定义一个处理异常的方法,并且这个方法需要添加@ExceptionHandler注解,这个注解可以用来统一处理方法抛出的异常。
@ExceptionHandler @ResponseBody public ResponseEntity exceptionHandler(Exception e){ System.out.println("进入异常处理"); return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); }
12、CORS跨域
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
在进行前后端分离开发的时候,前后端项目不在同一个域下面,所以在进行发送ajax请求的时候,浏览器会抛出不允许跨域请求,那这个时候我们又该如何处理呢?
12.1、局部解决跨域问题
使用注解:@CrossOrigin 该注解可以向@RequestMapping注解处理程序方法添加一个@CrossOrigin注解,以便启用CORS(默认情况下,@CrossOrigin允许在@RequestMapping注解中指定的所有源和HTTP方法)
12.2、全局解决跨域问题
我们添加一个配置类进行对全局跨域问题的Cros进行解决
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.cors.CorsConfiguration;import org.springframework.web.cors.UrlBasedCorsConfigurationSource;import org.springframework.web.filter.CorsFilter;@Configurationpublic class CorsConfig { @Bean // 允许跨域调用的过滤器 public CorsFilter corsFilter(){ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); //允许所有域名进行跨域调用 corsConfiguration.addAllowedOrigin("*"); //放行全部原始头信息 corsConfiguration.addAllowedHeader("*"); //允许所有请求方法跨域调用 corsConfiguration.addAllowedMethod("*"); source.registerCorsConfiguration("./**",corsConfiguration); return new CorsFilter(source); }}
13、jasypt加密
jasypt官网:
而我们需要使用jasypt,首先还是引入相关依赖:
com.github.ulisesbocchio jasypt-spring-boot-starter 2.0.0
之后我们可以在配置文件当中指定加密的算法和秘钥,
jasypt.encryptor.algorithm=PBEWithMD5AndDESjasypt.encryptor.password=123456
算法在JasyptEncryptorConfigurationProperties类当中也有默认值,也就是PBEWithMD5AndDES
最后新建一个测试类进行对加密和解密进行测试:import org.jasypt.encryption.StringEncryptor;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublic class jasyptTest { private StringEncryptor stringEncryptor; @Autowired public jasyptTest(StringEncryptor stringEncryptor) { this.stringEncryptor = stringEncryptor; } @Test public void test() { // 加密 String root = stringEncryptor.encrypt("root"); System.out.println(root); // 解密 String decrypt= stringEncryptor.decrypt("21J3+hSZ9GZt2Wnm6dwjcA=="); System.out.println(decrypt); }}
但是在这里的秘钥放在配置文件当中显然是不安全的,所以我们的秘钥通常要放在一台安全的服务器当中,或者放在启动程序当中,比如这里我们可以先放在jvm参数当中,-Djasypt.encryptor.password=123456
我们在启动 SpringBoot 时,控制台会打印 SpringBoot Logo 以及版本信息;而这个我们就可以根据banner进行自定义打印:
在使用banner的时候,我们只需要在rescources目录下添加一个banner.txt文件,就可以对其进行自定义显示。
██ ████ ░░ █████ ██░░██ ██ ███████ ██░░░██░██ ░██ ░██░░██░░░██░██ ░██░░█████ ░██ ░██ ░██░░██████ ░░░░██ ░██ ░██ ░██ ░░░░░██ ░███░██ ███ ░██ █████${ spring-boot.version}${ spring-boot.formatted-version}${ AnsiColor.RED} ${ spring-boot.version}${ AnsiColor.BRIGHT_CYAN} ${ spring-boot.formatted-version}
最后重启项目看一下效果:
Banner生成:哈哈,到这里SpringBoot基本上也就差不多写了这么多点笔记,但是感觉还是学到了许多,虽然说很大的一部分还是有着前面SSM框架的内容,但是在学习之后还是了解了很多的细节。最后,继续加油!
转载地址:http://wuqzi.baihongyu.com/