查看CentOS版本方法
有以下命令可以查看: rpm -q centos-release # lsb_release -a LSB Version: :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch Distributor ID: CentOS Description: CentOS release 5.4 (Final) Release: 5.4 Codename: Final 这个命令适用于所有的linux,包括Redhat、SuSE、Debian、Centos等发行版。 root@MyMail ~ # uname Linux root@MyMail ~ # uname -r 2.6.18-164.el5 [root@localhost ~]# uname -a Linux localhost.localdomain 2.6.18-194.el5 #1 SMP Fri Apr 2 14:58:35 EDT 2010 i686 i686 i386 GNU/Linux 以下二种方法适用于RedHat,CentOS root@MyMail ~ # cat /etc/redhat-release CentOS release 5.4 (Final) 登录到linux执行rpm -q redhat-release #rpm -q redhat-release 或CentOS root@MyMail ~ # rpm -q centos-release centos-release-5-4.el5.centos.1 当前centos 版本与redhat对应的版本的命令 # cat /proc/version Linux version 2.6.9-78.ELsmp (mockbuild@builder16.centos.org) (gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)) #1 SMP Fri […]
View Details.NET Core2.1项目在Linux上使用验证码报Unable to load shared library 'gdiplus' or one of its dependencies
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
2019-05-09 10:27:01,330 线程ID:[80] 日志级别:ERROR 出错类:WebApp.HttpGlobalExceptionFilter property:[(null)] - 错误描述:System.TypeInitializationException: The type initializer for 'System.DrawingCore.GDIPlus' threw an exception. ---> System.DllNotFoundException: Unable to load shared library 'gdiplus' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libgdiplus: cannot open shared object file: No such file or directory at System.DrawingCore.GDIPlus.GdiplusStartup(UInt64& token, GdiplusStartupInput& input, GdiplusStartupOutput& output) at System.DrawingCore.GDIPlus..cctor() --- End of inner exception stack trace --- at System.DrawingCore.GDIPlus.GdipGetGenericFontFamilySansSerif(IntPtr& fontFamily) at System.DrawingCore.FontFamily..ctor(GenericFontFamilies genericFamily) at System.DrawingCore.FontFamily.get_GenericSansSerif() at System.DrawingCore.Font.CreateFont(String familyName, Single emSize, FontStyle style, GraphicsUnit unit, Byte charSet, Boolean isVertical) at Common.VerifyCodeHelper.CreateByteByImgVerifyCode(String verifyCode, Int32 width, Int32 height) in F:\src\WebApp\Common\VerifyCodeHelper.cs:line 206 at WebApp.Controllers.VerifyCodeController.NumberVerifyCode() in F:\src\WebApp\Controllers\VerifyCodeController.cs:line 27 at lambda_method(Closure , Object , Object[] ) at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters) at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync() |
解决方法 Centos 7 yum install libgdiplus-devel from:https://www.cnblogs.com/asd14828/p/10837140.html?utm_source=tuicool
View DetailsCentOS7/8-重建官方yum源
1 2 3 4 |
cd /etc/yum.repos.d/ #删除所有 rpm -Uvh --force https://vault.centos.org/7.7.1908/os/x86_64/Packages/centos-release-7-7.1908.0.el7.centos.x86_64.rpm yum clean all yum makecache |
from:https://www.jianshu.com/p/cd1dfca70e85 CentOS8 http://mirror.centos.org/centos-8/8.5.2111/extras/x86_64/os/Packages/centos-release-stream-8.1-1.1911.0.7.el8.x86_64.rpm
View Details如何让 ASP.NET Core Web API 在 500 错误时返回具体的异常信息
通过 Opw.HttpExceptions.AspNetCore 搞定了。 1)安装 nuget 包 Opw.HttpExceptions.AspNetCore
1 |
<PackageReference Include="Opw.HttpExceptions.AspNetCore" Version="2.3.0" /> |
2)Startup.ConfigureServices 中添加 AddHttpExceptions
1 |
services.AddControllers().AddHttpExceptions(); |
3)Startup.Configure 中添加 UseHttpExceptions
1 |
app.UseHttpExceptions(); |
示例响应输出
1 |
{"type":"error:invalid-cast","title":"InvalidCast","status":500,"detail":"Invalid cast from \u0027System.Int32\u0027 to \u0027Cnblogs.Infrastructure.Primitives.PostConfig\u0027.","instance":"/zzkdocuments"} |
from:https://q.cnblogs.com/q/121590/
View DetailsGradle 换阿里仓库
改单个项目 在项目的build.gradle文件中,修改repositories配置,将mavenCentral()改为 maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}, 如:
1 2 3 |
repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } } |
更改所有项目 如果想一次更改所有的仓库地址,可以在 USER_HOME/.gradle/文件夹下添加 init.gradle 文件来配置,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
allprojects{ repositories { def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public/' all { ArtifactRepository repo -> if(repo instanceof MavenArtifactRepository){ def url = repo.url.toString() if (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')) { remove repo } } } maven { url REPOSITORY_URL } } } |
作者:xiaolyuh 链接:https://www.jianshu.com/p/471227b2b7e8 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details解决访问swaggerUI接口文档显示basic-error-controler问题
问题描述 使用swagger生成接口文档后,访问http://localhost:8888/swagger-ui.html#/,显示如下: 有些强迫症的我,感觉看起来很不舒服,结果百度了好久,找到解决方案,刚接触spring boot对于很多api还不是很熟悉,先mark再说 代码如下:
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 |
package com.course.config; import com.google.common.base.Predicates; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .pathMapping("/") .select() // 选择那些路径和api会生成document .apis(RequestHandlerSelectors.any())// 对所有api进行监控 //不显示错误的接口地址 .paths(Predicates.not(PathSelectors.regex("/error.*")))//错误路径不监控 .paths(PathSelectors.regex("/.*"))// 对根下所有路径进行监控 .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("这是我的接口文档") .contact(new Contact("rongrong", "", "emai@qq.com")) .description("这是SWAGGER_2生成的接口文档") .termsOfServiceUrl("NO terms of service") .license("The Apache License, Version 2.0") .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html") .version("v1.0") .build(); } } |
重启服务:再次访问如下 from:https://www.cnblogs.com/longronglang/p/9045559.html
View DetailsSpring Boot:整合Swagger文档
综合概述 spring-boot作为当前最为流行的Java web开发脚手架,越来越多的开发者选择用其来构建企业级的RESTFul API接口。这些接口不但会服务于传统的web端(b/s),也会服务于移动端。在实际开发过程中,这些接口还要提供给开发测试进行相关的白盒测试,那么势必存在如何在多人协作中共享和及时更新API开发接口文档的问题。 假如你已经对传统的wiki文档共享方式所带来的弊端深恶痛绝,那么尝试一下Swagger2 方式,一定会让你有不一样的开发体验。 使用 Swagger 集成文档具有以下几个优势: 功能丰富 :支持多种注解,自动生成接口文档界面,支持在界面测试API接口功能; 及时更新 :开发过程中花一点写注释的时间,就可以及时的更新API文档,省心省力; 整合简单 :通过添加pom依赖和简单配置,内嵌于应用中就可同时发布API接口文档界面,不需要部署独立服务。 实现案例 接下来,我们就通过Spring Boot 来整合Swagger实现在线API文档的功能。 生成项目模板 为方便我们初始化项目,Spring Boot给我们提供一个项目模板生成网站。 1. 打开浏览器,访问:https://start.spring.io/ 2. 根据页面提示,选择构建工具,开发语言,项目信息等。 3. 点击 Generate the project,生成项目模板,生成之后会将压缩包下载到本地。 4. 使用IDE导入项目,我这里使用Eclipse,通过导入Maven项目的方式导入。 添加相关依赖 添加 Maven 相关依赖,这里需要添加上WEB和SWAGGER依赖。 WEB依赖
1 2 3 4 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> |
swagger依赖,这里选择 2.9.2 版本。
1 2 3 4 5 6 7 8 9 10 11 |
<!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> |
添加配置类 添加一个swagger 配置类,在工程下新建 config 包并添加一个 SwaggerConfig 配置类。 SwaggerConfig.java
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 |
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()).build(); } private ApiInfo apiInfo(){ return new ApiInfoBuilder() .title("Kitty API Doc") .description("This is a restful api document of Kitty.") .version("1.0") .build(); } } |
添加控制器 添加一个控制器,在工程下新建 controller包并添加一个 HelloController控制器。 HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.louis.springboot.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; /* 类注解 */ @Api(value = "desc of class") @RestController public class HelloController { /* 方法注解 */ @ApiOperation(value = "desc of method", notes = "") @GetMapping(value="/hello") public Object hello( /* 参数注解 */ @ApiParam(value = "desc of param" , required=true ) @RequestParam String name) { return "Hello " + name + "!"; } } |
编译运行测试 1. 右键项目 -> Run as -> Maven install,开始执行Maven构建,第一次会下载Maven依赖,可能需要点时间,如果出现如下信息,就说明项目编译打包成功了。 2. 右键文件 DemoApplication.java -> Run as -> Java Application,开始启动应用,当出现如下信息的时候,就说明应用启动成功了,默认启动端口是8080。 3. 打开浏览器,访问:http://localhost:8080/swagger-ui.html,进入swagger接口文档界面。 4. 展开hello-controller的hello接口,输入参数并点击执行,就可以看到接口测试结果了。 常用注解说明 swagger 通过注解接口生成文档,包括接口名,请求方法,参数,返回信息等。 @Api: 修饰整个类,用于controller类上 @ApiOperation: 描述一个接口,用户controller方法上 @ApiParam: 单个参数描述 @ApiModel: […]
View DetailsSpring Boot:整合Spring Security
综合概述 Spring Security 是 Spring 社区的一个顶级项目,也是 Spring Boot 官方推荐使用的安全框架。除了常规的认证(Authentication)和授权(Authorization)之外,Spring Security还提供了诸如ACLs,LDAP,JAAS,CAS等高级特性以满足复杂场景下的安全需求。另外,就目前而言,Spring Security和Shiro也是当前广大应用使用比较广泛的两个安全框架。 Spring Security 应用级别的安全主要包含两个主要部分,即登录认证(Authentication)和访问授权(Authorization),首先用户登录的时候传入登录信息,登录验证器完成登录认证并将登录认证好的信息存储到请求上下文,然后再进行其他操作,如在进行接口访问、方法调用时,权限认证器从上下文中获取登录认证信息,然后根据认证信息获取权限信息,通过权限信息和特定的授权策略决定是否授权。 本教程将首先给出一个完整的案例实现,然后再分别对登录认证和访问授权的执行流程进行剖析,希望大家可以通过实现案例和流程分析,充分理解Spring Security的登录认证和访问授权的执行原理,并且能够在理解原理的基础上熟练自主的使用Spring Security实现相关的需求。 实现案例 接下来,我们就通过一个具体的案例,来讲解如何进行Spring Security的整合,然后借助Spring Security实现登录认证和访问控制。 生成项目模板 为方便我们初始化项目,Spring Boot给我们提供一个项目模板生成网站。 1. 打开浏览器,访问:https://start.spring.io/ 2. 根据页面提示,选择构建工具,开发语言,项目信息等。 3. 点击 Generate the project,生成项目模板,生成之后会将压缩包下载到本地。 4. 使用IDE导入项目,我这里使用Eclipse,通过导入Maven项目的方式导入。 添加相关依赖 清理掉不需要的测试类及测试依赖,添加 Maven 相关依赖,这里需要添加上web、swagger、spring security、jwt和fastjson的依赖,Swagge和fastjson的添加是为了方便接口测试。 pom.xml
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.louis.springboot</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <!-- spring security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- jwt --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <!-- 打包时拷贝MyBatis的映射文件 --> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/sqlmap/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> <filtering>true</filtering> </resource> </resources> </build> </project> |
添加相关配置 1.添加swagger 配置 添加一个swagger 配置类,在工程下新建 config 包并添加一个 SwaggerConfig 配置类,除了常规配置外,加了一个令牌属性,可以在接口调用的时候传递令牌。 SwaggerConfig.java
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 |
package com.louis.springboot.demo.config; import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Parameter; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi(){ // 添加请求参数,我们这里把token作为请求头部参数传入后端 ParameterBuilder parameterBuilder = new ParameterBuilder(); List<Parameter> parameters = new ArrayList<Parameter>(); parameterBuilder.name("Authorization").description("令牌").modelRef(new ModelRef("string")).parameterType("header") .required(false).build(); parameters.add(parameterBuilder.build()); return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()).build().globalOperationParameters(parameters); } private ApiInfo apiInfo(){ return new ApiInfoBuilder() .title("SpringBoot API Doc") .description("This is a restful api document of Spring Boot.") .version("1.0") .build(); } } |
加了令牌属性后的 Swagger 接口调用界面,会多出一个令牌参数,在发起请求的时候一起发送令牌。 2.添加跨域 配置 添加一个CORS跨域配置类,在工程下新建 config 包并添加一个 CorsConfig配置类。 CorsConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.louis.springboot.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 允许跨域访问的路径 .allowedOrigins("*") // 允许跨域访问的源 .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允许请求方法 .maxAge(168000) // 预检间隔时间 .allowedHeaders("*") // 允许头部设置 .allowCredentials(true); // 是否发送cookie } } |
安全配置类 下面这个配置类是Spring Security的关键配置。 在这个配置类中,我们主要做了以下几个配置: 1. 访问路径URL的授权策略,如登录、Swagger访问免登录认证等 2. 指定了登录认证流程过滤器 JwtLoginFilter,由它来触发登录认证 3. 指定了自定义身份认证组件 JwtAuthenticationProvider,并注入 UserDetailsService 4. 指定了访问控制过滤器 JwtAuthenticationFilter,在授权时解析令牌和设置登录状态 5. 指定了退出登录处理器,因为是前后端分离,防止内置的登录处理器在后台进行跳转 WebSecurityConfig.java
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 |
package com.louis.springboot.demo.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; import com.louis.springboot.demo.security.JwtAuthenticationFilter; import com.louis.springboot.demo.security.JwtAuthenticationProvider; import com.louis.springboot.demo.security.JwtLoginFilter; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { // 使用自定义登录身份认证组件 auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService)); } @Override protected void configure(HttpSecurity http) throws Exception { // 禁用 csrf, 由于使用的是JWT,我们这里不需要csrf http.cors().and().csrf().disable() .authorizeRequests() // 跨域预检请求 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 登录URL .antMatchers("/login").permitAll() // swagger .antMatchers("/swagger**/**").permitAll() .antMatchers("/webjars/**").permitAll() .antMatchers("/v2/**").permitAll() // 其他所有请求需要身份认证 .anyRequest().authenticated(); // 退出登录处理器 http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()); // 开启登录认证流程过滤器 http.addFilterBefore(new JwtLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class); // 访问控制时登录状态检查过滤器 http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class); } @Bean @Override public AuthenticationManager authenticationManager() throws Exception { return super.authenticationManager(); } } |
登录认证触发过滤器 JwtLoginFilter 是在通过访问 /login 的POST请求是被首先被触发的过滤器,默认实现是 UsernamePasswordAuthenticationFilter,它继承了 AbstractAuthenticationProcessingFilter,抽象父类的 doFilter 定义了登录认证的大致操作流程,这里我们的 JwtLoginFilter 继承了 UsernamePasswordAuthenticationFilter,并进行了两个主要内容的定制。 1. […]
View Detailsspringboot捕获全局异常和配置多数据源
捕获全局异常是在项目运行期间如果调用的某一个方法出现了运行时异常,则会捕获,并且给出回馈。 首先需要建一个包,包里新建一个捕获异常类GlobalExceptionHandler。前提是springboot的启动类的扫描注解ComponentScan()要扫描到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * 用于捕获全局异常 */ @ControllerAdvice//控制器切面 public class GlobalExceptionHandler { @ExceptionHandler(RuntimeException.class)//捕获运行时异常 @ResponseBody public Map<String,Object> exceptionHandler(){//处理异常方法 Map<String,Object> map=new HashMap<String, Object>(); map.put("errorCode","101"); map.put("errorMsg","系统错误!"); return map; } } |
这个捕获异常类可以捕获到全局的运行时异常,例如商城购物车的控制层一个方法出现异常,黄色背景的是重点,会发生异常。
1 2 3 4 5 6 7 |
@RequestMapping("getShoppingCar") public String getShoppingCar(HttpSession session,Model model){ Map<Integer,Cart> cartMap =(Map<Integer,Cart>)session.getAttribute("cartMap"); model.addAttribute("carList",cartMap); int i=1/0; return "udai_shopcart"; } |
然后启动项目,进入主页,当点击购物车按钮时也就是调用了getShoppingCar这个方法,发生了异常,运行结果是跳转页面失败,直接给出异常信息,也就是全局捕获异常类中设置的信息。 配置多数据源# 以前是在applicationContext.xml中配置的,现在springboot通过注解来配置数据源。 首先在application.properties配置文件中加入多数据源配置。
1 2 3 4 5 6 7 8 9 |
spring.datasource.test1.url=jdbc:mysql://127.0.0.1:3306/test1?serverTimezone=UTC spring.datasource.test1.username=root spring.datasource.test1.password=1234 spring.datasource.test1.driverClassName=com.mysql.cj.jdbc.Driver spring.datasource.test2.url=jdbc:mysql://127.0.0.1:3306/test2?serverTimezone=UTC spring.datasource.test2.username=root spring.datasource.test2.password=1234 spring.datasource.test2.driverClassName=com.mysql.cj.jdbc.Driver |
在例子开始之前,首先去创建两个用于测试的数据库test1和test2,并且新建两张空表。 写两个数据源的配置类。# 在java文件夹下新建dataSource包,新建数据源配置类DataSource01和DataSource02。
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 |
@Configuration//注解到springboot容器中 @MapperScan(basePackages="com.gyf.test1.mapper",sqlSessionFactoryRef="test1SqlSessionFactory") public class DataSource01 { /** * @return 返回test1数据库的数据源 */ @Bean(name="test1DataSource") @Primary//主数据源,一个应用只能有一个主数据源 @ConfigurationProperties(prefix="spring.datasource.test1") public DataSource dateSource(){ return DataSourceBuilder.create().build(); } /** * @return 返回test1数据库的会话工厂 */ @Bean(name = "test1SqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("test1DataSource") DataSource ds) throws Exception{ SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(ds); return bean.getObject(); } /** * @return 返回test1数据库的事务 */ @Bean(name = "test1TransactionManager") @Primary//主事务 public DataSourceTransactionManager transactionManager(@Qualifier("test1DataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } /** * @return 返回test1数据库的会话模版 */ @Bean(name = "test1SqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate( @Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } } |
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 |
@Configuration//注解到springboot容器中 @MapperScan(basePackages="com.gyf.test2.mapper",sqlSessionFactoryRef="test2SqlSessionFactory") public class DataSource02 { /** * @return 返回test2数据库的数据源 */ @Bean(name="test2DataSource") @ConfigurationProperties(prefix="spring.datasource.test2") public DataSource dateSource(){ return DataSourceBuilder.create().build(); } /** * @return 返回test2数据库的会话工厂 */ @Bean(name = "test2SqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("test2DataSource") DataSource ds) throws Exception{ SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(ds); return bean.getObject(); } /** * @return 返回test2数据库的事务 */ @Bean(name = "test2TransactionManager") public DataSourceTransactionManager transactionManager(@Qualifier("test2DataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } /** * @return 返回test2数据库的会话模版 */ @Bean(name = "test2SqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate( @Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } } |
在java文件夹下分别创建两个文件夹test1和test2,分别对这两个数据库进行操作,启动类都需要先扫描到test1和test2的包
1 2 3 4 5 6 7 8 9 10 |
@EnableAutoConfiguration @ComponentScan(basePackages = {"com.gyf.datasource","com.gyf.web","com.gyf.test1.service","com.gyf.test2.service"}) public class App { public static void main( String[] args ) { //启动springboot项目 SpringApplication.run(App.class,args); } } |
Test1的userMapper
1 2 3 4 |
public interface UserMapper { @Insert("insert user (username,password) values (#{username},#{password})") public int save(@Param("username") String username, @Param("password") String password); } |
Test1的UserServiceImpl
1 2 3 4 5 6 7 8 9 |
@Service @Transactional public class UserServiceImpl{ @Autowired private UserMapper userMapper; public void register(String username, String password) { userMapper.save(username,password); } } |
Test2的CustomerMapper
1 2 3 4 5 |
public interface CustomerMapper { @Insert("insert customer (name,tel) values (#{name},#{tel})") public int save(@Param("name") String name, @Param("tel") String tel); } |
Test2的CustomerServiceImpl
1 2 3 4 5 6 7 8 9 |
@Service @Transactional public class CustomerServiceImpl { @Autowired private CustomerMapper customerMapper; public void save(String name, String tel) { customerMapper.save(name,tel); } } |
最后写一个controller类,调用这两个service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@RestController //声明Rest风格的控制器 //@EnableAutoConfiguration //自动配置,相当于写了spring的配置文件 @RequestMapping("user") public class UserController { @Autowired private UserServiceImpl userService; @Autowired private CustomerServiceImpl customerService; @RequestMapping("register") @ResponseBody public String register(String username,String password){ //把数据保存到test1数据库 userService.register(username,password); //把数据保存到test2数据库 customerService.save(username,"120"); return "success"; } } |
启动项目,看数据库表内容,两张表都插入了信息。 from:https://www.cnblogs.com/fantongxue/p/12443377.html
View DetailsMySQL 错误1418 的原因分析及解决方法
具体错误: 使用mysql创建、调用存储过程,函数以及触发器的时候会有错误符号为1418错误。 [Err] 1418 – This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable) 查阅相关资料,意思是说binlog启用时,创建的函数没有声明类型,因为binlog在主从复制需要知道这个函数创建语句是什么类型,否则同步数据会有不一致现象。 mysql开启了bin-log, 我们就必须指定我们的函数是否是哪种类型: 1 DETERMINISTIC 不确定的 2 NO SQL 没有SQl语句,当然也不会修改数据 3 READS SQL DATA 只是读取数据,当然也不会修改数据 4 MODIFIES SQL DATA 要修改数据 5 CONTAINS SQL 包含了SQL语句 为了解决这个问题,MySQL强制要求: 在主服务器上,除非子程序被声明为确定性的或者不更改数据,否则创建或者替换子程序将被拒绝。这意味着当创建一个子程序的时候,必须要么声明它是确定性的,要么它不改变数据。 声明方式有两种: 第一种:声明是否是确定性的 DETERMINISTIC和NOT DETERMINISTIC指出一个子程序是否对给定的输入总是产生同样的结果。 如果没有给定任一特征,默认是NOT DETERMINISTIC,所以必须明确指定DETERMINISTIC来声明一个子程序是确定性的。 这里要说明的是:使用NOW() 函数(或它的同义)或者RAND() 函数不会使一个子程序变成非确定性的。对NOW()而言,二进制日志包括时间戳并会被正确的执行。RAND()只要在一个子程序内被调用一次也可以被正确的复制。所以,可以认为时间戳和随机数种子是子程序的确定性输入,它们在主服务器和从服务器上是一样的。 第二种:声明是否会改变数据 CONTAINS SQL, NO SQL, READS SQL DATA, MODIFIES SQL用来指出子程序是读还是写数据的。 无论NO SQL还是READS SQL DATA都指出,子程序没有改变数据,但是必须明确地指定其中一个,因为如果任何指定,默认的指定是CONTAINS SQL。 默认情况下,如果允许CREATE PROCEDURE 或CREATE […]
View Details