<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>插件 &#8211; chang的个人博客</title>
	<atom:link href="https://www.qiqin-chang.cn/category/back/%e6%8f%92%e4%bb%b6/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.qiqin-chang.cn</link>
	<description></description>
	<lastBuildDate>Mon, 29 Dec 2025 00:04:43 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.qiqin-chang.cn/wp-content/uploads/2025/04/cropped-无背景-圆形-32x32.png</url>
	<title>插件 &#8211; chang的个人博客</title>
	<link>https://www.qiqin-chang.cn</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WebSocket-全双工通信协议</title>
		<link>https://www.qiqin-chang.cn/websocket-%e5%85%a8%e5%8f%8c%e5%b7%a5%e9%80%9a%e4%bf%a1%e5%8d%8f%e8%ae%ae/</link>
					<comments>https://www.qiqin-chang.cn/websocket-%e5%85%a8%e5%8f%8c%e5%b7%a5%e9%80%9a%e4%bf%a1%e5%8d%8f%e8%ae%ae/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:30:19 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=70</guid>

					<description><![CDATA[依赖： 配置类： websocket服务类： 返回顶部]]></description>
										<content:encoded><![CDATA[
<p>依赖：</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;dependency>
    &lt;groupId>org.springframework.boot&lt;/groupId>
    &lt;artifactId>spring-boot-starter-websocket&lt;/artifactId>
&lt;/dependency></code></pre>



<p>配置类：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">/**
 * WebSocket配置类，用于注册WebSocket的Bean
 */
@Configuration
public class WebSocketConfiguration {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}</code></pre>



<p>websocket服务类：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">/**
 * WebSocket服务
 */
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
​
    //存放会话对象
    private static Map&lt;String, Session> sessionMap = new HashMap();
​
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端：" + sid + "建立连接");
        sessionMap.put(sid, session);
    }
​
    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端：" + sid + "的信息:" + message);
    }
​
    /**
     * 连接关闭调用的方法
     *
     * @param sid
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);
    }
​
    /**
     * 群发
     *
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection&lt;Session> sessions = sessionMap.values();
        System.out.println("发送");
        for (Session session : sessions) {
            try {
                //服务器向客户端发送消息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
​
}</code></pre>



<p><a href="#top">返回顶部</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/websocket-%e5%85%a8%e5%8f%8c%e5%b7%a5%e9%80%9a%e4%bf%a1%e5%8d%8f%e8%ae%ae/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SpringTask-定时任务</title>
		<link>https://www.qiqin-chang.cn/springtask-%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1/</link>
					<comments>https://www.qiqin-chang.cn/springtask-%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:29:21 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=68</guid>

					<description><![CDATA[使用步骤： 与ServiceImpl层相似: 返回顶部]]></description>
										<content:encoded><![CDATA[
<p>使用步骤：</p>



<ul class="wp-block-list">
<li>导入maven坐标：spring-context(已存在)</li>



<li>启动类添加注解：@EnableScheduling //开启任务调度</li>



<li>自定义定时任务类</li>
</ul>



<p>与ServiceImpl层相似:</p>



<pre class="wp-block-code"><code lang="java" class="language-java">/**
 * 定时任务 
 */
@Scheduled(cron = "0/5 * * * * ?") //每隔5秒触发一次
public void execute() {
    log.info("定时任务开始执行：{}",new Date());
}</code></pre>



