自定义Api接口访问系统日志记录

23 篇文章 0 订阅
13 篇文章 0 订阅

Log:

package com.rz.common.aspect;



import com.rz.common.enums.BusinessType;
import com.rz.common.enums.OperatorType;

import java.lang.annotation.*;

/**
 * @Description : 自定义操作日志记录注解
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

    /**
     * 模块
     */
    String title() default "";

    /**
     * 功能
     */
    BusinessType businessType() default BusinessType.OTHER;

    /**
     * 操作人类别
     */
    OperatorType operatorType() default OperatorType.MANAGE;

    /**
     * 是否保存请求的参数
     */
    boolean isSaveRequestData() default true;

}

BusinessType:

package com.rz.common.enums;

/**
 * @Description : 业务操作类型
 */
public enum BusinessType {

    /**
     * 其它
     */
    OTHER,

    /**
     * 新增
     */
    INSERT,

    /**
     * 修改
     */
    UPDATE,

    /**
     * 删除
     */
    DELETE,

    /**
     * 授权
     */
    GRANT,

    /**
     * 导出
     */
    EXPORT,

    /**
     * 导入
     */
    IMPORT,

    /**
     * 强退
     */
    FORCE,

    /**
     * 生成代码
     */
    GENCODE,

    /**
     * 清空
     */
    CLEAN,

    /**
     * 查询
     */
    QUERY
}

OperatorType:

package com.rz.common.enums;

/**
 * @Description : 操作类型

 */
public enum OperatorType {

    /**
     * 其它
     */
    OTHER,

    /**
     * 后台用户
     */
    MANAGE,

    /**
     * 手机端用户
     */
    MOBILE

}

IBaseAspect:

package com.rz.common.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public interface IBaseAspect {

	void before(JoinPoint joinPoint) throws Throwable;

	void after(JoinPoint joinPoint) throws Throwable;

	void afterReturning(JoinPoint joinPoint, Object returnObj) throws Throwable;

	void afterThrowing(JoinPoint joinPoint, Throwable e) throws Throwable;

	Object around(ProceedingJoinPoint pJoinPoint) throws Throwable;

}

LogBaseAspect:

package com.rz.common.aspect.impl;


import com.rz.common.aspect.IBaseAspect;
import com.rz.common.aspect.Log;
import com.rz.common.manager.AsyncFactory;
import com.rz.common.manager.AsyncManager;
import com.alibaba.fastjson.JSON;
import com.rz.common.util.ServletUtils;
import com.rz.common.util.StringUtils;
import com.rz.common.util.local.NetworkUtil;
import com.rz.domian.base.SysOperateLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;



@Aspect
@Component
@Order(3)
public class LogBaseAspect implements IBaseAspect {

    private static final Logger log = LoggerFactory.getLogger(LogBaseAspect.class);

    /**
     * 配置织入点
     */
    @Pointcut("@annotation(com.rz.common.aspect.Log)")
    public void logPointCut() {
    }


    @Override
    public void before(JoinPoint joinPoint) throws Throwable {
    }

    @Override
    public void after(JoinPoint joinPoint) throws Throwable {

    }

    /**
     * 后置通知,拦截
     * @param joinPoint
     * @param returnObj
     * @throws Throwable
     */
    @Override
    @AfterReturning(pointcut = "logPointCut()", argNames = "joinPoint,returnObj", returning = "returnObj")
    public void afterReturning(JoinPoint joinPoint, Object returnObj) throws Throwable {
        handleLog(joinPoint, null);
    }

