Java动态代理代码编写

2023-11-17

Java动态代理代码编写

代理的概念

  动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的。

  动态代理技术就是用来产生一个对象的代理对象的。在开发中为什么需要为一个对象产生代理对象呢?
  举一个现实生活中的例子:歌星或者明星都有一个自己的经纪人,这个经纪人就是他们的代理人,当我们需要找明星表演时,不能直接找到该明星,只能是找明星的代理人。比如刘德华在现实生活中非常有名,会唱歌,会跳舞,会拍戏,刘德华在没有出名之前,我们可以直接找他唱歌,跳舞,拍戏,刘德华出名之后,他干的第一件事就是找一个经纪人,这个经纪人就是刘德华的代理人(代理),当我们需要找刘德华表演时,不能直接找到刘德华了(刘德华说,你找我代理人商谈具体事宜吧!),只能是找刘德华的代理人,因此刘德华这个代理人存在的价值就是拦截我们对刘德华的直接访问!
  这个现实中的例子和我们在开发中是一样的,我们在开发中之所以要产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。那么代理对象应该具有什么方法呢?代理对象应该具有和目标对象相同的方法

  所以在这里明确代理对象的两个概念:
    1、代理对象存在的价值主要用于拦截对真实业务对象的访问。
    2、代理对象应该具有和目标对象(真实业务对象)相同的方法。刘德华(真实业务对象)会唱歌,会跳舞,会拍戏,我们现在不能直接找他唱歌,跳舞,拍戏了,只能找他的代理人(代理对象)唱歌,跳舞,拍戏,一个人要想成为刘德华的代理人,那么他必须具有和刘德华一样的行为(会唱歌,会跳舞,会拍戏),刘德华有什么方法,他(代理人)就要有什么方法,我们找刘德华的代理人唱歌,跳舞,拍戏,但是代理人不是真的懂得唱歌,跳舞,拍戏的,真正懂得唱歌,跳舞,拍戏的是刘德华,在现实中的例子就是我们要找刘德华唱歌,跳舞,拍戏,那么只能先找他的经纪人,交钱给他的经纪人,然后经纪人再让刘德华去唱歌,跳舞,拍戏。

 

java中的代理

"java.lang.reflect.Proxy"类介绍

  现在要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。在java中如何用程序去生成一个对象的代理对象呢,java在JDK1.5之后提供了一个"java.lang.reflect.Proxy"类,通过"Proxy"类提供的一个newProxyInstance方法用来创建一个对象的代理对象,如下所示:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

 newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler h用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。

 

编写生成代理对象的类

  在java中规定,要想产生一个对象的代理对象,那么这个对象必须要有一个接口,所以我们第一步就是设计这个对象的接口,在接口中定义这个对象所具有的行为(方法)

  1、定义对象的行为接口

package cn.gacl.proxy;
 
 /**
 * @ClassName: Person
 * @Description: 定义对象的行为
 *
 */ 
 public interface Person {
 
     /**
     * @Method: sing
     * @Description: 唱歌
     * @Anthor:孤傲苍狼
     *
     * @param name
    * @return
     */ 
     String sing(String name);
     /**
     * @Method: sing
     * @Description: 跳舞
     * @Anthor:孤傲苍狼
     *
     * @param name
     * @return
     */ 
     String dance(String name);
 }

  2、定义目标业务对象类

 package cn.gacl.proxy;
 
 /**
 * @ClassName: LiuDeHua
 * @Description: 刘德华实现Person接口,那么刘德华会唱歌和跳舞了
 *
 */ 
 public class LiuDeHua implements Person {
 
     public String sing(String name){
         System.out.println("刘德华唱"+name+"歌!!");
         return "歌唱完了,谢谢大家!";
     }
     
     public String dance(String name){
         System.out.println("刘德华跳"+name+"舞!!");
         return "舞跳完了,多谢各位观众!";
     }
 }

  3、创建生成代理对象的代理类

