我是靠谱客的博主 含糊柜子,这篇文章主要介绍Spring Boot 系列(1) :初步认识、异常处理、AOP切面,现在分享给大家,希望可以做个参考。

1、从官网下载demo
1)网址:http://start.spring.io
2)可选择Maven/Gradle+Java+版本
3)Group填组名、Artifact填模块名、右侧Dependencies可以选择相应的依赖,因为我们要构建web项目,所以可以添加web的依赖

4)点击 Generate Project 生成下载项目


2、把下载的demo代码导入eclipse或者ide中,直接运行 DemoApplication.java 的main方法。
在eclipse导入后可能pom文件会报错,报错内容如下:
复制代码
1
2
3
4
Project build error: Non-resolvable parent POM for com.example.hs:demo:0.0.1-SNAPSHOT: Failure to transfer org.springframework.boot:spring-boot-starter-parent:pom: 2.0.3.RELEASE from https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced. Original error: Could not transfer artifact org.springframework.boot:spring-boot-starter-parent:pom:2.0.3.RELEASE from/to central (https:// repo.maven.apache.org/maven2): Received fatal alert: protocol_version and 'parent.relativePath' points at no local POM
解决方案:打开终端,进入出错项目的根目录,然后使用 maven bin 目录下的 mvn 编译一下,完成之后右键项目 Maven——Update Project 即可。
复制代码
1
F:javaProjectNewdemo>mvn compile

3、在springboot中配置除了支持application.properties,还支持application.yml的配置方式。


4、异常处理类方式(以权限为例)--springMVC

1)权限错误时抛出此异常

复制代码
1
2
3
4
5
6
7
8
9
10
package com.ex.exception; public class AuthException extends RuntimeException { private static final long serialVersionUID = 1L; public AuthException(final String msg) { super(msg); } public AuthException(final String msg, final Throwable exception) { super(msg, exception); } }

2)全局异常处理

复制代码
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
package com.ex.util; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.ex.exception.AuthException; @ControllerAdvice(annotations = { RestController.class }) public class ExceptionUtil implements ExceptionMapper<Throwable> { private final static Logger LOGGER = LoggerFactory.getLogger(ExceptionUtil.class); @Override public Response toResponse(final Throwable exception) { LOGGER.error("exception:[{}]", exception); return Response.status(Status.BAD_REQUEST).entity(ResponseUtil.errorRes(exception.getMessage())) .type(MediaType.APPLICATION_JSON).build(); } @ExceptionHandler @ResponseStatus(value = HttpStatus.OK) public @ResponseBody ResponseUtil exception(final HttpServletRequest request, final Exception exception) { final ResponseUtil resp = new ResponseUtil(false); final String url = request.getRequestURL().toString(); LOGGER.error("the request is:[{}] and the exception is:[{}]", url, exception); if (exception instanceof AuthException) { resp.setErrorMsg("no permission"); } resp.setErrorMsg(exception.getLocalizedMessage()); return resp; } }

其中核心内容如下:

@ControllerAdvice(annotations = { RestController.class })

  • @ControllerAdvice:对controller做advice(横切通知),配置需要拦截的类。使用 @ControllerAdvice,不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调。这里是指定所有注释了@RestController的controller。它还可以指定特定包下所有的controller例如@ControllerAdvice("org.example.controllers"),也可以指定特定类例如@ControllerAdvice(assignableTypes = {NameListInfoService.class, AbstractController.class})。@ControllerAdvice的实现类能够通过classpath扫描自动检测到。注解了@ControllerAdvice的类可以包含@ExceptionHandler,@InitBinder和@ModelAttribute方法。这些方法能够应用到所有controller结构中的@RequestMapping方法上,而不单是在它所在的类中。
  • @ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度。这里不指明异常类,会自动映射。
  • @ResponseStatus:可以将某种异常映射为HTTP状态码。

3)自定义注解~~(PointCut连接点注解类)

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.ex.anno; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)//定义注解在JVM运行时保留,在运行是通过反射机制获取 @Target(ElementType.METHOD)//定义注解的作用目标**作用范围字段、枚举的常量/方法 @Documented//说明该注解将被包含在javadoc中 public @interface Authorize { public String value() default ""; }

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。