    /**
     * 异常拦截操作
     *
     * @param joinPoint
     * @param e
     * @throws Throwable
     */
    @Override
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Throwable e) throws Throwable {
        handleLog(joinPoint, e);
    }

    /**
     * @Around 可以更改系统返回值
     * @param pJoinPoint
     * @return
     * @throws Throwable
     */
    @Override
    public Object around(ProceedingJoinPoint pJoinPoint) throws Throwable {
        return null;
    }


    protected void handleLog(final JoinPoint joinPoint, final Throwable e) {
        try {

            // 获取注解
            Log controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null) {
                return;
            }
            String userName = "";
            /*boolean result = SpringUtils.containsBean("openUserServiceImpl");
            if (!result) {
                log.error(" noSuchBeanDefinitionException plase setting bean name ‘openUserServiceImpl’");
                log.error("操作日志记录停止,无法获取操作人,请实现IOpenUserService接口,初始化用户名");
                return;
            }
            IOpenUserService userService = SpringUtils.getBean(IOpenUserService.class);
            userName = userService.getUserNameApi();*/
//          userName = (String) SessionUtil.getPrincipal();


            // *========数据库日志=========*//
            SysOperateLog operLog = new SysOperateLog();
            operLog.setStatus(Boolean.TRUE);

            operLog.setOperIp(NetworkUtil.getRemoteAddr(ServletUtils.getRequest()));
            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
            operLog.setOperName(userName);
            operLog.setDeptName("");
            operLog.setOperTime(new Date());
            operLog.setToLocalIp(NetworkUtil.getLocalAddr());


            if (e != null) {
                operLog.setStatus(Boolean.FALSE);
                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // 处理设置注解上的参数
            getControllerMethodDescription(controllerLog, operLog);
            // 保存数据库
            AsyncManager.getInstance().execute(AsyncFactory.recordOper(operLog));

        } catch (Exception exp) {
            log.error(" --log-- 操作日志异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param log     日志
     * @param operLog 操作日志
     * @throws Exception
     */
    public void getControllerMethodDescription(Log log, SysOperateLog operLog) throws Exception {
        // 设置action动作
        int businessType = log.businessType().ordinal();
        operLog.setBusinessType((byte) businessType);
        // 设置标题
        operLog.setTitle(log.title());
        // 设置操作人类别
        int operatorType = log.operatorType().ordinal();
        operLog.setOperatorType((byte) operatorType);
        // 是否需要保存request,参数和值
        if (log.isSaveRequestData()) {
            // 获取参数的信息,传入到数据库中。
            setRequestValue(operLog);
        }
    }

    /**
     * 获取请求的参数,放到log中
     *
     * @param operLog 操作日志
     * @throws Exception 异常
     */
    private void setRequestValue(SysOperateLog operLog) throws Exception {
        Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
        String params = JSON.toJSONString(map);
        operLog.setOperParam(params);
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }
}

ServletUtils:

package com.rz.common.util;

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @Description : Servlet客户端工具类
 */
public class ServletUtils {

    /**
     * 获取request
     */
    public static HttpServletRequest getRequest() {
        return getRequestAttributes().getRequest();
    }

    public static ServletRequestAttributes getRequestAttributes() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes) attributes;
    }

}

SysOperateLog:

package com.rz.domian.base;

import java.io.Serializable;
import java.util.Date;

public class SysOperateLog implements Serializable {
    private Long operId;

    private String title;

    private Byte businessType;

    private String method;

    private Byte operatorType;

    private String operName;

    private String deptName;

    private String operUrl;

    private String operIp;

    private String operLocation;

    private String toLocalIp;

    private Boolean status;

    private String errorMsg;

    private Date operTime;

    private String operParam;

    private static final long serialVersionUID = 1L;

    public Long getOperId() {
        return operId;
    }

    public void setOperId(Long operId) {
        this.operId = operId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title == null ? null : title.trim();
    }

    public Byte getBusinessType() {
        return businessType;
    }

    public void setBusinessType(Byte businessType) {
        this.businessType = businessType;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method == null ? null : method.trim();
    }

    public Byte getOperatorType() {
        return operatorType;
    }

    public void setOperatorType(Byte operatorType) {
        this.operatorType = operatorType;
    }

    public String getOperName() {
        return operName;
    }

    public void setOperName(String operName) {
        this.operName = operName == null ? null : operName.trim();
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName == null ? null : deptName.trim();
    }

    public String getOperUrl() {
        return operUrl;
    }

