Spring开发指南是Spring官方提供的Spring技术的入门级学习指南,内容主题全面覆盖了Spring技术栈,每篇指南都遵循一套标准化的学习流程,从新手入门到专题介绍,从基础概念介绍到编码实战,即使你什么都不会,也可以从零开始跟着文档一步步完成编码,最终完成学习这并不是一件难事,在每个指南中同时提供了多种主流构建方式(Maven、Gradle、IDE),项目完整的源代码放在Github上可下载,内容与最新版本同步更新,有很好的学习借鉴和指导性,作为初学者的技术入门和了解新技术都是不错的必备之选。
如果有人问我推荐什么资料,我一定首先推荐官方的开发指南,再配合各个框架参考文档,作为入门学习已经足够了。但是让很多人望而却步的是“看着一大篇英文就头疼”,这的确是个问题,这需要一边写着代码还得一边在线翻译资料。作为一个专业的软件开发人,这似乎是必经之路,无论你走过多少路都得回到开始的地方,源代码和参考文档就是那个“最初的地方”。当然,我也能理解,学习一门英语也非“一朝一夕之事”。
关于Spring开发指南
Spring开发指南分为三个类型,
快速入门(Getting Started Guides),适合新手入门,一般是使用Spring技术来构建诸如“Hello World”的简单示例,你学习时间在15到30分钟
专题指南(Topical Guides),比新手入门的内容广泛,带有独特观点的技术讲解,适合全面的理解技术和框架的架构设计,学习时间在一个小时左右
学习教程(Tutorials),更加深度和主题的企业级应用开发,提供现实世界复杂问题的解决方案,学习时间在2到3小时
在新手入门阶段,往往需要提前了解一些基础知识和概念,这些知识有助于理解所学内容和顺利完成学习任务。比如,JSON、REST、POJO、JavaScript、Tomcat等,除此之外,还需要会安装一些常用Java相关开发工具,比如Java SDK、Git、STS等,这些都会在开发中经常用到。
目前已经提供的快速入门,已有发布有69篇,涵盖主题有前端(jQuery、AngularJS、Vaadin)、工具(Maven、Gradle、STS、IntelliJ IDEA.)、数据(MySQL、JPA、Redis、MongoDB、 Neo4j)、消息与服务(JMS、Web Service)、云(Google Cloud、Cloud Foundry、网关、配置管理)、测试、安全等等,已经相当全面了。而专题方面则只有一篇是关于Spring Security的,这个我目前正在写一些有关的文章。教程方面目前也有5篇,仍然有更多可完善的内容,尤其是关于Spring Cloud方面比较缺乏。
Spring日常开发使用技巧
通用注解
@Component
@Configuration
dao层
@Repository
service 层
@Service
controller 类的:
1. @Controller
2. @RestController = @Controller + @ResponseBody
3. 通知类,切面编程,其实就是给@RequestMapping 上加了多元注解,
@ControllerAdvice(assignableTypes = {
MyController.class})
内部常用注解
3.1 @ExceptionHandler({
Throwable.class})
@ExceptionHandler({
Throwable.class})
public ResponseEntity<String> res(Throwable throwable){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(throwable.getMessage());
}
3.2 @ModelAttribute("acceptLanguage")
@ModelAttribute
public void addAttribute(Model model) {
model.addAttribute("attribute", "The Attribute");
}
3.3 @CookieValue
3.4 @InitBinder : 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器 ,比如:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
3.5 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 返回状态
4. @RequestMapping
5. ResponseEntity 对象
注入属性
@Data
@ConfigurationProperties(prefix = "anthony")
public class MyProperties {
@value(${
"anthony.name"})
String name;
String age;
String info;
//在对象初始化之后立 马执行
@PostConstruct
public void doFirst() {
System.out.println("name = " + name);
System.out.println("age = " + age);
System.out.println("info = " + info);
this.info = "modify";
}
}
// 如果不用EnableConfigurationProperties 需要将MyProperties加上一个@Configuration最好
@EnableConfigurationProperties(MyProperties.class)
@RestController
public class MyController {
@Autowired
MyProperties properties;
}
单元测试类
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringValidatorApplicationTests {
@Test
@After
@Before
public void test(){
}
}
validate 数据校验
@Data
public class MYData {
@NotNull(message = "状态不能为空")
@Min(value = 18,groups = Adult.class)
@PositiveOrZero(message = "正数或者0")
private Integer age;
public interface Adult{
}
public interface Minor{
}
}
@RequestMapping("/live")
public String live(@Validated({
MYData.Adult.class}) MYData foo, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
for (FieldError fieldError : bindingResult.getFieldErrors()) {
//...
}
return "fail";
}
return "success";
}
@NotBlank
@NotEmpty
@NotNull(message = "状态不能为空")
@Min(value = 18,message = "错了")
@PositiveOrZero(message = "正数或者0")
@Validated({
MYData.Adult.class}) 只会对 groups标记的做校验 其他不会进行 ,所以要么你注意一点
@Valid 不可以进行分组检测
BindingResult 可以获取失败结果
aop
1. 自定义log注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
String value() default "";
}
2. 自定义 log aop 类
@Aspect
@Component
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
// 可以将 加上 @log 注解的类 环绕通知
@Pointcut("@annotation(com.spring.springvalidator.aop.Log)")
public void logPointCut() {
}
//环绕通知
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
Object result =null;
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("doBefore : 请求地址 : " + request.getRequestURL().toString());
logger.info("doBefore : HTTP METHOD : " + request.getMethod());
logger.info("doBefore : CLASS_METHOD : " + point.getSignature().getDeclaringTypeName() + "."
+ point.getSignature().getName());
// 执行方法
result = point.proceed();
logger.info("doBefore : 方法参数 : " + Arrays.toString(point.getArgs()));
logger.info("doBefore : 方法返回值 : " + result);
logger.info("doAfterReturning");
return result;
} catch (Exception e) {
logger.error("doAfterThrowing : {} ", e.getMessage());
throw new RuntimeException("runtime exception");
} finally {
logger.info("doAfter");
}
}
@Aspect
@Component
public class WebLogAspect2 {
private static final Logger logger = LoggerFactory.getLogger(WebLogAspect2.class);
//切点
//两个..代表所有子目录,最后括号里的两个..代表所有参数
@Pointcut("execution( * com.spring.springvalidator.web.*.*(..))")
public void logPointCut() {
}
//前置通知
@Before("logPointCut()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
logger.info("doBefore");
}
// 成功返回
@AfterReturning("logPointCut()")
public void doAfterReturning(JoinPoint joinPoint){
logger.info("doAfterReturning");
}
// 失败返回
@AfterThrowing("logPointCut()")
public void doAfterThrowing(JoinPoint joinPoint){
logger.info("doAfterThrowing");
}
//前置通知
@After("logPointCut()")
public void doAfter(JoinPoint joinPoint){
logger.info("doAfter");
}
}
执行顺序 一般是 :
doBefore do(controller) doAfter doAfterReturning\doAfterThrowing
或者 环绕通知,
@Around("logPointCut()")
public Object aroundLog(ProceedingJoinPoint pjp) {
Object reValue = null;
try {
// 请求参数 :
Object[] args = pjp.getArgs();
logger.info("doBefore");
reValue = pjp.proceed(args);
logger.info("成功返回值 : {} ", reValue);
logger.info("doAfterReturning");
return reValue;
} catch (Throwable throwable) {
logger.info("doAfterThrowing");
throw new RuntimeException(throwable);
} finally {
logger.info("doAfter");
}
}
doBefore doAfterReturning/doAfterThrowing doAfter
拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
/** * 添加拦截器 * @param registry */
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 设置
System.out.println("前置拦截1");
return true;
}
});
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 设置
System.out.println(handler);
System.out.println("前置拦截2");
response.setStatus(400);
return false;
}
});
}
}
学习建议
如果是刚接触到Spring技术,建议先从新手入门学起,先跟着示例一步一步将代码完成,这样会有个基本认识,如果有不清楚的地方可以先查找Spring框架对应的参考文档。目前的大部分例子都是直接使用Spring Boot进行开发的,这一开始会让你觉得它很简单快速,少量的代码和少量的配置就能立即运行起来,这对于初学者其实是一种诱惑,久而久之会造成一种错觉,认为简单是理所当然的。如果这样去想,后面必定会吃亏踩坑导致心理上受挫。
Spring的项目越来越多,各个框架之间的整合和依赖也越来越密切。自动装配会减少配置,但也让配置变得无处不在(条件和规则只是隐藏在代码之中),出错之后定位和解决的难度增加。各种starters只是屏蔽了第三方项目的直接依赖,但是这种依赖依然存在,你仍然需要知道依赖的是什么。所以在学习的过程中,还是要学习其他框架和库,了解它们仍然很有必要。
最基础的技术比如Java EE的一些规范,Spring Framework等等,还有部分人认为会Spring Boot、Spring Cloud就不需要学习Spring Framework,这当然是不对的。在领进门之后,剩下的是需要时间,在不断的项目实战和学习摸索中领悟“The Spring Way”!
文档和代码下载使用
目前,官方的开发指南文档和代码都托管在Github上,所有的代码遵守ASLv2,而所有的文档遵守Attribution, NoDerivatives creative commons license,任何人都可以阅读、下载包括分发,但是禁止演绎,也就是不允许修改和翻译。
如果觉得本文对你有帮助,可以转发关注支持一下