C# 图书管理系统源码(三层架构,含数据库)

【实例简介】

1、首先保证计算机上已经成功安装SQL Server 2005。

2、将数据库文件附加到数据库中。

3、如果当前计算机装有多个SQL Server 2005实例,请在BookManageSystem目录下打开app.config程序文件,将程序数据库连接字符串localhost改为localhost\你的数据库实例名。如果仅有一个实例,就不用修改了。

4、编译运行即可。

管理员账户和密码:admin admin
读者账户和密码:user user

文件:590m.com/f/25127180-488083780-127562(访问密码:551685)

【实例截图】

C# 图书管理系统源码(三层架构,含数据库)
C# 图书管理系统源码(三层架构,含数据库)
C# 图书管理系统源码(三层架构,含数据库)
以下内容无关:

-------------------------------------------分割线---------------------------------------------

方法日志打印
最近开发遇到的一个问题是关于日志打印。日志非常重要,通过查看日志,我们可以快速排查问题。
我们项目的整个系统内网关处做了拦截,能够看到前端传过来的日志,但是内部服务间调用,服务间的入参与出参看不到;还有,一些重要的方法如果要看到入参和出参,只能一个个去写log方法。
这种重复的工作非常适合使用切面来写一些小工具。下面是我写的小工具,下面方法几乎是搬运一位老哥写的博客,老哥的博客找不见了,sorry。

定义注释类
/**

  • @Description 打印参数

  • @Author lkb

  • @CreateDate: 2021/3/25
    /
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MethodLog {
    }
    AOP 打印输入输出参数
    /
    *

  • @Description

  • @Author lkb

  • @CreateDate: 2021/3/25
    */
    @Aspect
    @Component
    @Slf4j
    public class MethodLogAspect {

    @Pointcut("@annotation(com…annotion.MethodLog)")
    public void pointCut(){}

    @Around(value = “pointCut()”)
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
    try{
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    MethodLog annotation = method.getAnnotation(MethodLog.class);
    if (Objects.isNull(annotation)){
    try {
    return joinPoint.proceed();
    } catch (Throwable throwable) {
    log.error(“method proceed fail. e = {}”, throwable.getMessage(), throwable);
    throw throwable;
    }
    }else{
    String methodName = method.getDeclaringClass().getSimpleName() + “.” + method.getName();
    log.info("methodName: "+methodName);
    Object[] args = joinPoint.getArgs();
    log.info("param: " + JsonUtil.toJSON(args));

             Instant start = Instant.now();
             log.info("method start. methodName = {}", methodName);
             Object result = null;
             try {
                 // 这里的result记得return
                 result = joinPoint.proceed();
             } catch (Throwable throwable) {
                 log.error("method proceed fail. e = {}", throwable.getMessage(), throwable);
                 throw throwable;
             }
    
             log.info("method end. methodName = {}, cost = {}", methodName, ChronoUnit.MILLIS.between(start, Instant.now()));
    
             return result;
         }
     }catch (Exception e){
         log.error("MethodLogAspect around fail. e= {}", e.getMessage(), e);
         throw e;
     }
    

    }
    }

任务切片
遇到的第二个问题是,
在一个调用中,需要多次调用外部系统的服务,本来应该使用MQ去解耦,但是因为多方面原因只能维持现状(我们服务多次调用外部系统的服务)。这样导致整个请求特别慢,上线多台设备的时候可能需要十几二十秒。
与其他两个系统的交互互不影响,相互独立。因此,我想到使用任务切片的方式来加快执行速度。
下面是我写的任务切片小工具。

DTO
/**

  • @Description

  • @Author lkb

  • @CreateDate: 2021/3/26
    */
    @Data
    public class AsynTaskDTO<T, R> {

    public T param;

    public Function<T, R> function;

    public R resultData;

    public Boolean result;

    public String key;

    public AsynTaskDTO(Function<T,R> function, T param){
    this.function = function;
    this.param = param;
    this.result = false;
    this.key = String.valueOf(param.hashCode());
    }

}
任务切片实现类
/**

  • @Description

  • @Author lkb

  • @CreateDate: 2021/3/26
    */
    @Slf4j
    @Getter
    public class AsynTaskUtil {

    private static final ForkJoinPool ASYNC_IO_POOL = new ForkJoinPool((Runtime.getRuntime().availableProcessors() << 1) + 1);

    private List taskDTOS;

    public AsynTaskUtil(List taskDTOS){
    this.taskDTOS = taskDTOS;
    }

    public boolean doTask(){
    CompletableFuture[] futures = taskDTOS.stream().map(task -> CompletableFuture.runAsync(() -> {
    try{
    task.setResultData(task.getFunction().apply(task.getParam()));
    task.setResult(true);
    }catch (Exception e){
    log.error(“AsynTaskUtil doTask fail. e = {}” + e.getMessage(), e);
    task.setResult(false);
    }
    }, ASYNC_IO_POOL)).toArray(CompletableFuture[]::new);

     CompletableFuture.allOf(futures).join();
    
     boolean f = taskDTOS.stream().anyMatch(t -> Objects.equals(false, t.getResult()));
     return !f;
    

    }
    }

上一篇:echart生成饼状图


下一篇:C#应用NPOI实现导出EXcel表格中插入饼状图(可实现动态数据生成)