package cn.gacl.proxy;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
 /**
 * @ClassName: LiuDeHuaProxy
 * @Description: 这个代理类负责生成刘德华的代理人
 *
 */ 
 public class LiuDeHuaProxy {
 
     //设计一个类变量记住代理类要代理的目标对象
     private Person ldh = new LiuDeHua();
     
     /**
     * 设计一个方法生成代理对象
     * @Method: getProxy
     * @Description: 这个方法返回刘德华的代理对象:Person person = LiuDeHuaProxy.getProxy();//得到一个代理对象
     * @return 某个对象的代理对象
     */ 
     public Person getProxy() {
         //使用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)返回某个对象的代理对象
         return (Person) Proxy.newProxyInstance(LiuDeHuaProxy.class
                 .getClassLoader(), ldh.getClass().getInterfaces(),
                 new InvocationHandler() {
                    /**
                     * InvocationHandler接口只定义了一个invoke方法,因此对于这样的接口,我们不用单独去定义一个类来实现该接口,
                     * 而是直接使用一个匿名内部类来实现该接口,new InvocationHandler() {}就是针对InvocationHandler接口的匿名实现类
                      */
                     /**
                      * 在invoke方法编码指定返回的代理对象干的工作
                      * proxy : 把代理对象自己传递进来 
                      * method:把代理对象当前调用的方法传递进来 
                      * args:把方法参数传递进来
                      * 
                      * 当调用代理对象的person.sing("冰雨");或者 person.dance("江南style");方法时,
                      * 实际上执行的都是invoke方法里面的代码,
                      * 因此我们可以在invoke方法中使用method.getName()就可以知道当前调用的是代理对象的哪个方法
                      */
                     @Override
                     public Object invoke(Object proxy, Method method,
                             Object[] args) throws Throwable {
                         //如果调用的是代理对象的sing方法
                         if (method.getName().equals("sing")) {
                           System.out.println("我是他的经纪人,要找他唱歌得先给十万块钱!!");
                             //已经给钱了,经纪人自己不会唱歌,就只能找刘德华去唱歌!
                             return method.invoke(ldh, args); //代理对象调用真实目标对象的sing方法去处理用户请求
                         }
                         //如果调用的是代理对象的dance方法
                         if (method.getName().equals("dance")) {
                             System.out.println("我是他的经纪人,要找他跳舞得先给二十万块钱!!");
                             //已经给钱了,经纪人自己不会唱歌,就只能找刘德华去跳舞!
                             return method.invoke(ldh, args);//代理对象调用真实目标对象的dance方法去处理用户请求
                         }
 
                         return null;
                     }
                 });
     }
 }

 测试代码:

package cn.gacl.proxy;
 
 public class ProxyTest {
     
     public static void main(String[] args) {
         
         LiuDeHuaProxy proxy = new LiuDeHuaProxy();
         //获得代理对象
         Person p = proxy.getProxy();
         //调用代理对象的sing方法
         String retValue = p.sing("冰雨");
         System.out.println(retValue);
         //调用代理对象的dance方法
         String value = p.dance("江南style");
         System.out.println(value);
     }
 }

  运行结果如下:

  
  Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。
  由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。

 

动态代理应用

  在动态代理技术里,由于不管用户调用代理对象的什么方法,都是调用开发人员编写的处理器的invoke方法(这相当于invoke方法拦截到了代理对象的方法调用)。并且,开发人员通过invoke方法的参数,还可以在拦截的同时,知道用户调用的是什么方法,因此利用这两个特性,就可以实现一些特殊需求,例如:拦截用户的访问请求,以检查用户是否有访问权限、动态为某个对象添加额外的功能。

在字符过滤器中使用动态代理解决中文乱码

  在平时的JavaWeb项目开发中,我们一般会写一个CharacterEncodingFilter(字符过滤器)来解决整个JavaWeb应用的中文乱码问题,如下所示:

package me.gacl.web.filter;
 
 import java.io.IOException;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
 /**
 * @ClassName: CharacterEncodingFilter
 * @Description: 解决中文乱码的字符过滤器
 *
 */ 
 public class CharacterEncodingFilter implements Filter {

     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
 
     }
 
     @Override
     public void doFilter(ServletRequest request, ServletResponse response,
             FilterChain chain) throws IOException, ServletException {
         //解决以Post方式提交的中文乱码问题
         request.setCharacterEncoding("UTF-8");
         response.setCharacterEncoding("UTF-8");
         response.setContentType("text/html;charset=UTF-8");
         chain.doFilter(request, response);
     }
 
     @Override
     public void destroy() {
 
     }
 }

 但是这种写法是没有办法解决以get方式提交中文参数时的乱码问题的,我们可以用如下的代码来证明上述的解决中文乱码过滤器只对以post方式提交中文参数时有效,而对于以get方式提交中文参数时无效

  jsp测试页面如下:

 <%@ page language="java" pageEncoding="UTF-8"%>
 <%--引入jstl标签库 --%>
 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
 <!DOCTYPE HTML>
 <html>
   <head>
     <title>使用字符过滤器解决解决get、post请求方式下的中文乱码问题</title>
   </head>
   <body>
        <%--使用c:url标签构建url,构建好的url存储在servletDemo1变量中--%>
        <c:url value="/servlet/ServletDemo1" scope="page" var="servletDemo1">
            <%--构建的url的附带的中文参数 ,参数名是:username,值是:孤傲苍狼--%>
           <c:param name="username" value="孤傲苍狼"></c:param>
        </c:url>
       <%--使用get的方式访问 --%>
        <a href="${servletDemo1}">超链接(get方式请求)</a>
        <hr/>
        <%--使用post方式提交表单 --%>
        <form action="${pageContext.request.contextPath}/servlet/ServletDemo1" method="post">
            用户名:<input type="text" name="username" value="孤傲苍狼" />
            <input type="submit" value="post方式提交">
        </form>
        
   </body>
 </html>

  处理请求的ServletDemo1代码如下:

 package me.gacl.web.controller;
 
 import java.io.IOException;
 import java.io.PrintWriter;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 public class ServletDemo1 extends HttpServlet {
 
     public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         // 接收参数
         String username = request.getParameter("username");
         // 获取请求方式
         String method = request.getMethod();
         // 获取输出流
         PrintWriter out = response.getWriter();
         out.write("请求的方式:" + method);
         out.write("<br/>");
         out.write("接收到的参数:" + username);
     }
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
 }

 在web.xml中注册上述的CharacterEncodingFilter和ServletDemo1

 <filter>
       <filter-name>CharacterEncodingFilter</filter-name>
       <filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class>
   </filter>
  
   <filter-mapping>
       <filter-name>CharacterEncodingFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
   
   <servlet>
     <servlet-name>ServletDemo1</servlet-name>
     <servlet-class>me.gacl.web.controller.ServletDemo1</servlet-class>
   </servlet>
 
   <servlet-mapping>
     <servlet-name>ServletDemo1</servlet-name>
     <url-pattern>/servlet/ServletDemo1</url-pattern>
   </servlet-mapping>    

  测试结果如下所示:

 从运行结果可以看出,上述的过滤器的确是不能解决以get方式提交中文参数的乱码问题,下面使用动态代理技术改造上述的过滤器,使之能够解决以get方式提交中文参数的乱码问题,改造后的过滤器代码如下:

package me.gacl.web.filter;
 
 import java.io.IOException;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 /**
 * @ClassName: CharacterEncodingFilter
 * @Description: 解决中文乱码的字符过滤器
 *
 */ 
 public class CharacterEncodingFilter implements Filter {
 
     @Override
     public void init(FilterConfig filterConfig) throws ServletException {
 
     }
 
   @Override
     public void doFilter(ServletRequest req, ServletResponse resp,
             FilterChain chain) throws IOException, ServletException {
         
         final HttpServletRequest request = (HttpServletRequest) req;
         HttpServletResponse response = (HttpServletResponse) resp;
         //解决以Post方式提交的中文乱码问题
         request.setCharacterEncoding("UTF-8");
         response.setCharacterEncoding("UTF-8");
         response.setContentType("text/html;charset=UTF-8");
         //获取获取HttpServletRequest对象的代理对象
         ServletRequest requestProxy = getHttpServletRequestProxy(request);
         /**
          * 传入代理对象requestProxy给doFilter方法,
          * 这样用户在使用request对象时实际上使用的是HttpServletRequest对象的代理对象requestProxy
          */
         chain.doFilter(requestProxy, response);
     }
 
     
     /**
     * @Method: getHttpServletRequestProxy
     * @Description: 获取HttpServletRequest对象的代理对象
     *
     * @param request
     * @return HttpServletRequest对象的代理对象
     */ 
     private ServletRequest getHttpServletRequestProxy(final HttpServletRequest request){
         ServletRequest proxy  = (ServletRequest) Proxy.newProxyInstance(
                 CharacterEncodingFilter.class.getClassLoader(),
                 request.getClass().getInterfaces(),   
              new InvocationHandler(){
                     @Override
                     public Object invoke(Object proxy, Method method, Object[] args)
                             throws Throwable {
                         //如果请求方式是get并且调用的是getParameter方法
                        if (request.getMethod().equalsIgnoreCase("get") && method.getName().equals("getParameter")) {
                             //调用getParameter方法获取参数的值
                             String value = (String) method.invoke(request, args);
                             if(value==null){
                                 return null;
                             }
                             //解决以get方式提交的中文乱码问题
                             return new String(value.getBytes("iso8859-1"),"UTF-8");
                         }else {
                             //直接调用相应的方法进行处理
                             return method.invoke(request, args);
                         }
                     }
                 });
         //返回HttpServletRequest对象的代理对象
         return proxy;
     }
     
     @Override
     public void destroy() {
 
     }
 }

  我们在过滤器中使用动态代理技术生成一个HttpServletRequest对象的代理对象requestProxy,然后把代理对象requestProxy进行chain.doFilter(requestProxy, response)传递给用户使用,这样用户实际上使用的就是HttpServletRequest对象的代理对象requestProxy。然而这一过程对于用户来说是透明的,用户是不知道自己使用的HttpServletRequest对象是一个代理对象requestProxy,由于代理对象requestProxy和目标对象HttpServletRequest具有相同的方法,当用户调用getParameter方法接收中文参数时,实际上调用的就是代理对象requestProxy的invoke方法,因此我们就可以在invoke方法中就判断当前的请求方式以及用户正在调用的方法,如果判断当前的请求方式是get方式并且用户正在调用的是getParameter方法,那么我们就可以手动处理get方式提交中文参数的中文乱码问题了。

  测试结果如下所示:

 

