springboot第48集:【思维导图】地图,面向对象,异常,功能代码

在Spring Boot中,可以通过编写拦截器(Interceptor)来对请求进行拦截与处理。下面是一个简单的拦截器实现示例:

  1. 创建一个类并实现HandlerInterceptor接口

public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在请求处理之前进行拦截处理String token = request.getHeader("Authorization");if (StringUtils.isEmpty(token)) {// 如果请求头中没有携带token,则返回错误信息response.setContentType("application/json;charset=UTF-8");response.getWriter().write("{"code":401,"msg":"未授权访问"}");return false;}// 如果token验证通过,则放行return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 请求处理之后进行拦截处理}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 请求完成之后进行拦截处理}
}
  1. 在Spring Boot配置类中注册拦截器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {/*** 注册拦截器*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册AuthInterceptor拦截器,并设置拦截路径为/api/**registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**");}}

在上面的示例代码中,我们编写了一个名为AuthInterceptor的拦截器,对所有以/api/开头的请求进行拦截,并进行token验证。如果token验证不通过,则返回错误信息,否则放行。

接着,在Spring Boot的配置类WebMvcConfig中,我们通过重写addInterceptors方法来注册AuthInterceptor拦截器,并将其设置拦截路径为/api/。

需要注意的是,在拦截器中可能会有一些资源需要释放,例如数据库连接等,这时可以在afterCompletion方法中进行资源释放操作。

springboot写验证器

在Spring Boot中,可以通过编写验证器(Validator)来对表单数据进行校验。下面是一个简单的验证器实现示例:

  1. 创建一个类并实现Validator接口

public class UserValidator implements Validator {/*** 判断当前支持的验证类型*/@Overridepublic boolean supports(Class<?> clazz) {return User.class.equals(clazz);}/*** 执行具体的验证逻辑*/@Overridepublic void validate(Object target, Errors errors) {User user = (User) target;if (StringUtils.isEmpty(user.getUsername())) {// 如果用户名为空,则添加错误信息errors.rejectValue("username", "username.empty");}if (StringUtils.isEmpty(user.getPassword())) {// 如果密码为空,则添加错误信息errors.rejectValue("password", "password.empty");}}
}
  1. 在Controller中使用验证器进行表单校验

@RestController
@RequestMapping("/api")
public class UserController {/*** 使用UserValidator验证表单数据*/@PostMapping("/login")public ResponseEntity<String> login(@Validated @RequestBody User user, BindingResult result) {if (result.hasErrors()) {// 如果表单数据不符合要求,则返回错误信息StringBuilder sb = new StringBuilder();result.getAllErrors().forEach(error -> sb.append(error.getDefaultMessage()).append(";"));return ResponseEntity.badRequest().body(sb.toString());}// 如果表单数据验证通过,则进行登录操作// ...return ResponseEntity.ok("登录成功");}
}

在上面的示例代码中,我们创建了一个名为UserValidator的验证器,并在其中实现了对User对象中的username和password字段进行非空校验的逻辑。

接着,在Controller中的login方法中,我们使用@Validated注解将User对象标记为需要进行表单验证的对象,并将BindingResult对象作为参数传入。在方法中先判断BindingResult对象是否存在错误信息,如果存在则说明表单数据不符合要求,返回相应的错误信息;否则说明表单数据验证通过,进行登录操作。

需要注意的是,在使用@Validated注解时需要在Controller类上添加@Validated注解,以启用Spring Boot的表单验证机制。

springboot写权限拦截

在Spring Boot中,可以通过编写拦截器(Interceptor)来对请求进行权限拦截。下面是一个简单的权限拦截器实现示例:

  1. 创建一个类并实现HandlerInterceptor接口

public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在请求处理之前进行权限拦截处理String token = request.getHeader("Authorization");if (StringUtils.isEmpty(token)) {// 如果请求头中没有携带token,则返回错误信息response.setContentType("application/json;charset=UTF-8");response.getWriter().write("{"code":401,"msg":"未授权访问"}");return false;}// 获取用户权限,并与当前请求的URL进行比对String permission = getUserPermission(token);String requestUrl = getRequestUrl(request);if (!hasPermission(permission, requestUrl)) {// 如果用户没有访问此URL的权限,则返回错误信息response.setContentType("application/json;charset=UTF-8");response.getWriter().write("{"code":403,"msg":"无权访问"}");return false;}// 如果权限验证通过,则放行return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 请求处理之后进行拦截处理}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 请求完成之后进行拦截处理}/*** 获取用户权限*/private String getUserPermission(String token) {// 根据token获取用户信息,包括用户权限// ...return "admin,user";}/*** 判断用户是否有访问此URL的权限*/private boolean hasPermission(String permission, String requestUrl) {// 将用户权限字符串转换为数组,便于比对String[] permissions = permission.split(",");for (String p : permissions) {if (AntPathMatcher.match(p, requestUrl)) {return true;}}return false;}/*** 获取请求的URL*/private String getRequestUrl(HttpServletRequest request) {String url = request.getRequestURI();String contextPath = request.getContextPath();return url.replaceFirst(contextPath, "");}
}
  1. 在Spring Boot配置类中注册拦截器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {/*** 注册拦截器*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册AuthInterceptor拦截器,并设置拦截路径为/api/**registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**");}}

在上面的示例代码中,我们编写了一个名为AuthInterceptor的拦截器,对所有以/api/开头的请求进行权限拦截。在拦截器中,我们先获取请求头中携带的token,并根据该token获取到当前用户对应的权限信息。

接着,我们将用户权限字符串转换为数组,遍历数组并使用AntPathMatcher工具类对用户权限和当前请求的URL进行比对,判断用户是否有访问此URL的权限。如果用户没有访问此URL的权限,则返回错误信息;否则说明权限验证通过,放行。

需要注意的是,在使用AntPathMatcher对URL进行比对时,可以使用通配符***,其中*匹配任意字符,匹配任意多级目录。例如:

  • /api/user/* 匹配 /api/user/list、/api/user/add 等URL;

  • /api/user/** 匹配 /api/user/list、/api/user/detail/1 等URL。

springboot写短信发送

在Spring Boot中,可以通过调用第三方短信服务商提供的接口来实现短信发送功能。下面以阿里云短信服务为例,展示如何在Spring Boot中实现短信发送功能。

  1. 添加依赖

在pom.xml文件中添加阿里云SDK依赖:

<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.0</version>
</dependency>
<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId><version>1.0.0</version>
</dependency>
  1. 添加配置

在application.yml文件中添加阿里云短信服务的相关配置信息:

aliyun:access-key-id: <your-access-key-id>access-key-secret: <your-access-key-secret>sms:sign-name: <your-sms-sign-name>template-code: <your-sms-template-code>

需要将上面的 <your-access-key-id><your-access-key-secret><your-sms-sign-name><your-sms-template-code> 分别替换成真正的值。其中,access-key-id 和 access-key-secret 是阿里云账号的访问密钥ID和密钥,sign-name 是在阿里云短信控制台中设置的签名名称,template-code 是在阿里云短信控制台中创建的短信模板ID。

  1. 编写发送短信的代码

在需要发送短信的地方,可以使用以下代码来调用阿里云短信服务的API:

@Autowired
private AliyunSmsConfig smsConfig;public void sendSms(String phone, String code) throws ClientException {// Step 1. 初始化DefaultAcsClientIClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", smsConfig.getAccessKeyId(), smsConfig.getAccessKeySecret());DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");IAcsClient client = new DefaultAcsClient(profile);// Step 2. 构造请求CommonRequest request = new CommonRequest();request.setMethod(MethodType.POST);request.setDomain("dysmsapi.aliyuncs.com");request.setVersion("2017-05-25");request.setAction("SendSms");// Step 3. 设置请求参数request.putQueryParameter("PhoneNumbers", phone);request.putQueryParameter("SignName", smsConfig.getSignName());request.putQueryParameter("TemplateCode", smsConfig.getTemplateCode());request.putQueryParameter("TemplateParam", "{"code":"" + code + ""}");// Step 4. 发送请求并解析响应CommonResponse response = client.getCommonResponse(request);JSONObject object = JSON.parseObject(response.getData());String codeValue = object.getString("Code");if (!StringUtils.equals(codeValue, "OK")) {throw new RuntimeException("短信发送失败:" + object.getString("Message"));}
}

在上面的示例代码中,我们先通过Autowired注解将阿里云短信服务的配置信息注入到smsConfig变量中,然后调用sendSms方法来发送短信。具体步骤如下:

  • Step 1. 初始化DefaultAcsClient:创建一个IAcsClient对象,并传入阿里云账号的访问密钥ID和密钥。

  • Step 2. 构造请求:设置请求的域名、版本号和操作名称。

  • Step 3. 设置请求参数:设置接收短信的手机号码、短信签名、短信模板ID以及短信模板中的变量值。

  • Step 4. 发送请求并解析响应:调用IAcsClient对象的getCommonResponse方法发送请求,并将响应结果转换为JSONObject对象进行解析。如果发送成功,则返回的Code值为OK;否则返回的

e71e43b3a941c2e03921a6ea66b10364.png
image.png
1fe75206f9ce7d38437ca97dd915f25a.png
image.png
d9e7807bbe3ed2675b77a1df205f1288.png
image.png

快捷键

633b1eed40b41a7d679fea97edc9c216.png
image.png
AMapLoader.load({key: "key", // 申请好的Web端开发者Key,首次调用 load 时必填version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15plugins: ["AMap.moveAnimation"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等AMapUI: {// 是否加载 AMapUI,缺省不加载version: "1.1", // AMapUI 版本plugins: [], // 需要加载的 AMapUI ui插件},
const map = new AMap.Map("container", {//设置地图容器idviewMode: "3D", //是否为3D地图模式zoom: 13, //初始化地图级别center: current_position.value, //初始化地图中心点位置mapStyle: "amap://styles/fresh",})
AMap.plugin(["AMap.ToolBar","AMap.Scale","AMap.HawkEye","AMap.Geolocation","AMap.MapType","AMap.MouseTool","AMap.Polyline",],function () {//异步同时加载多个插件// 添加地图插件// map.addControl(new AMap.ToolBar()) // 工具条控件;范围选择控件map.addControl(new AMap.Scale()) // 显示当前地图中心的比例尺// map.addControl(new AMap.HawkEye()) // 显示缩略图// map.addControl(new AMap.Geolocation()) // 定位当前位置// map.addControl(new AMap.MapType()) // 实现默认图层与卫星图,实时交通图层之间切换// 以下是鼠标工具插件const mouseTool = new AMap.MouseTool(map)// mouseTool.rule();// 用户手动绘制折线图,测量距离// mouseTool.measureArea() // 测量面积}
// 实例化点标记const marker = new AMap.Marker({icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",position: current_position.value, // 这里我们通过上面的点击获取经纬度坐标,实时添加标记// 通过设置 offset 来添加偏移量offset: new AMap.Pixel(-26, -54),})
//这里监听标注点的点击事件,触发实现动画效果marker.on("click", function () {animationMove()})marker.setMap(map)// 历史轨迹动画function animationMove() {AMap.plugin("AMap.MoveAnimation", function () {var marker,lineArr = [[116.478935, 39.997761],[116.478939, 39.997825],[116.478912, 39.998549],[116.478912, 39.998549],[116.478998, 39.998555],[116.478998, 39.998555],[116.479282, 39.99856],[116.479658, 39.998528],[116.480151, 39.998453],[116.480784, 39.998302],[116.480784, 39.998302],[116.481149, 39.998184],[116.481573, 39.997997],[116.481863, 39.997846],[116.482072, 39.997718],[116.482362, 39.997718],[116.483633, 39.998935],[116.48367, 39.998968],[116.484648, 39.999861],]var map = new AMap.Map("container", {resizeEnable: true,center: [116.397428, 39.90923],zoom: 17,})marker = new AMap.Marker({map: map,position: [116.478935, 39.997761],icon: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png",offset: new AMap.Pixel(-13, -26),})// 绘制轨迹var polyline = new AMap.Polyline({map: map,path: lineArr,showDir: true,strokeColor: "#28F", //线颜色// strokeOpacity: 1,     //线透明度strokeWeight: 6, //线宽// strokeStyle: "solid"  //线样式})var passedPolyline = new AMap.Polyline({map: map,strokeColor: "#AF5", //线颜色strokeWeight: 6, //线宽})marker.on("moving", function (e: any) {passedPolyline.setPath(e.passedPath)map.setCenter(e.target.getPosition(), true)})map.setFitView()marker.moveAlong(lineArr, {// 每一段的时长duration: 500, //可根据实际采集时间间隔设置// JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置autoRotation: true,})})}}).catch((e) => {console.log(e)})
}
AMapLoader.load({"key": "",              // 申请好的Web端开发者Key,首次调用 load 时必填"version": "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15"plugins": []           // 需要使用的的插件列表,如比例尺'AMap.Scale'等"AMapUI": {             // 是否加载 AMapUI,缺省不加载"version": '1.1',   // AMapUI 缺省 1.1"plugins":[],       // 需要加载的 AMapUI ui插件},"Loca":{                // 是否加载 Loca, 缺省不加载"version": '1.3.2'  // Loca 版本,缺省 1.3.2},
}).then(()=>{window.AMap.xx;window.AMapUI.xx;window.Loca.xx
});

已加载插件:fastestmirror、langpacks、product-id、search-disabled-repos、subscription-manager

此系统未注册到授权服务器。您可以使用 subscription-manager 注册。

仓库 epel 在配置中列出了多次。

Repodata 已超过两周未更新。安装 yum-cron?或运行:yum makecache fast 未安装组文件。

可能需要运行:yum groups mark convert(参见 man yum)

确定最快的镜像
可用的环境组:最小安装计算节点基础设施服务器文件和打印服务器Cinnamon 桌面MATE 桌面基本 Web 服务器虚拟化主机带 GUI 的服务器GNOME 桌面KDE Plasma Workspaces开发和创意工作站
可用的组:备份客户端基本Cinnamon兼容性库控制台互联网工具开发工具电子邮件服务器教育软件电子实验室Fedora 打包工具字体通用桌面图形管理工具图形创建工具硬件监控实用程序Haskell输入法互联网应用程序KDE 桌面LXQt 桌面传统 UNIX 兼容性MATEMilkymist网络基础设施服务器网络工具办公套件和生产力性能工具科学支持安全工具智能卡支持系统管理系统管理工具技术写作TurboGears 应用程序框架Web 服务器Web Servlet 引擎Xfce
3de1dccb208f9ecf00859d3703042092.png
image.png
● sshd.service - OpenSSH server daemonLoaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)Active: active (running) since Wed 2023-08-16 01:44:00 CST; 4 months 21 days agoDocs: man:sshd(8)man:sshd_config(5)Main PID: 1306 (sshd)Tasks: 4Memory: 6.7MCGroup: /system.slice/sshd.service├─ 1306 /usr/sbin/sshd -D├─11566 sshd: root@pts/0├─11824 -bash└─22367 systemctl status sshd
ea5acfaad9bf46e10871e5609ede784d.png
image.png
7a2dab3d1284ac2139cca0201aa5216e.png
image.png
2ac33cdf3e36532ef7441b8a9c5a2996.png
image.png
31350f9c0d37f78681b9bc32c60dae6f.png
image.png
b8ea575992e0dd9e4d9fe70532c5bd1b.png
image.png
132119fbc68e51ae4937dfa329a2797b.png
image.png
f1a186271513a756bd687b1ae10584dd.png
image.png
b553fc4f3430b69e9350b3de437ac197.png
image.png
2dd77f4699162a01fe8c6b4d809a3c46.png
image.png
7c2cb387f9af2f2bf13da8135e6e0901.png
image.png
304cb9cdc9232600450031f02af8b3ed.png
image.png
4964537daff3ad621a9b9bfb0c9a7d71.png
image.png
2fb0b6cc34b92ba453536d13e6dbfec3.png
image.png
b12dbfb7688bfe5a08dbcad1a499feb1.png
image.png
bdc9abac693d8ba21f77c9f3a3a46062.png
image.png
648d0e1b0af6e576bda6417e4cffd535.png
image.png
e684fc2dccd8201b22b69b67a3bac24e.png
image.png
6512bc51e5f7407c4fb193fd3c6a31dc.png
image.png
dd54229806f5a34dcbd9bb97672f3dda.png
image.png
6d00d7ab2244ad307240624f06dbeb28.png
image.png
10efec8bf7ea53d1507f5978377ba06e.png
image.png
779ee6f1fa25a1faa0d882019b09aa71.png
image.png
b519a5b14718458ca542fe22d39d7e6e.png
image.png
9b36bb10e0115180911da0513dd8c20e.png
image.png
e9f8448bf316530e7c6c359447067999.png
image.png
819b54deb748c429712d46c42be5a40f.png
image.png
71cf64f95f285b5cd7715fa88dbb74af.png
image.png
3f133604fa99a7a5be26c4b3c08a01a3.png
image.png

加群联系作者vx:xiaoda0423

仓库地址:https://github.com/webVueBlog/JavaGuideInterview