    public void setOperUrl(String operUrl) {
        this.operUrl = operUrl == null ? null : operUrl.trim();
    }

    public String getOperIp() {
        return operIp;
    }

    public void setOperIp(String operIp) {
        this.operIp = operIp == null ? null : operIp.trim();
    }

    public String getOperLocation() {
        return operLocation;
    }

    public void setOperLocation(String operLocation) {
        this.operLocation = operLocation == null ? null : operLocation.trim();
    }

    public String getToLocalIp() {
        return toLocalIp;
    }

    public void setToLocalIp(String toLocalIp) {
        this.toLocalIp = toLocalIp == null ? null : toLocalIp.trim();
    }

    public Boolean getStatus() {
        return status;
    }

    public void setStatus(Boolean status) {
        this.status = status;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg == null ? null : errorMsg.trim();
    }

    public Date getOperTime() {
        return operTime;
    }

    public void setOperTime(Date operTime) {
        this.operTime = operTime;
    }

    public String getOperParam() {
        return operParam;
    }

    public void setOperParam(String operParam) {
        this.operParam = operParam == null ? null : operParam.trim();
    }
}

AsyncManager:

package com.rz.common.manager;


import com.rz.common.util.ThreadUtils;

import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description : 异步任务管理器
 */
public class AsyncManager {

    /**
     * 操作延迟10毫秒
     */
    private final int OPERATE_DELAY_TIME = 10;

    /**
     * 异步操作任务调度线程池
     */
    private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);


    /**
     * 单例模式
     */
    private volatile static AsyncManager asyncManager;


    private AsyncManager(){

    }

    public static AsyncManager getInstance() {
        if (null == asyncManager) {
            synchronized (AsyncManager.class) {
                if (null == asyncManager) {
                    asyncManager = new AsyncManager();
                }
            }
        }
        return asyncManager;
    }

    /**
     * 执行任务
     *
     * @param task 任务
     */
    public void execute(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }

    /**
     * 停止任务线程池
     */
    public void shutdown() {
        ThreadUtils.shutdownAndAwaitTermination(executor);
    }

}

AsyncFactory:

package com.rz.common.manager;


import com.rz.common.util.SpringUtils;
import com.rz.domian.base.SysOperateLog;
import com.rz.domian.base.RateLimiterRecord;
import com.rz.service.ISysOperateLogService;
import com.rz.service.RateLimiterRecordService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.TimerTask;

/**
 * @Description :
 *      异步工厂(产生任务用),注意分布式环境下,同时跑两个一样的任务
 */
public class AsyncFactory {

    private static final Logger sys_user_logger = LoggerFactory.getLogger(AsyncFactory.class);



    /**
     * 操作日志记录
     *
     * @param operLog 操作日志信息
     * @return 任务task
     */
    public static TimerTask recordOper(final SysOperateLog operLog) {
        return new TimerTask() {
            @Override
            public void run() {

                try {					
                    SpringUtils.getBean(ISysOperateLogService.class).insertOperlog(operLog);
                } catch (Exception e) {
                    sys_user_logger.error("操作日志记录异常  -> errorMsg : {}", e.getMessage());
                }
            }
        };
    }


}

SpringUtils:

package com.rz.common.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * spring工具类 方便在非spring管理环境中获取bean
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor
{
    /** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        SpringUtils.beanFactory = beanFactory;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException
    {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException
    {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name)
    {
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
    {
        return beanFactory.getAliases(name);
    }
}

NetworkUtil:

package com.rz.common.util.local;


import com.rz.common.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.Enumeration;
import java.util.Random;

public class NetworkUtil {

    /**
     * 获取本机ip地址
     * @return
     */
    public static String getLocalAddr() {
        String localip = null;// 本地IP,如果没有配置外网IP则返回它
        String netip = null;// 外网IP
        try {
            Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            boolean finded = false;// 是否找到外网IP
            while (netInterfaces.hasMoreElements() && !finded) {
                NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
                Enumeration address = ni.getInetAddresses();
                while (address.hasMoreElements()) {
                    ip = (InetAddress) address.nextElement();
                    if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 外网IP
                        netip = ip.getHostAddress();
                        finded = true;
                        break;
                    } else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {// 内网IP
                        localip = ip.getHostAddress();
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }

        if (netip != null && !"".equals(netip)) {
            return netip;
        } else {
            return localip;
        }
    }

    /**
     * 获取远程访问地址
     * @param request
     * @return
     */
	public static String getRemoteAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");

		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("ali-cdn-real-ip");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}

		String[] ipArray = ip.split(",");
		if (ipArray != null && ipArray.length > 0) {
			ip = ipArray[0].trim();
		}

		return ip;
	}
    
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			URLConnection conn = realUrl.openConnection();

			// 随机生成ip
			String ip = randIP();
			conn.setRequestProperty("X-Forwarded-For", ip);
			conn.setRequestProperty("HTTP_X_FORWARDED_FOR", ip);
			conn.setRequestProperty("HTTP_CLIENT_IP", ip);
			conn.setRequestProperty("REMOTE_ADDR", ip);
			conn.setRequestProperty("Host", "operation.cardniu.com");
			conn.setRequestProperty("Connection", "keep-alive");
			conn.setRequestProperty("Content-Length", "17");
			conn.setRequestProperty("Accept", "application/json");
			conn.setRequestProperty("Origin", "ORIGIN");
			conn.setRequestProperty(
					"User-Agent",
					"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");
			conn.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			conn.setRequestProperty(
					"Referer",
					"REFERER");
			conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
			conn.setRequestProperty("Accept-Language",
					"zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,pt;q=0.2");

			conn.setDoOutput(true);
			conn.setDoInput(true);
			out = new PrintWriter(conn.getOutputStream());
			out.print(param);
			out.flush();
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常!" + e);
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	private static String randIP() {
		Random random = new Random(System.currentTimeMillis());
		return (random.nextInt(255) + 1) + "." + (random.nextInt(255) + 1)
				+ "." + (random.nextInt(255) + 1) + "."
				+ (random.nextInt(255) + 1);
	}

}

ThreadUtils:

package com.rz.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description : 线程相关工具类.
 */
public class ThreadUtils {

    private static final Logger logger = LoggerFactory.getLogger("sys-user");