在字符过滤器中使用动态代理压缩服务器响应的内容后再输出到客户端

  压缩过滤器的代码如下:

  package me.gacl.web.filter;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  import java.util.zip.GZIPOutputStream;
  
  import javax.servlet.Filter;
  import javax.servlet.FilterChain;
  import javax.servlet.FilterConfig;
  import javax.servlet.ServletException;
  import javax.servlet.ServletOutputStream;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  /**
  * @ClassName: GzipFilter
  * @Description: 压缩过滤器,将web应用中的文本都经过压缩后再输出到浏览器
  *
  */ 
  public class GzipFilter implements Filter {
  
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
  
      }
  
      @Override
      public void doFilter(ServletRequest req, ServletResponse resp,
             FilterChain chain) throws IOException, ServletException {
          
          final HttpServletRequest request = (HttpServletRequest) req;
         final HttpServletResponse response = (HttpServletResponse) resp;
         final ByteArrayOutputStream bout = new ByteArrayOutputStream();
          final PrintWriter pw = new PrintWriter(new OutputStreamWriter(bout,"UTF-8"));
          
          chain.doFilter(request, getHttpServletResponseProxy(response, bout, pw));
          pw.close();
          //拿到目标资源的输出
          byte result[] = bout.toByteArray();
          System.out.println("原始大小:" + result.length);
          
          ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
          GZIPOutputStream gout = new GZIPOutputStream(bout2);
          gout.write(result);
          gout.close();
         
          //拿到目标资源输出的压缩数据
          byte gzip[] = bout2.toByteArray();
         System.out.println("压缩大小:" + gzip.length);
          
          response.setHeader("content-encoding", "gzip");
          response.setContentLength(gzip.length);
          response.getOutputStream().write(gzip);
      }
  
      /**
      * @Method: getHttpServletResponseProxy
      * @Description: 获取HttpServletResponse对象的代理对象
      * @param response
      * @param bout
      * @param pw
      * @return HttpServletResponse对象的代理对象
      */ 
     private ServletResponse getHttpServletResponseProxy(
              final HttpServletResponse response,
              final ByteArrayOutputStream bout, 
              final PrintWriter pw) {
          
          return (ServletResponse) Proxy.newProxyInstance(GzipFilter.class.getClassLoader(), 
                  response.getClass().getInterfaces(), 
                  new InvocationHandler(){
                      @Override
                      public Object invoke(Object proxy, Method method, Object[] args)
                              throws Throwable {
                          if(method.getName().equals("getWriter")){
                              return pw; 
                          }else if(method.getName().equals("getOutputStream")){
                              return new MyServletOutputStream(bout);
                          }else{
                              return method.invoke(response, args);
                         }
                     }
                  });
      }
  
      @Override
     public void destroy() {
  
     }

     class MyServletOutputStream extends ServletOutputStream{
         
         private ByteArrayOutputStream  bout = null;
         public MyServletOutputStream(ByteArrayOutputStream  bout){
             this.bout = bout;
         }
         @Override
         public void write(int b) throws IOException {
             bout.write(b);
         }
        
     }
 }

 在web.xml中注册上述的GzipFilter

  <filter>
       <description>配置压缩过滤器</description>
       <filter-name>GzipFilter</filter-name>
       <filter-class>me.gacl.web.filter.GzipFilter</filter-class>
   </filter>
   
   <!--jsp文件的输出的内容都经过压缩过滤器压缩后才输出 -->
   <filter-mapping>
       <filter-name>GzipFilter</filter-name>
       <url-pattern>*.jsp</url-pattern>
       <!-- 配置过滤器的拦截方式-->
       <!-- 对于在Servlet中通过
           request.getRequestDispatcher("jsp页面路径").forward(request, response) 
       方式访问的Jsp页面的要进行拦截 -->
       <dispatcher>FORWARD</dispatcher>
       <!--对于直接以URL方式访问的jsp页面进行拦截,过滤器的拦截方式默认就是REQUEST-->
      <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
   <!--js文件的输出的内容都经过压缩过滤器压缩后才输出 -->
   <filter-mapping>
       <filter-name>GzipFilter</filter-name>
      <url-pattern>*.js</url-pattern>
   </filter-mapping>
   <!--css文件的输出的内容都经过压缩过滤器压缩后才输出 -->
   <filter-mapping>
       <filter-name>GzipFilter</filter-name>
       <url-pattern>*.css</url-pattern>
   </filter-mapping>
   <!--html文件的输出的内容都经过压缩过滤器压缩后才输出 -->
   <filter-mapping>
       <filter-name>GzipFilter</filter-name>
       <url-pattern>*.html</url-pattern>
   </filter-mapping>

 GzipFilter过滤器会将*.jsp,*.js,*.css,*.html这些文件里面的文本内容都经过压缩后再输出到客户端显示。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java动态代理代码编写 的相关文章

  • Groovy语言详解

    一 Groovy 概述 Groovy是一种基于Java平台的面向对象语言 Groovy 1 0于2007年1月2日发布 其中Groovy 2 4是当前的主要版本 Groovy通过Apache License v 2 0发布 Groovy中有
  • 深入学习java源码之Integer.parseInt()与Integer.valueOf()

    深入学习java源码之Integer parseInt 与Integer valueOf 一般我们创建一个类的时候是通过new关键字 比如 Object obj new Object 但是对于 Integer 类 我们却可以这样 Integ
  • 深入学习java源码之Math.scalb()与 Math.powerOfTwoF()

    深入学习java源码之Math scalb 与 Math powerOfTwoF final关键字 final在Java中是一个保留的关键字 可以声明成员变量 方法 类以及本地变量 一旦你将引用声明作final 你将不能改变这个引用了 编译
  • java泛型代码编写

    java泛型代码编写 泛型的由来 我们先看下面这段代码 List list new ArrayList list add 24 向集合中添加一个 Integer 类型的数据 list add Tom 向集合中添加一个 String 类型的数
  • Unsafe初探

    Unsafe Unsafe 是sun misc Unsafe下的一个包 通过这个类可以直接使用底层native方法来获取和操作底层的数据 例如获取一个字段在内存中的偏移量 利用偏移量直接获取或修改一个字段的数据等等 当然这个类正如他的名字一
  • 深入学习java源码之ArrayList.addAll()与ArrayList.retainAll()

    深入学习java源码之ArrayList addAll 与ArrayList retainAll 引入多态 List是接口 所以实现类要把接口中的抽象方法全部重写 在重写的时候父类中的方法的时候 操作的数据类型也是要与父类保持一致的 所以父
  • Spring Bean生命周期doCreateBean源码阅读

    bean的生命周期的几个后置接口都是在这个方法里面调用 所以单独开一篇该方法的源码阅读 下面从两个点来阅读 1 何时调用 只看容器启动 2 梳理这个方法的流程 跟上一节对应上 先贴上源码 protected Object doCreateB
  • 深入学习java源码之ArrayList.iterator()与ArrayList.listIterator()

    深入学习java源码之ArrayList iterator 与ArrayList listIterator 内部类的使用典型的情况是 内部类继承自某个类或实现某个接口 内部类的代码操作创建其的外层类的对象 所以你可以认为内部类提供了某种进入
  • 深入学习java源码之Byte.decode()与Byte.toUnsignedInt()

    深入学习java源码之Byte decode 与Byte toUnsignedInt 异常 异常就是有异于常态 和正常情况不一样 有错误出错 在java中 阻止当前方法或作用域的情况 称之为异常 其中Error类中包括虚拟机错误和线程死锁
  • Java多线程代码编写

    Java多线程代码编写 什么是多线程 并发和并行 并行 指两个或多个时间在同一时刻发生 同时发生 并发 指两个或多个事件在一个时间段内发生 在操作系统中 安装了多个程序 并发指的是在一段时间内宏观上有多个程序同时运行 这在单 CPU 系统中
  • Java动态代理代码编写

    Java动态代理代码编写 代理的概念 动态代理技术是整个java技术中最重要的一个技术 它是学习java框架的基础 不会动态代理技术 那么在学习Spring这些框架时是学不明白的 动态代理技术就是用来产生一个对象的代理对象的 在开发中为什么
  • 堵塞队列之ArrayBlockingQueue和LinkedBlockingQueue解析

    在线程池创建的时候 需要传一个堵塞队列来维护需要执行的线程任务 其中最常用的是ArrayBlockingQueue和LinkedBlockingQueue 他们都继承了BlockingQueue接口 ArrayBlockingQueue 一
  • 使用java关键字编写代码

    使用java关键字编写代码 java的关键字 java的基本数据类型 Java是一种强类型语言 必须为每一个变量声明一种类型 Java共包含8中基本类型 其中4种整型 2种浮点型 1种用于表示Unicode编码的字符单元的字符类型char和
  • 线程池面试题

    线程池面试题 1 Executor 框架三大组成部分 2 ThreadPoolExecutor 类 线程池执行器 核心 2 1 ThreadPoolExecutor 3 个最重要的参数 2 2 ThreadPoolExecutor 饱和策略
  • 基于java中SSM框架+小程序实现乐器商城程序设计演示【附项目源码】

    基于java中SSM框架 小程序实现乐器商城程序设计演示 JAVA简介 JAVA语言是目前软件市场上应用最广泛的语言开发程序 可以在多种平台上运用的 兼容性比较强 适应市面上大多数操作系统 不会出现乱码的现像 其扩展性和维护性都更好 具有分
  • 基于springboot+vue实现汽车改装方案网站演示【附项目源码+论文说明】

    基于springboot vue实现汽车改装方案网站演示 摘要 本文主要讲述了基于SpringBoot MySql开发技术开发的汽车改装方案网站的设计与实现 这里的汽车改装方案网站是通过一个平台使所有的汽车爱好者们可以不用出门就可以体验到专
  • 基于springboot+vue实现实企业任务管理追踪系统【附项目源码+论文说明】

    基于springboot vue实现实企业任务管理追踪系统 摘要 随着时代的进步 人们现在通过计算机线上化的办公方式成功的提升了日常办公的效率 通过线上办公能够有效地提升信息传递的效率 可以快速的完成任务的流程处理 邮件的发送等等功能 并且
  • 基于springboot+vue实现流浪动物救助平台演示【附项目源码+论文说明】

    基于springboot vue实现流浪动物救助平台演示 摘要 随着人们对于动物及环境保护的意识越来越强 流浪动物的救助与保护涉及到了健康卫生以及城市容貌等多个方面 流浪动物保护是一个全球性的问题 不同的国家和地区都出台了形式多样的保护办法
  • 基于springboot+vue实现食品安全管理系统演示【附项目源码+论文说明】

    基于springboot vue实现食品安全管理系统演示 摘要 食品行业同其他行业有很多的差别 食品行业不仅要管食品的生产和销售 还要管食品的库存和保质期 那么对于食品管理者来说 就存在着一定的难度 况且食品的种类复杂 存储条件各不相同 存
  • 基springboot+vue实现开放实验室管理系统子系统【附项目源码+论文说明】

    基springboot vue实现开放实验室管理系统子系统 摘要 信息技术永远是改变生活的第一种创新方式 各种行业的发展更是脱离不了科技化的支持 原本传统的行业正在被科技行业的切入悄悄的发生变化 就拿我们生活当中常见的事情举例而言 在外卖行