<p><a href="#top">返回顶部</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/springtask-%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>JWT-令牌加密</title>
		<link>https://www.qiqin-chang.cn/jwt-%e4%bb%a4%e7%89%8c%e5%8a%a0%e5%af%86/</link>
					<comments>https://www.qiqin-chang.cn/jwt-%e4%bb%a4%e7%89%8c%e5%8a%a0%e5%af%86/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:28:17 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=66</guid>

					<description><![CDATA[依赖： 工具包： 旧： 生成Token 获取用户信息： Service层login方法中： 生成token并返 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">依赖：</h2>



<pre class="wp-block-code"><code>&lt;!--JWT 令牌加密--&gt;<br>&lt;dependency&gt;<br> &nbsp; &nbsp;&lt;groupId&gt;com.auth0&lt;/groupId&gt;<br> &nbsp; &nbsp;&lt;artifactId&gt;java-jwt&lt;/artifactId&gt;<br> &nbsp; &nbsp;&lt;version&gt;4.3.0&lt;/version&gt;<br>&lt;/dependency&gt;</code></pre>



<h2 class="wp-block-heading">工具包：</h2>



<h3 class="wp-block-heading">旧：</h3>



<p>生成Token 获取用户信息：</p>



<pre class="wp-block-code"><code>package com.chang.utils;
​
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.chang.entity.Account;
import com.chang.service.impl.AdminServiceImpl;
import com.chang.service.impl.EmployeeServiceImpl;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
​
import java.util.Date;
​
@Component
public class TokenUtils {
​
    @Autowired
    AdminServiceImpl adminService;
    @Autowired
    EmployeeServiceImpl employeeService;
​
    static AdminServiceImpl staticAdminService;
    static EmployeeServiceImpl staticEmployeeService;
​
    //springboot工程启动后会加载这段代码
    @PostConstruct
    public void init(){
        staticAdminService = adminService;
        staticEmployeeService = employeeService;
    }
​
​
    /**
     * 生成token
     */
    public static String createToken(String data,String sign) {
        return JWT.create().withAudience(data) //将userId-role 保存到token里面，作为载荷
                .withExpiresAt(DateUtil.offsetDay(new Date(),1)) //1天后token过期
                .sign(Algorithm.HMAC256(sign)); //秘钥签名 以password 作为token的秘钥，HMAC256算法加密
    }
​
    /**
     * 获取当前登录用户信息
     */
    public static Account getCurrentUser() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token  = request.getHeader("token");
        if (StrUtil.isBlank(token)){
            token = request.getParameter("Token");
        }
        if (StrUtil.isBlank(token)){
            return null;
        }
        //拿到token的载荷数据
        String audience = JWT.decode(token).getAudience().get(0);
        String&#91;] split = audience.split("-");
        String userId = split&#91;0];
        String role = split&#91;1];
        //根据token解析出来的userId去对应的表查询用户信息
        if ("ADMIN".equals(role)){
            return staticAdminService.selectById(Integer.valueOf(userId));
        } else if ("EMP".equals(role)) {
            return staticEmployeeService.selectById(Integer.valueOf(userId));
        }
​
        return null;
    }
}
​</code></pre>



<p>Service层login方法中：</p>



<p>生成token并返回给前端：</p>



<pre class="wp-block-code"><code>String token = TokenUtils.createToken(dbAdmin.getId() + "-" + "ADMIN", dbAdmin.getPassword());<br>dbAdmin.setToken(token);</code></pre>



<p>获取当前用户信息：</p>



<pre class="wp-block-code"><code>Account currentUser = TokenUtils.getCurrentUser();</code></pre>



<h3 class="wp-block-heading">新：</h3>



<pre class="wp-block-code"><code>package com.chang.utils;
​
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chang.entity.Account;
import com.chang.service.impl.AdminServiceImpl;
import com.chang.service.impl.EmployeeServiceImpl;
import com.chang.service.impl.UserServiceImpl;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
​
import java.util.Date;
​
@Component
public class JWTUtils {
​
    private static final String sign = "chang_2025";
​
    @Autowired
    AdminServiceImpl adminService;
    @Autowired
    EmployeeServiceImpl employeeService;
    @Autowired
    UserServiceImpl userService;
​
    static AdminServiceImpl staticAdminService;
    static EmployeeServiceImpl staticEmployeeService;
    static UserServiceImpl staticUserService;
​
    //springboot工程启动后会加载这段代码
    @PostConstruct
    public void init(){
        staticAdminService = adminService;
        staticEmployeeService = employeeService;
        staticUserService = userService;
    }
​
    /**
     * 生成 Token
     */
    public static String createToken(Integer id, String role) {
        return JWT.create()
                .withClaim("id", id)
                .withClaim("role", role)               // 角色
                .withExpiresAt(DateUtil.offsetDay(new Date(), 1)) // 1天后过期
                .sign(Algorithm.HMAC256(sign));
    }
​
    /**
     * 获取用户信息
     * @return
     */
    public static Account getCurrentUser() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("Token");
        if (StrUtil.isBlank(token)) {
            token = request.getParameter("Token");
        }
        if (StrUtil.isBlank(token)) {
            return null; //只能进行静默处理
        }
​
        try {
            // 1. 验签
            DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(sign)).build().verify(token);
​
            // 2. 解析 payload
            Integer userId = decodedJWT.getClaim("id").asInt();
            String role = decodedJWT.getClaim("role").asString();
​
            // 根据角色查对应表
            if ("ADMIN".equals(role)) {
                return staticAdminService.selectById(userId); // 假设 username 是主键
            } else if ("EMP".equals(role)) {
                return staticEmployeeService.selectById(userId);
            } else if ("USER".equals(role)) {
                return staticUserService.selectById(userId);
            }
        } catch (Exception e) {
            return null;
        }
​
​
        return null;
    }
