04JavaWeb Day10_基础增强

基础加强

注解 annotation

  • 什么是注解?
    注解和接口、类一样都属于数据类型

  • 注解作用

    1. 编译检查
    2. 配置(后期用的多)
    3. 生成帮助文档
  • 注解特点

    • 注解可以在 变量、方法和类之上加载
    • 注解可以有属性也可以没属性 @Override @Test(timeout=1000)
    • 注解的作用范围 (源码、编译期间、运行期间)
      • 源码期有效:String类之上 @Author、@Since、@See
        作用:使用命令javadoc命令将当前的源码生成帮助文件,可以识别在String类上的相关的注解 \color{red}{代码中的中文注释会导致生成文档失败 暂时不知道怎么解决}
      • 编译器有效:@Override @Deprecated @Susspresswarning
        作用:告诉编译器部分信息
      • 运行期间有效:@Test
        作用: 当我们在当前代码上以JUnit方式运行时, JUnit会运行方法上包含@Test注解的方法
  • 回顾JDK中出现的三种注解:
    @Override、@Deprecated、@Suppresswarning

  • 举例

//以下注解的含义是:抑制编译器发生警告信息(如果有变量未使用,未遵循泛型格式错误不报警告)
@SuppressWarnings("unused")
        int i = 10;
        
//以下注解的含义是:抑制编译器发生警告信息(如果有变量未使用,未遵循泛型格式错误不报警告)
@SuppressWarnings({ "unused", "rawtypes" })
List list = new ArrayList();

//以下注解的含义是:声明以下的方法是过时的方法,不建议大家使用
@Deprecated
public void test2()
{
}
  • 自定义注解
  • 格式:
public @interface 注解名字{
    public 属性类型 属性名字1();
    public 属性类型 属性名称2() default 默认值;
}
自定义注解属性支持的类型:基本数据类型(4类8种),String,Class,Annotation(注解类型),枚举类型,以及以上类型的一维数组类型
  • 注解作用:配置作用
    配置:开发的时候部分信息不希望写死在程序中, 例如数据库的用户名和密码,可以将用户名和密码存放在.txt,.properties,.xml文件中, 利用程序来读取文件中的内容
    例如: 新建一个类继承HttpServlet 然后给类注解 @WebServlet("/DemoServlet") 那么就不用在web.xml中进行servlet的注册和隐射, 如果你创建的wb框架是3.0版本,那么默认是没有web.xml 都是按照注解来配置的
@WebServlet("/DemoServlet")
@WebInitParam(name="name", value="tom")
public class DemoServlet extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        System.out.println("来了一个请求");
        String value = req.getServletContext().getInitParameter("name");
        resp.getWriter().write("hello demoServlet:" + value);
    }
  • 模拟JUnit
  1. 自定义注解@MyTest,通过原注解@Retention和@Target声明当前注解作用域以及目标对象,如果没有声明,在运行期间是无法获取到注解的信息
// 自定义注解 相当于JUnit@Test
// 定义注解的时候, 需要通过元注解Retention说明此注解是运行时注解(class runtime source)
// 约束注解的宿主是什么类型
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest
{
    public int timeout() default -1;
}
  1. 定义UserDao类,创建四个方法addUser delUser getUser uptUser,在前三个方法上加载注解
public class UserDao
{
    @MyTest
    public void addUsr()
    {
        System.out.println("增加用户");
    }
    @MyTest
    public void delUsr()
    {
        System.out.println("删除用户");
    }
    @MyTest
    public void getUsr()
    {
        System.out.println("获取用户");
    }
    public void updateUsr()
    {
        System.out.println("更新用户");
    }
}
  1. 定义类MyJunit ,模拟JUnit
    • 将UserDao.class 文件加载到内存
    • 获取到字节码文件所有的方法
    • 遍历方法,判断每个方法上是否加载了@MyTest注解,有的话执行这个方法
public class MyJunit
{
    public static void main(String[] args) throws Exception
    {
        // 加载UserDao.class 字节码文件中的方法, 判断哪些方法上有自定义注解@MyTest,若有则执行此方法
        // 1. 将UserDao.class 字节码文件加载到内存中, class对象(代表字节码文件在内存中的对象)
        try
        {
            Class clazz = Class.forName("myjava.com.dao.UserDao");
            // 2.获取字节码对象上所有的方法, 返回Method数组对象,数组中的每一个元素都代表Method对象(想当于字节码上的每一个方法)
            Method[] methods = clazz.getMethods();
            for (Method method : methods)
            {
                if (method.isAnnotationPresent(MyTest.class))
                {
                    method.invoke(new UserDao());
                }
            }
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        System.out.println("hello MyJUnit");
    }
}

动态代理 解决网站中文编码问题

装饰者模式

  • 场景: 二次开发的时候, 无法获取到源码,无法使用继承前提下, 要对已经存在对象上的功能进行封装与增强
  • 前提:可以获取到被装饰的对象GoogleCar实现的所有接口
  • 实现思路:自定义装饰类实现ICar接口, 为自定义装饰类传递被装饰的对象
  • 弊端:如果被实现的接口中的方法过多,装饰类中的方法过多冗余

动态代理模式

  • 原理: 通过虚拟机在内存中创建类似MyCar.class文件
  • 前提
  • 字节码加载器: jdk 有一些程序, 专业将各种字节码文件加载到内存, 这类程序简称为字节码加载器
    底层实现过程:利用IO流技术,获取到文件中的数据加载到内存
    共同父类:java.lang.ClassLoader
    分为三种类型:
    引导类加载器 :BootstrapClassLoader 不是类 ClassLoader classLoader = String.class.getClassLoader(); // 由于String.class int.class 等频繁的被加载到内存中 所有用c++加载 所以返回的classloader 是null
    扩展类加载器:ExtClassLoader(extension) 类 ClassLoader classLoader2 = sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader();
    应用类加载器:AppClassLoader
    使用 类.class.getClassLoader()获取加载自己的类加载器。 自己定义的类的加载器都是应用类加载器 System.out.println(TestClassLoader.class.getClassLoader());
  • 动态代理解决全站乱码问题
  1. 使用filter进行请求过滤
  2. 在post请求上 增加 request.setCharacterEncoding("UTF-8");
  3. 在get请求下 进行动态代理
HttpServletRequest myreq = (HttpServletRequest) Proxy.newProxyInstance(ServletFilter.class.getClassLoader(),
                    arg0.getClass().getInterfaces(), new InvocationHandler()
                    {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
                        {
                            Object retObj = null;
                            if (method.getName().equalsIgnoreCase("getParameter"))
                            {
                                retObj = method.invoke(request, args);
                                String val = (String)retObj;
                                val = new String(val.getBytes("iso-8859-1"), "utf-8");
                                System.out.println("val:" + val + "hashcode:" + request.hashCode());
                                return val;
                            }
                            else
                            {
                                retObj = method.invoke(request, args);
                            }
                            return retObj;
                        }
                    });
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容