开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情(juejin.cn/post/716729… "juejin.cn/post/716729…")
1. 自定义日期转换器
- 首先写一个转换日期的util工具类
- 这里边可以转换 yyyy-MM-dd yyyy-MM-dd HH:mm:ss 两种格式的日期
package cn.yufire.wms.util;
import cn.yufire.wms.util.EmptyUtils;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* <p>
* Description: 自定义日期转化器
* </p>
*
* @author yufire
* @version v1.0.0
* @see cn.yufire.wms.config
* @since 2020-05-12 16:27:14
*/
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String str) {
if (EmptyUtils.isEmpty(str) || str.length() <= 0) {
return null;
} else {
Date date = null;
try {
date = new SimpleDateFormat(str.length() > 11 ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd").parse(str);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return date;
}
}
}
- 写一个配置类 继承 WebMvcConfigurerAdapter
- 重写 addFormatters 方法
- 配置日期转换类
package cn.yufire.wms.config;
import cn.yufire.wms.util.DateConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* <p>
* Description: 配置日期转换器
* </p>
*
* @author yufire
* @version v1.0.0
* @see cn.yufire.wms.config
* @since 2020-05-12 16:27:02
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new DateConverter());
}
}
这样就可以实现全局日期转换了!
2. 解决跨域问题
什么是跨域问题 ?
在浏览器端进行不同源的 Ajax 请求时会出现跨域问题,那么什么是跨域,如何解决跨域呢?
什么是同源?
所谓同源是指,域名,协议,端口均相同
- www.yufire.cn--> admin.yufire.cn 跨域
- www.yufire.cn --> www.yufire.cn 非跨域
- www.yufire.cn --> www.yufire.cn:8080 跨域
- www.yufire.cn --> www.yufire.cn 跨域
全局解决跨域
- 写一个配置类
- 在IOC容器中创建一个 Bean WebMvcConfigurer
- 重写 addCorsMappings 方法 并设置参数
package cn.yufire.dining.back.confing;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
* <p>
* Description:跨域请求配置
* </p>
*
* @author yufire
* @version v1.0.0
* @since 2020-03-05 22:43:21
* @see cn.yufire.dining.back.confing
*
*/
@Configuration
public class CORSConfiguration {
//addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。
//allowedMethods:允许所有的请求方法访问该跨域资源服务器,如:POST、GET、PUT、DELETE等。
//allowedOrigins:允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:"http://www.baidu.com",只有百度可以访问我们的跨域资源。
//allowedHeaders:允许所有的请求header访问,可以自定义设置任意请求头信息,如:"X-YAUTH-TOKEN"
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "DELETE", "PUT","PATCH")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
};
}
}
单个Controller解决跨域
- 可以直接使用注解实现
CrossOrigin
package cn.yufire.wms.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "*",maxAge = 3600)
public class TestController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
3.拦截器
- 写一个配置类
- 实现
WebMvcConfigurer - 重写
package cn.yufire.dining.back.confing;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 拦截器
*/
@Configuration
class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册TestInterceptor拦截器
InterceptorRegistration registration = registry.addInterceptor(new AdminInterceptor());
//所有路径都被拦截
registration.addPathPatterns("/**");
// 不拦截请求的数组
String[] excludePaths = {"/index", "/login/adminLogin", "/login", "/**/*.html", "/**/*.js", "/**/*.css", "/**/*.woff", "/**/*.ttf"};
// 不拦截哪些请求
registration.excludePathPatterns(excludePaths);
}
}
- 写一个拦截器类
package cn.yufire.dining.back.confing;
import cn.yufire.dining.back.util.ResultUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 拦截器
*/
class Interceptor implements HandlerInterceptor {
/**
* 转换json的类
*/
private ObjectMapper objectMapper = new ObjectMapper();
/**
* 在请求处理之前进行调用(Controller方法调用之前)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//服务器地址
String strBackUrl = "http://" + request.getServerName()
+ ":"
//端口号
+ request.getServerPort()
//项目名称
+ request.getContextPath()
//请求页面或其他地址
+ request.getServletPath()
//参数
+ "?" + (request.getQueryString());
// 获取请求头信息中的数据
String token = request.getHeader("token");
if (token ** null) {
// return true代表可以往下走
// 反则不可以往下走 可以用下边的方法给前端返回json数据
// 如果是同步请求的话可以直接重定向 或 转发
returnJson(response, "去登陆!!!");
return false;
} else {
return true;
}
}
/**
* 返回给前端的json串 提示用户没有登陆
*
* @param response
* @param msg
* @throws Exception
*/
public void returnJson(HttpServletResponse response, String msg) throws Exception {
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
try {
String msgJson = objectMapper.writeValueAsString(ResultUtil.error(msg));
writer = response.getWriter();
writer.print(msgJson);
} catch (IOException e) {
} finally {
if (writer != null) {
writer.close();
}
}
}
}
4. 获取RestTemplate
- 写一个配置类
package cn.yufire.dining.back.confing;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
/**
*
* <p>
* Description: 获取一个 RestTemplate 对象 放入 IOC容器中
* </p>
*
* @author yufire
* @version v1.0.0
* @since 2020-03-06 12:37:04
* @see cn.yufire.dining.back.confing
*
*/
@Component
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
5. SpringBoot开机启动的类
- 这个类会在SpringBoot项目启动的时候进行加载
- 你可以在 run 方法中执行自己的业务
package cn.yufire.wms.config;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class PowerOnClass implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Spring Boot 启动了");
// 你要干的事情...
}
}
6.SpringBoot异步任务
- SpringBoot异步任务可用于 邮件发送 验证码发送 等等 执行时间较长的任务
- 方法的返回值必须是 void !!!
- 首先在 SpringBoot主类中使用
@EnableAsync注解开启异步任务
package cn.yufire.app;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//开启异步方法
@EnableAsync
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
- 在要使用异步任务的方法上加上
@Async注解即可 - 这边创建了一个 service 模拟真实环境
Service
package cn.yufire.skills.service;
public interface AsyncService {
void asyncTest() throws InterruptedException;
}
ServiceImpl
package cn.yufire.skills.service.impl;
import cn.yufire.skills.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
@Async
@Override
public void asyncTest() throws InterruptedException {
Thread.sleep(3000);
System.out.println("执行完成!");
}
}
Controller
package cn.yufire.skills.controller;
import cn.yufire.skills.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping("/")
public String asyncTest() throws InterruptedException {
asyncService.asyncTest();
return "success";
}
}
- 写好之后打开网页直接访问该接口
- 会发现 该接口会直接给我们返回结果 并没有等待那个 线程睡眠的3秒钟
- 测试结果
7. Thymeleaf的HTML头信息
xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Thymeleaf头信息</title>
</head>
<body>
<span th:text="session.user.usreName"></span>
</body>
</html>
8. JDBC开箱即用
注意
添加了 spring-boot-starter-jdbc 依赖后必须在配置文件中填写数据库连接信息 否则项目启动报错
- 创建SpringBoot项目
- 添加依赖
<!--SpringBoot的Web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot的JDBC依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--MySQL驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
- 添加配置文件
spring:
datasource: # mysql的配置
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://ip:端口/db_name?serverTimezone=Asia/Shanghai
username: root
password: root
- 创建Controller
package cn.yufire.skills.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class JdbcTemplateController {
/**
* Spring为我们高度封装的 jdbc操作模板
*/
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping("/")
public List<Map<String, Object>> getUsers() {
String sql = "select * from jy_user";
// 使用 queryForList 查询出来数据集合
List<Map<String, Object>> users = jdbcTemplate.queryForList(sql);
return users;
}
}
- 测试
- 可以看到数据库的信息已经被我们查询出来了
- 其他的 DML 操作 可以使用
query方法进行
JdbcTemplate模板操作详解 传送门 还没开始写
9. Redis开箱即用
-
创建SpringBoot项目
-
添加依赖
<!--SpringBoot的Web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot的Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置文件添加Reids信息
spring:
redis:
database: 0
host: 192.168.244.106
port: 6379
password: root
- 创建 Controller
package cn.yufire.skills.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RedisTemplateController {
/**
* Spring为我们封装的 redis操作摸板
*/
@Autowired
private RedisTemplate<String, String> redisTemplate;
@GetMapping("/get/{key}")
public String getKey(@PathVariable("key") String key) {
return redisTemplate.opsForValue().get(key);
}
@GetMapping("/set")
public String getKey(String key, String value) {
redisTemplate.opsForValue().set(key, value);
return "success";
}
}
- 测试 结果
10. 自定义页面映射
- 创建配置类
package cn.yufire.skills.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
/**
* <p>
* Description: Web访问路径配置类
* </p>
*
* @author yufire
* @version v1.0.0
* @see cn.yufire.skills.config
* @since 2020-05-12 19:45:42
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
// 你要访问的路径 : 真实的页面
// 页面位于 templates下
registry.addViewController("/").setViewName("index");
// 可以添加多个
//registry.addViewController("/").setViewName("index");
}
}
- 启动项目 测试
11. SpringBoot中的事务
package cn.yufire.jysong.service.impl;
@Service
// 也可也放在类上
//@Transactional
public class Song_KuGouServiceImpl extends CommonClass implements Song_KuGouService {
@Autowired
private JySongInfoKgMapper kgMapper;
@Autowired
private JySongLyricKgMapper lyricKgMapper;
@Override
// 使用 Transactional注解开启事务
// rollbackFor指定出现哪些异常才进行回滚
// Java中已经定义的异常可以不指定 如果是自定义的异常需要指定
@Transactional(rollbackFor = Exception.class)
public JySongInfoWyy addSongInfo(JySongInfoWyy jySongInfoWyy) {
return null;
}
}
@Transactional注解 配置说明
| 属性名 | 说明 |
|---|---|
| name | 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。 |
| propagation | 事务的传播行为,默认值为 REQUIRED。 |
| isolation | 事务的隔离度,默认值采用 DEFAULT。 |
| timeout | 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
| read-only | 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。 |
| rollback-for | 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。 |
| no-rollback- for | 抛出 no-rollback-for 指定的异常类型,不回滚事务。 |
12. SpringBoot多环境配置
- 在resources下创建 application-dev.yml 或 application-xxx-yml
- 在主配置文件中激活
spring:
profiles:
active: dev # 该 dev 就是 application-dev.yml
作者:yufire © yufirem@vip.qq.com