​
}</code></pre>



<h2 class="wp-block-heading">拦截器：</h2>



<h3 class="wp-block-heading">注册拦截器：</h3>



<pre class="wp-block-code"><code>package com.chang.config;
​
import com.chang.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
​
@Configuration
public class WebConfig implements WebMvcConfigurer {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/register");
    }
    
    @Bean
    public JWTInterceptor jwtInterceptor() {
        return new JWTInterceptor();
    }
}</code></pre>



<h3 class="wp-block-heading">实现拦截器：</h3>



<h4 class="wp-block-heading">旧：</h4>



<pre class="wp-block-code"><code>package com.chang.interceptor;
​
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.chang.entity.Account;
import com.chang.exception.CustomException;
import com.chang.service.AdminService;
import com.chang.service.EmployeeService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
​
@Component
public class JWTInterceptor implements HandlerInterceptor {
    
    @Autowired
    AdminService adminService;
    @Autowired
    EmployeeService employeeService;
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.从请求头中获取token
        String token = request.getHeader("Token");
        if (StrUtil.isEmpty(token)){
            //如果没拿到，从参数里再拿一次
            token = request.getParameter("Token");
        }
        //2.认证token
        if (StrUtil.isBlank(token)){
            throw new CustomException("401","您无权限操作");
        }
​
        Account account = null;
        try{
            //拿到token的载荷数据
            String audience = JWT.decode(token).getAudience().get(0);
            String&#91;] split = audience.split("-");
            String userId = split&#91;0];
            String role = split&#91;1];
            //根据token解析出来的userId去对应的表查询用户信息
            if ("ADMIN".equals(role)){
                account = adminService.selectById(Integer.valueOf(userId));
            } else if ("EMP".equals(role)) {
                account = employeeService.selectById(Integer.valueOf(userId));
            }
        }catch (Exception e){
            throw new CustomException("401","您无权限操作");
        }
        if (account == null){
            throw new CustomException("401","您无权限操作");
        }
​
        //验证签名
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build();
            jwtVerifier.verify(token);
        }catch (Exception e){
            throw new CustomException("401","您无权限操作");
        }
        
        return true;
    }
}</code></pre>



<h4 class="wp-block-heading">新：</h4>



<pre class="wp-block-code"><code>package com.chang.interceptor;
​
import cn.hutool.core.util.StrUtil;
import com.chang.entity.Account;
import com.chang.exception.CustomException;
import com.chang.utils.TokenUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
​
@Component
public class JWTInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.从请求头中获取token
        String token = request.getHeader("Token");
        if (StrUtil.isEmpty(token)){
            //如果没拿到，从参数里再拿一次
            token = request.getParameter("Token");
        }
​
        //2.认证token
        if (StrUtil.isBlank(token)){
            throw new CustomException("401", "未检测到登录凭证，请先登录");
        }
​
        Account account = TokenUtils.getCurrentUser();
        if (account == null) {
            throw new CustomException("401", "Token无效或已过期，请重新登录");
        }
​
        return true;
    }
}</code></pre>



<h2 class="wp-block-heading">前端：</h2>



<h3 class="wp-block-heading">设置拦截器：</h3>