自定义注解的作用:在反射中获取注解,以取得注解修饰的类、方法或属性的相关解释。

4)AOP切面

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Aspect//定义切面 @Component public class AuthAspect { @Autowired private transient AuthBO authBO; //环绕通知:定义@Around增强,pointcut连接点使用@annotation(xxx)定义,其中xxx对应该方法中final Authorize authorize参数authorize @Around(value = "@annotation(authorize)") public Object doAuthorize(final ProceedingJoinPoint joinPoint, final Authorize authorize) throws Throwable { final String value = authorize.value(); if (value != null && !"".equals(value)) { // 调用方法名 final String methodName = value.substring(0, value.indexOf('(')); // 资源编号 final String code = value.substring(value.indexOf(''') + 1, value.lastIndexOf(''')).replaceAll("'", "").replaceAll("\s*", ""); final Boolean flag = new ReflectTask<Boolean>(authBO, methodName, new Class[] { String.class }, new Object[] { code }).call(); if (!flag) { throw new AuthException("权限错误!"); } } return joinPoint.proceed();//调用目标方法 } }
在上面定义@Around增强时,通过@annotation() 方式指定了pointcut,其中方法参数为连接点注解类Authorize;
  • @annotation(around):参数around应该与增强处理方法中的参数名保持一致,该声明指定了pointcut连接点,也可以使用其他方式,如:pointcut="execution(* org.crazyit.app.service.impl.*.*(..))";
  • point.proceed()调用了目标方法,并获取其返回值;
  • 如果需要对某一方法进行增强,只需要在相应的方法上添加上此注解即可,如下:
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package com.ex.service; import org.springframework.stereotype.Component; import com.ex.anno.Authorize; @Component public class LoginService { @Authorize(value="admin")//表示需要对该方法进行@Around增强处理 public String getSomething(){ return "HelloWord"; } }

5、登录日志简单示例

1)自定义LoginLog注解类

复制代码
1
2
3
4
5
6
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @Inherited public @interface LoginLog { }

2)日志切点类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Aspect @Component @ConditionalOnProperty(name = "exsystem.isLog", havingValue = "true") public class LogAspect { @Autowired private transient LogsBO logsBO; private final static Logger LOGGER = LoggerFactory.getLogger(LogAspect.class); @Around(value = "within(cn.ex..*) && @annotation(loginLog)") public Object doLoginLog(final ProceedingJoinPoint joinPoint, final LoginLog loginLog) throws Throwable { // 调用参数 final Object[] args = joinPoint.getArgs(); final Object obj = joinPoint.proceed(args); try { logsBO.writeLoginLog(obj, args); } catch (Exception e) { LOGGER.error("创建登录日志异常,异常信息:{}", e.getMessage()); } return obj; } }

其中SpringBoot通过@ConditionalOnProperty来控制Configuration是否生效,其中name用来从application.yml中读取某个属性值,如果该值为空,则返回false;如果值不为空,则将该值与havingValue指定的值进行比较;

另外通过环绕通知@Around对cn.ex..*包下类以及所有加了LoginLog注解的方法体进行切入拦截,如上代码会进入doLoginLog里进行logsBO.writeLoginLog(obj, args);将登录日志入数据库处理。

3)切入点

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RestController @RequestMapping("/login") public class LoginServerResource { /** * 登录操作 * * @param loginName 用户名 * @param password 密码 * @param checkCode 验证码 * @return */ @LoginLog @RequestMapping(value = "/login", method = { RequestMethod.POST }, consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE }) public ModelAndView login(final @ModelAttribute(value = "loginName") String loginName, final @ModelAttribute(value = "password") String password, final @ModelAttribute(value = "checkCode") String checkCode, final @ModelAttribute(value = "phoneCode") String phoneCode) { return null; } }

通过@LoginLog自定义注解切入。


...

最后

以上就是含糊柜子最近收集整理的关于Spring Boot 系列(1) :初步认识、异常处理、AOP切面的全部内容,更多相关Spring内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部