我是靠谱客的博主 含糊柜子,最近开发中收集的这篇文章主要介绍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文件会报错,报错内容如下:
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 即可。
F:javaProjectNewdemo>mvn compile

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


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

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

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)全局异常处理

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连接点注解类)

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切面

@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()调用了目标方法,并获取其返回值;
  • 如果需要对某一方法进行增强,只需要在相应的方法上添加上此注解即可,如下:
    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注解类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
public @interface LoginLog {
}

2)日志切点类

@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)切入点

@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 Boot 系列(1) :初步认识、异常处理、AOP切面所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部