    /**
     * sleep等待,单位为毫秒
     */
    public static void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            return;
        }
    }

    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍人超時,則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        if (pool != null && !pool.isShutdown()) {
            pool.shutdown();
            try {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        logger.info("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

}

TestController:

package com.rz.controller;
import com.rz.common.aspect.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.util.List;

/**
 * @Description : 日志测试
 */
@RestController
public class TestController {

    private Logger logger = LoggerFactory.getLogger(EsSearchOppositeController.class);
   

    @GetMapping("/test")
    @Log(title = "测试", businessType = BusinessType.QUERY)
    public Result test() {
        Result result = new Result();
        result.setMessage("test msg");
        return result;
    }


}

 

  finish!

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了你的问题。这是一个非常有趣的项目,需要一定的数据库和Spring知识,但是我会尽力解释清楚每个步骤。首先,我会介绍一下这个项目的整体结构和目标,然后分别介绍Spring Data JPA和Redis的整合方法。 ## 项目结构和目标 我们将设计一个简单的任务管理系统,其中需要存储任务的名称、描述和截止日期。任务将被存储在数据库中,并且可以通过REST API进行访问。我们将使用Spring Boot作为我们的开发框架,并使用Spring Data JPA和Redis来实现数据持久化。 下面是项目的结构: ``` src/ ├── main/ │ ├── java/ │ │ └── com.example/ │ │ ├── controller/ │ │ ├── model/ │ │ ├── repository/ │ │ ├── service/ │ │ ├── Application.java │ │ └── ApplicationConfig.java │ └── resources/ │ └── application.properties └── test/ └── java/ └── com.example/ ``` 我们将把实体类放在`com.example.model`包中,将`Repository`接口放在`com.example.repository`包中,将服务接口和实现放在`com.example.service`包中,最后将控制器放在`com.example.controller`包中。 ## Spring Data JPA整合方法 ### 定义实体类 首先,我们需要定义一个简单的实体类来表示任务。我们将使用注解来定义实体和属性。在`com.example.model`包中创建一个名为`Task`的类,并添加以下代码: ```java @Entity public class Task { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String description; private Date deadline; // getters and setters } ``` 这个类使用`@Entity`注解来标识它是一个JPA实体。我们还使用`@Id`注解来标识任务的ID,并使用`@GeneratedValue`注解来指定ID的生成策略。在这个例子中,我们使用默认的自动增加ID生成策略。 ### 定义Repository接口 接下来,我们需要定义一个`Repository`接口来处理任务的持久化。在`com.example.repository`包中创建一个名为`TaskRepository`的接口,并添加以下代码: ```java @Repository public interface TaskRepository extends JpaRepository<Task, Long> { List<Task> findByDeadlineBefore(Date deadline); } ``` 这个接口继承了`JpaRepository`接口,这个接口提供了许多常用的持久化方法,如`save()`、`findAll()`和`delete()`。我们还定义了一个自定义方法`findByDeadlineBefore()`,用于查找在截止日期之前的所有任务。 ### 实现服务接口 接下来,我们需要实现一个服务接口来处理任务。在`com.example.service`包中创建一个名为`TaskService`的接口,并添加以下代码: ```java public interface TaskService { Task createTask(Task task); List<Task> getTasks(); Task getTaskById(Long id); List<Task> getTasksByDeadlineBefore(Date deadline); void deleteTask(Long id); } ``` 这个接口定义了一些基本的任务服务方法,如创建任务、获取所有任务、通过ID获取任务、获取截止日期之前的所有任务和删除任务。 接下来,我们需要实现这个接口。在`com.example.service`包中创建一个名为`TaskServiceImpl`的类,并添加以下代码: ```java @Service public class TaskServiceImpl implements TaskService { @Autowired private TaskRepository taskRepository; @Override public Task createTask(Task task) { return taskRepository.save(task); } @Override public List<Task> getTasks() { return taskRepository.findAll(); } @Override public Task getTaskById(Long id) { Optional<Task> optionalTask = taskRepository.findById(id); return optionalTask.orElse(null); } @Override public List<Task> getTasksByDeadlineBefore(Date deadline) { return taskRepository.findByDeadlineBefore(deadline); } @Override public void deleteTask(Long id) { taskRepository.deleteById(id); } } ``` 这个类实现了`TaskService`接口,并使用`@Autowired`注解注入了`TaskRepository`。我们实现了所有服务方法,并将它们映射到`TaskRepository`的方法上。 ### 创建控制器 最后,我们需要创建一个控制器来处理HTTP请求。在`com.example.controller`包中创建一个名为`TaskController`的类,并添加以下代码: ```java @RestController @RequestMapping("/tasks") public class TaskController { @Autowired private TaskService taskService; @PostMapping public Task createTask(@RequestBody Task task) { return taskService.createTask(task); } @GetMapping public List<Task> getTasks() { return taskService.getTasks(); } @GetMapping("/{id}") public Task getTaskById(@PathVariable Long id) { return taskService.getTaskById(id); } @GetMapping("/deadline/{deadline}") public List<Task> getTasksByDeadlineBefore(@PathVariable String deadline) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date parsedDate; try { parsedDate = dateFormat.parse(deadline); } catch (ParseException e) { return null; } return taskService.getTasksByDeadlineBefore(parsedDate); } @DeleteMapping("/{id}") public void deleteTask(@PathVariable Long id) { taskService.deleteTask(id); } } ``` 这个类使用`@RestController`注解将它标识为一个REST控制器,并使用`@RequestMapping`注解指定了所有请求的前缀。我们使用`@Autowired`注解注入了`TaskService`。 控制器定义了一些HTTP请求处理方法,如`createTask()`、`getTasks()`、`getTaskById()`、`getTasksByDeadlineBefore()`和`deleteTask()`。这些方法将服务方法映射到HTTP请求。 ### 配置应用程序 最后,我们需要配置应用程序。在`src/main/resources`目录中创建一个名为`application.properties`的文件,并添加以下代码: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/example?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=update spring.redis.host=localhost spring.redis.port=6379 ``` 这个文件包含了数据库和Redis的配置信息。我们使用MySQL作为我们的数据库,因此需要指定URL、用户名和密码。我们还启用了Spring Data JPA的SQL查询日志和Hibernate的DDL自动更新。最后,我们指定了Redis的主机和端口。 现在我们已经完成了Spring Data JPA的整合方法。接下来,我们将介绍Redis的整合方法。 ## Redis整合方法 ### 添加Redis依赖 首先,我们需要添加Redis的依赖。在`build.gradle`文件中添加以下代码: ```groovy implementation 'org.springframework.boot:spring-boot-starter-data-redis' ``` 这个依赖将添加Redis相关的Spring Boot启动器和Redis客户端。 ### 配置RedisTemplate 接下来,我们需要配置`RedisTemplate`。在`com.example`包中创建一个名为`ApplicationConfig`的类,并添加以下代码: ```java @Configuration @EnableCaching public class ApplicationConfig { @Value("${spring.redis.host}") private String redisHost; @Value("${spring.redis.port}") private int redisPort; @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisHost, redisPort); return new LettuceConnectionFactory(configuration); } @Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } ``` 这个类使用`@Configuration`注解将它标识为一个配置类,并使用`@EnableCaching`注解启用缓存。我们使用`@Value`注解将Redis的主机和端口注入到类中。 我们使用`RedisConnectionFactory`和`LettuceConnectionFactory`来创建Redis连接。然后,我们使用`RedisTemplate`来设置连接工厂、键和值的序列化器。 ### 添加缓存注解 接下来,我们需要在服务方法上添加缓存注解。在`com.example.service`包中打开`TaskService`接口,并添加以下代码: ```java public interface TaskService { @Cacheable(value = "tasks") Task createTask(Task task); @Cacheable(value = "tasks") List<Task> getTasks(); @Cacheable(value = "tasks", key = "#id") Task getTaskById(Long id); @Cacheable(value = "tasks", key = "#deadline") List<Task> getTasksByDeadlineBefore(Date deadline); @CacheEvict(value = "tasks", key = "#id") void deleteTask(Long id); } ``` 这些注解将启用Spring缓存,并将服务方法的结果缓存到Redis中。`@Cacheable`注解将结果缓存,并使用`value`指定缓存的名称。`@Cacheable`注解还可以使用`key`指定缓存的键。`@CacheEvict`注解将从缓存中删除指定的条目。 ### 配置Redis缓存管理器 最后,我们需要配置Redis缓存管理器。在`com.example`包中创建一个名为`CacheConfig`的类,并添加以下代码: ```java @Configuration @EnableCaching public class CacheConfig { @Value("${spring.cache.redis.time-to-live}") private Duration timeToLive = Duration.ZERO; @Bean public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(timeToLive) .disableCachingNullValues() .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(configuration) .build(); } } ``` 这个类使用`@Configuration`注解将它标识为一个配置类,并使用`@EnableCaching`注解启用缓存。我们使用`@Value`注解将Redis的过期时间注入到类中。 我们使用`RedisCacheConfiguration`来配置缓存,并设置了过期时间、禁用缓存空值、键和值的序列化器。然后,我们使用`RedisCacheManager`来创建缓存管理器,并将缓存配置和Redis连接工厂传递给它。 ## 总结 现在,我们已经介绍了Spring Data JPA和Redis的整合方法,并通过一个任务管理系统的例子来演示了如何使用注解来定义实体类、自定义`Repository`接口、实现服务接口、创建控制器、配置应用程序、配置`RedisTemplate`、添加缓存注解和配置Redis缓存管理器。这是一个非常有用的项目,可以帮助你深入了解Spring和数据库的知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值