随机推荐

  • 人才盘点的主角是业务部门负责人还是HR?

    你的企业 是否存在以下问题 人才储备不足 关键岗位人员离职后 没有合适的马上接替 人才质量不高 企业战略变革转型期 不知谁可以引领和驱动变革 人才现状不清 新的业务 新的项目要开拓 不知合适的人才在哪里 人才分布不均 成熟业务部门人才扎堆
  • gin框架38--使用中间件

    gin框架38 使用中间件 介绍 案例 说明 介绍 本文主要介绍如何在gin框架中使用中间件 并通过案例加以说明 使用MyBenchLogger中间件来输出特有的日志 用AuthRequire中间件来实现基础认证 案例 package ma
  • Cost function

    cost function的形式 cost function的推导满足以下过程 1 认为error 满足某个分布 写出样本点xi的样本的error 2 认为样本点是相互独立的 推导出其对数似然函数 3 求偏导 是得导函数为0 分离常数部分
  • Java 高精度计算 BigDecimal 和 BigInteger

    BigDecimal 在 Java 中 表示小数值一般使用 float 或者 double 类型 可以用于科学计算或者工程计算等 数学意义上的小数是连续的 但 float 和 double 只能表示其中的一些离散点 如果我们要表示的数值刚好
  • Webpack 中常用的loader和plugin已经webpack如何配置

    dist文件夹存放打包后的文件 动态获取出口路径 需要有webpack init 生成package js文件 1 1webpack是什么 webpack 是一种前端资源构建工具 一个静态模块打包器 modulebundler 在 webp
  • IEnumerable vs IEnumerator

    对对象的存储对每一种语言都很重要 例如C 中的Iterator C 中的IEnumerator Java中的Iterator等 C 所有的集合类都定义了一个叫iterator的数据成员 可以通过此对象实现对集合的traverse vecto
  • kafka权威指南中文版之三

    第三章kafka producer 向kafka写入消息 无论你将kafka作为一个消息队列 或者消息总线 还是一个数据存储平台 你都要通过生产者producer向kafka写入数据 通过消费者consumer读取kafka的数据 例如 一
  • 微信支付流程

    一 微信支付流程 APP用户点击进行支付 会向我们自己的订单服务发送请求 携带订单的相关信息 订单服务接收到请求之后需要保存订单 调用微信统一下单接口生成预支付订单 微信会返回预支付订单标识 订单服务会根据微信返回的标识生成带签名的支付信息
  • SQL 注入-盲注

    目录 一 什么时候用到盲注 二 盲注的优缺点 三 盲注的流程 四 盲注的分类 五 布尔盲注 5 1 原理以及什么时候使用布尔盲注 5 2 例如upload labs靶场中的Less 8 5 3 布尔盲注常用函数及定义 5 4 length
  • PyQt5 第一章 PyQt5简介和安装

    第一章 PyQt5简介和安装 零基础入门玩转 PyQt5 邀请码 LWskm3AS 1 1 PyQt5 简介 PyQt5是Digia的一套Qt5应用框架与python的结合 同时支持2 x和3 x Qt库由Riverbank Computi
  • 计算机与图像处理论文标题,数字图像处理论文各种题目.doc

    数字图像处理论文各种题目 待处理图片 参考最终效果图 29利用中值空间滤波去去除波形噪声 要求 掌握空间滤波原理 了解中值空间滤波在实际中的应用 利用MATLAB实现对波形的中值滤波 改进算子 使图像达到标准对照图像效果 待处理图片 处理后
  • webpack html 引入cdn,Webpack如何引入CDN连接来优化编译后的体积

    背景 在 Vue 项目中 引入到工程中的全部 js 文件 编译时都会被打包进 vendor js 也就致使了 vendor js 文件体积变得至关臃肿 必定程度上影响着页面的渲染 为了减小编译后的体积 提升页面渲染速度 咱们能够经过引入 C
  • python时间戳转换年,月,日,季度,周

    数据结构 def q year day week day dict 0 星期一 1 星期二 2 星期三 3 星期四 4 星期五 5 星期六 6 星期天 for x in range 0 366 time item star time int
  • github上传的报错的问题解决

    文章目录 前言 一 遇见的问题 二 开始配置ssh key 这就完成了 可以重新尝试一下上面代码到github 前言 有很多伙伴们在操作github时候 上传代码的时候 会有报错问题 上传代码失败 这里我给出我本人的的解决办法 一 遇见的问
  • Sakura美化

    文章原地址在 我的博客 接上次的文章 闲着也是闲着 不如搭个免费的博客玩玩 0 前言 做hexo的美化工作 主要是 修改布局文件 HTML模板ejs文件 添加功能 做好CSS 还是得对HTML 结构 CSS 表现 Javascript 行为
  • 【华为OD机试真题 Python】整理扑克牌 (A卷2022Q4)

    前言 本专栏将持续更新华为OD机试题目 并进行详细的分析与解答 包含完整的代码实现 希望可以帮助到正在努力的你 关于OD机试流程 面经 面试指导等 如有任何疑问 欢迎联系我 wechat steven moda email nansun09
  • python数据容器--集合的常用操作

    python数据容器 集合的常用操作 数据是无序存储的 不支持下标索引 不允许重复数据的存在 set集合基本操作 my set 传智教育 itheima 黑马程序员 添加新元素 my set add python print f 添加元素后
  • Mysql mysqldump备份数据

    mysqldump客户端实用程序执行逻辑备份 生成一组 SQL 语句 可以执行这些语句来重现原始数据库对象定义和表数据 它转储一个或多个 MySQL 数据库以进行备份或传输到另一台 SQL 服务器 mysqldump 命令还可以生成 CSV
  • C++实验一:简单数据及运算(解方程、海伦公式求三角形面积)

    实验目的 1 掌握C 中的基本数据类型的算术运算和逻辑运算 2 理解并掌握C 中运算符的优先级 3 掌握简单的类型转换方法 4 掌握C 的math头文件中常用的几种数学运算 5 了解visual studio的debug功能 并使用debu
  • Java动态代理代码编写

    Java动态代理代码编写 代理的概念 动态代理技术是整个java技术中最重要的一个技术 它是学习java框架的基础 不会动态代理技术 那么在学习Spring这些框架时是学不明白的 动态代理技术就是用来产生一个对象的代理对象的 在开发中为什么