<p>utils包：</p>



<p>request.js:</p>



<p>添加请求头 处理错误信息：</p>



<pre class="wp-block-code"><code>import axios from 'axios';<br>import {ElMessage} from 'element-plus';<br>import router from "@/router/index.js";<br>​<br>const request = axios.create({<br> &nbsp; &nbsp;baseURL:'http://localhost:9090',<br> &nbsp; &nbsp;timeout:30000, //后台接口超时时间<br>})<br>​<br>//request 拦截器<br>//可以自动请求发送前对请求做的一些处理<br>request.interceptors.request.use(<br> &nbsp; &nbsp;config =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;config.headers&#91;'Content-Type'] = 'application/json;charset=utf-8';<br> &nbsp; &nbsp; &nbsp; &nbsp;let user = JSON.parse(localStorage.getItem('chang-user')||'{}');<br> &nbsp; &nbsp; &nbsp; &nbsp;config.headers&#91;'token'] = user.token<br> &nbsp; &nbsp; &nbsp; &nbsp;return config;<br> &nbsp;  },<br> &nbsp; &nbsp;error =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;return Promise.reject(error);<br> &nbsp;  }<br>)<br>​<br>//response 拦截器<br>//可以在接口响应后统一处理结果<br>request.interceptors.response.use(<br> &nbsp; &nbsp;response =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;let res = response.data;<br> &nbsp; &nbsp; &nbsp; &nbsp;//兼容服务端返回的字符串数据<br> &nbsp; &nbsp; &nbsp; &nbsp;if (typeof res === 'string') {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;res = res ? JSON.parse(res) : res;<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp; &nbsp; &nbsp; &nbsp;if (res.code === '401') {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ElMessage.error(res.msg);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;router.push('/login');<br> &nbsp; &nbsp; &nbsp;  }else{<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return res;<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp; &nbsp; &nbsp; &nbsp;return res;<br> &nbsp;  },<br> &nbsp; &nbsp;error =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp;if (error.response.status === 404) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ElMessage.error('未找到请求接口')<br> &nbsp; &nbsp; &nbsp;  }else if (error.response.status === 500) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ElMessage.error('系统异常，请查看后端控制台报错')<br> &nbsp; &nbsp; &nbsp;  }else {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;console.error(error.message);<br> &nbsp; &nbsp; &nbsp;  }<br> &nbsp; &nbsp; &nbsp; &nbsp;return Promise.reject(error);<br> &nbsp;  }<br>)<br>​<br>export default request;</code></pre>



<h3 class="wp-block-heading">拼接Token令牌：</h3>



<p>eg：更改导出数据代码:</p>



<pre class="wp-block-code"><code>user:JSON.parse(localStorage.getItem('chang-user')||'{}'),
​
//导出数据
const exportData=()=&gt;{
 &nbsp;let url = &nbsp;`http://localhost:9090/employee/export`
 &nbsp;+ `?Token=${data.user.token}`;
 &nbsp;//导出数据 是通过流的形式下载 excel &nbsp; 打开流的连接，浏览器会自动帮我们下载文件
 &nbsp;window.open(url);
}</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/jwt-%e4%bb%a4%e7%89%8c%e5%8a%a0%e5%af%86/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Lombok-构建工具</title>
		<link>https://www.qiqin-chang.cn/lombok-%e6%9e%84%e5%bb%ba%e5%b7%a5%e5%85%b7/</link>
					<comments>https://www.qiqin-chang.cn/lombok-%e6%9e%84%e5%bb%ba%e5%b7%a5%e5%85%b7/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:25:21 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=64</guid>

					<description><![CDATA[依赖： 使用方法： 注解 添加位置 说明 @Setter: 注解在类/字段 生成setter方法 @Gette [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>依赖：</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;dependency>
    &lt;groupId>org.projectlombok&lt;/groupId>
    &lt;artifactId>lombok&lt;/artifactId>
&lt;/dependency></code></pre>



<p>使用方法：</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>注解</th><th>添加位置</th><th>说明</th></tr></thead><tbody><tr><td>@Setter:</td><td>注解在类/字段</td><td>生成setter方法</td></tr><tr><td>@Getter:</td><td>注解在类/字段</td><td>生成getter方法</td></tr><tr><td>@ToString:</td><td>注解在类</td><td>生成toString方法</td></tr><tr><td>@EqualsAndHashCode:</td><td>注解在类</td><td>生成hashCode和equals方法</td></tr><tr><td>@NoArgsConstructor:</td><td>注解在类</td><td>生成无参构造方法</td></tr><tr><td>@RequireArgsConstructor:</td><td>注解在类</td><td>为需要特殊处理的字段生成构造方法（如final和被@NonNull注解的字段）</td></tr><tr><td>@Data:</td><td>注解在类</td><td>生成setter、getter、equals、canEqual、hashCode、toString方法。(final属性，不会生成setter方法)</td></tr><tr><td>@Slf4j:</td><td>注解在类</td><td>生成log日志</td></tr><tr><td>@Builder：</td><td>注解在类</td><td>链式构造Java类对象</td></tr></tbody></table></figure>



<p><a href="#top">返回顶部</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/lombok-%e6%9e%84%e5%bb%ba%e5%b7%a5%e5%85%b7/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Swagger-接口文档</title>
		<link>https://www.qiqin-chang.cn/swagger-%e6%8e%a5%e5%8f%a3%e6%96%87%e6%a1%a3/</link>
					<comments>https://www.qiqin-chang.cn/swagger-%e6%8e%a5%e5%8f%a3%e6%96%87%e6%a1%a3/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:24:24 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=62</guid>

					<description><![CDATA[依赖： 常用注解： 注解 说明 @Api 用在Controller类上 @ApiOperation 用在Con [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>依赖：</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;dependency>
    &lt;groupId>com.github.xiaoymin&lt;/groupId>
    &lt;artifactId>knife4j-spring-boot-starter&lt;/artifactId>
&lt;/dependency></code></pre>



<p>常用注解：</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>注解</th><th>说明</th></tr></thead><tbody><tr><td>@Api</td><td>用在Controller类上</td></tr><tr><td>@ApiOperation</td><td>用在Controller方法上</td></tr><tr><td>@ApiModel</td><td>用在pojo类上</td></tr><tr><td>@ApiModelProperty</td><td>用在pojo属性上</td></tr></tbody></table></figure>



<p>使用方法：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">/**
 * 配置类，注册web层相关组件
 */
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    /**
 	* 通过knife4j生成接口文档
 	* @return
 	*/
	@Bean
	public Docket docket() {
    	ApiInfo apiInfo = new ApiInfoBuilder()
            	.title("标题")
            	.version("2.0")
        	    .description("描述")
    	        .build();
   	 	Docket docket = new Docket(DocumentationType.SWAGGER_2)
        	    .apiInfo(apiInfo)
    	        .select()
	            //指定生成接口需要扫描的包
	            .apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
            	.paths(PathSelectors.any())
        	    .build();
    	return docket;
	}

	/**
 	* 设置静态资源映射
 	* @param registry
 	*/
	protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    	registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
    	registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
	}
}</code></pre>



<p><a href="#top">返回顶部</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/swagger-%e6%8e%a5%e5%8f%a3%e6%96%87%e6%a1%a3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SpringCache-缓存管理</title>
		<link>https://www.qiqin-chang.cn/springcache-%e7%bc%93%e5%ad%98%e7%ae%a1%e7%90%86/</link>
					<comments>https://www.qiqin-chang.cn/springcache-%e7%bc%93%e5%ad%98%e7%ae%a1%e7%90%86/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:22:30 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=58</guid>

					<description><![CDATA[依赖： 常用注解： 注解 添加位置 说明 @EnableCaching 启动类 开启缓存注解功能 @Cache [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>依赖：</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;dependency>
    &lt;groupId>org.springframework.boot&lt;/groupId>
    &lt;artifactId>spring-boot-starter-cache&lt;/artifactId>
&lt;/dependency></code></pre>



<p>常用注解：</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>注解</th><th>添加位置</th><th>说明</th></tr></thead><tbody><tr><td>@EnableCaching</td><td>启动类</td><td>开启缓存注解功能</td></tr><tr><td>@Cacheable</td><td>方法</td><td>在方法执行前先查询缓存中是否存在数据，如有直接返回缓存数据；否则调用方法并将返回值放到缓存中</td></tr><tr><td>@CachePut</td><td>方法</td><td>将方法返回值放到缓存中</td></tr><tr><td>@CacheEvict</td><td>方法</td><td>从缓存中删除一条或多条数据</td></tr></tbody></table></figure>



<p>使用试例：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">@PostMapping
   @CachePut(cacheNames = "userCache",key = "#user.id") //如果使用Spring Cache 缓存数据，key的生成：userCache::2
   //@CachePut(cacheNames = "userCache",key = "#result.id") // .导航对象
   //@CachePut(cacheNames = "userCache",key = "#p0.id")
   //@CachePut(cacheNames = "userCache",key = "#a0.id")
   //@CachePut(cacheNames = "userCache",key = "#root.args[0].id")
   public User save(@RequestBody User user){
       userMapper.insert(user);
       return user;
   }
​
   @GetMapping
   @Cacheable(cacheNames = "userCache",key = "#id") //key的生成：userCache::10
   public User getById(Long id){
       User user = userMapper.getById(id);
       return user;
   }
​
   @DeleteMapping
   @CacheEvict(cacheNames = "userCache",key = "#id") //key的生成：userCache::10
   public void deleteById(Long id){
       userMapper.deleteById(id);
   }
​
   @DeleteMapping("/delAll")
   @CacheEvict(cacheNames = "userCache",allEntries = true)
   public void deleteAll(){
       userMapper.deleteAll();
   }</code></pre>



<p><a href="#top">返回顶部</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/springcache-%e7%bc%93%e5%ad%98%e7%ae%a1%e7%90%86/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>HttpClient-http请求</title>
		<link>https://www.qiqin-chang.cn/httpclient-http%e8%af%b7%e6%b1%82/</link>
					<comments>https://www.qiqin-chang.cn/httpclient-http%e8%af%b7%e6%b1%82/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:21:28 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=56</guid>

					<description><![CDATA[依赖： 阿里云OSS包含此依赖： 核心API： HttpClient HttpClients Closeabl [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>依赖：</p>



<pre class="wp-block-code"><code>&lt;dependency>  
    &lt;groupId>org.apache.httpcomponents&lt;/groupId>  
    &lt;artifactId>httpclient&lt;/artifactId>  
&lt;/dependency></code></pre>



<p>阿里云OSS包含此依赖：</p>



<pre class="wp-block-code"><code>&lt;dependency>  
    &lt;groupId>com.aliyun.oss&lt;/groupId>  
    &lt;artifactId>aliyun-sdk-oss&lt;/artifactId>  
&lt;/dependency></code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>核心API：</th></tr></thead><tbody><tr><td>HttpClient</td></tr><tr><td>HttpClients</td></tr><tr><td>CloseableHttpClient</td></tr><tr><td>HttpGet</td></tr><tr><td>HttpPost</td></tr></tbody></table></figure>



<p>发送请求步骤：</p>



<ul class="wp-block-list">
<li>创建HttpClient对象</li>



<li>调用Http请求对象</li>



<li>调用HttpClient的execute方法发送请求</li>
</ul>



<pre class="wp-block-code"><code>@SpringBootTest
public class HttpClientTest {
​
    /**
     * 测试通过httpclient发送GET方式的请求
     */
    @Test
    public void testGET() throws Exception{
        //创建httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
​
        //创建请求对象
        HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");
​
        //发送请求，接收响应结果
        CloseableHttpResponse response = httpClient.execute(httpGet);
​
        //获取服务器端返回的状态
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("服务端返回的状态码为：" + statusCode);
​
        HttpEntity entity = response.getEntity();
        String body = EntityUtils.toString(entity);
        System.out.println("服务端返回的数据为：" + body);
​
        //关闭资源
        response.close();
        httpClient.close();
    }
​
    /**
     * 测试通过httpclient发送POST方式的请求
     */
    @Test
    public void testPOST() throws Exception{
        //创建httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
​
        //创建请求对象
        HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");
​
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username", "admin");
        jsonObject.put("password", "123456");
​
        StringEntity entity = new StringEntity(jsonObject.toString());
​
        //指定请求编码方式
        entity.setContentEncoding("UTF-8");
​
        //数据格式
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
​
        //发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
​
        //解析返回结果
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("响应码为：" + statusCode);
​
        HttpEntity entity1 = response.getEntity();
        String body = EntityUtils.toString(entity1);
        System.out.println("响应数据" + body);
​
        //关闭资源
        response.close();
        httpClient.close();
​
    }
}</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/httpclient-http%e8%af%b7%e6%b1%82/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Pagehelper-分页插件</title>
		<link>https://www.qiqin-chang.cn/pagehelper-%e5%88%86%e9%a1%b5%e6%8f%92%e4%bb%b6/</link>
					<comments>https://www.qiqin-chang.cn/pagehelper-%e5%88%86%e9%a1%b5%e6%8f%92%e4%bb%b6/#respond</comments>
		
		<dc:creator><![CDATA[乐章]]></dc:creator>
		<pubDate>Wed, 09 Apr 2025 12:20:26 +0000</pubDate>
				<category><![CDATA[后端]]></category>
		<category><![CDATA[插件]]></category>
		<guid isPermaLink="false">http://8.153.197.211/?p=54</guid>

					<description><![CDATA[依赖： 任务：从前端获取页码和页码大小，返回总条数和数据 返回结果封装： -result包 Controlle [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>依赖：</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;dependency>
  &lt;groupId>com.github.pagehelper&lt;/groupId>
  &lt;artifactId>pagehelper-spring-boot-starter&lt;/artifactId>
&lt;/dependency></code></pre>



<p>任务：从前端获取页码和页码大小，返回总条数和数据</p>



<p>返回结果封装：</p>



<p>-result包</p>



<pre class="wp-block-code"><code lang="java" class="language-java">/**
 * 封装分页查询结果
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
​
    private long total; //总记录数
​
    private List records; //当前页数据集合
​
}</code></pre>



<p>Controller层：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">    /**
     * 分页查询
     * @param testPageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("分页查询")
    public Result&lt;PageResult> page(TestPageQueryDTO testPageQueryDTO){
        log.info("分页查询，参数为：{}",testPageQueryDTO);
        PageResult pageResult = testService.pageQuery(testPageQueryDTO);
        return Result.success(pageResult);
    }</code></pre>



<p>Service层接口：</p>



<pre class="wp-block-code"><code lang="java" class="language-java"> /**
     * 分页查询
     * @param testPageQueryDTO
     * @return
     */
    PageResult pageQuery(TestPageQueryDTO testPageQueryDTO);</code></pre>



<p>Service层：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">  /**
     * 分页查询
     * @param testPageQueryDTO
     * @return
     */
    public PageResult pageQuery(TestPageQueryDTO testPageQueryDTO) {
        //开始分页查询
        PageHelper.startPage(testPageQueryDTO.getPage(),testPageQueryDTO.getPageSize());
​
        Page&lt;Test> page = testMapper.pageQuery(testPageQueryDTO);
​
        long total = page.getTotal();
        List&lt;Test> records = page.getResult();
​
        return new PageResult(total,records);
    }</code></pre>



<p>Mapper层：</p>



<pre class="wp-block-code"><code lang="java" class="language-java">    /**
     * 分页查询
     * @param testPageQueryDTO
     * @return
     */
    Page&lt;Test> pageQuery(TestPageQueryDTO testPageQueryDTO);</code></pre>



<p>Mapper.xml</p>



<pre class="wp-block-code"><code lang="xml" class="language-xml">&lt;select id="pageQuery" resultType="com.sky.entity.Test"
            parameterType="com.项目名.dto.TestPageQueryDTO">
            select * from test
            查询条件
            order by create_time desc
&lt;/select></code></pre>



<p><a href="#top">返回顶部</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.qiqin-chang.cn/pagehelper-%e5%88%86%e9%a1%b5%e6%8f%92%e4%bb%b6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
