zoukankan      html  css  js  c++  java
  • 基础加强

    基础加强

    今日任务

    • 使用自定义注解完成仿@Test的作用.
    • 使用Servlet3.0完成文件上传.
    • 使用动态代理解决网站的字符集编码

    教学导航

    教学目标

    了解JDK中提供的三个注解

    会自定义注解及注解的反射.

    能够简单使用Servlet3.0

    掌握动态代理技术

    了解类加载器

    教学方法

    案例驱动法

    1.1 案例一:使用自定义注解完成@Test注解功能类似的效果:

    1.1.1 需求

    使用Junit是单元测试的工具.在一个类中使用 @Test 对程序中的方法进行测试.

    自定义一个注解@MyTest 也将这个注解加在类的方法上. 使这个方法得到执行.

    1.1.2 分析:

    1.1.2.1 技术分析:

    • 【注解】

    程序中有 注释 和注解

    * 注释:给开发人员.

    * 注解:给计算机看的.

     

    注解使用:学习框架支持注解开发.

    • JDK提供的注解】

    @Override :描述方法的重写.

    @SuppressWarnings :压制警告.

    @Deprecated :标记过时.

    • 自定义注解:

    定义一个类:class

    定义一个借口:interface

    定义一个枚举:enum

    定义一个注解:@interface

     

    【自定义注解案例】

    @interface MyAnno1{

     

    }

     

    带有属性的注解:

    @interface MyAnno2{

    int a() default 1;

    String b();

    // 注解属性的类型:基本数据类型,字符串类型String,Class,注解类型,枚举类型,以及以上类型的一维数组.

    // Date d();

    Class clazz();

    MyAnno3 m3(); // 注解

    Color c(); // 枚举

    String[] arrs();

     

    }

     

    @MyAnno4("aaa") // 如果属性名称为value 那么使用的时候 value可以省略(只出现这一个value的属性情况下).

    public class AnnotationDemo3 {

     

    }

     

    @interface MyAnno4{

    String value();

    int a() default 1;

    }

    1.1.2.2 步骤分析:

    定义一个测试类

    public class AnnotationDemo3 {

     

    @MyTest

    public void demo1(){

    System.out.println("demo1执行了...");

    }

     

    @MyTest

    public void demo2(){

    System.out.println("demo2执行了...");

    }

     

    public void demo3(){

    System.out.println("demo3执行了...");

    }

    }

    定义核心运行类:

    在核心运行类中有一个主函数:

    获得测试类中的所有的方法.

    获得每个方法,查看方法上是否有@MyTest注解.

    如果有这个注解,让这个方法执行.

    1.1.3 代码实现:

    通过元注解定义注解存在的阶段.

    * 元注解也是一个注解:修饰注解的 注解.

     

    自定义一个注解:

     

    核心运行类:

    public class CoreRunner {

     

    public static void main(String[] args) {

    // 反射:获得类的字节码对象.Class

    Class clazz = AnnotationDemo3.class;

    // 获得测试类中的所有的方法:

    Method[] methods = clazz.getMethods();

    // 遍历数组:

    for (Method method : methods) {

    // System.out.println(method.getName());

    // 判断方法上是否有@MyTest注解:

    boolean flag = method.isAnnotationPresent(MyTest.class);

    // System.out.println(method.getName()+"   "+flag);

    if(flag){

    // 让这个方法执行:

    try {

    method.invoke(clazz.newInstance(), null);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    }

     

    }

    1.1.4 总结:

    使用注解完成JDBC工具类的编写:(了解)

    public class JDBCUtils {

    private static  String driverClass;

    private static  String url;

    private static  String username;

    private static  String password;

     

    @JDBCInfo

    public static Connection getConnection() throws Exception{

    // 反射:

    Class clazz = JDBCUtils.class;

     

    Method method = clazz.getMethod("getConnection", null);

     

    // 获得方法上的注解:

    JDBCInfo jdbcInfo = method.getAnnotation(JDBCInfo.class);

    driverClass = jdbcInfo.driverClass();

    url = jdbcInfo.url();

    username = jdbcInfo.username();

    password = jdbcInfo.password();

     

    Class.forName(driverClass);

    Connection conn = DriverManager.getConnection(url, username, password);

     

    return conn;

    }

    }

    1.2 案例二:使用Servlet3.0技术完成文件的上传:

    1.2.1 需求:

     

    1.2.2 分析:

    1.2.2.1 技术分析:

    Servlet3.0

    Servlet3.0 Servlet2.5

        * Servlet3.0需要运行在tomcat7以上的服务器中.

        * Servlet3.0以后web.xml就不是必须的.

    1.Servlet3.0支持注解开发.

    2.支持文件上传.

    Servlet3.0支持注解开发】

    使用@WebServlet替换web.xml中配置的Servlet

    @WebServlet(urlPatterns="/ServletDemo1",loadOnStartup=2,initParams=@WebInitParam(name="username",value="root"))

     

    使用@WebListener替换web.xml中监听器的配置:

    @WebListener

     

    使用@WebFilter替换web.xml中的过滤器的配置:

    @WebFilter(urlPatterns="/*")

    Servlet3.0的文件上传】

    • 文件上传:

    文件上传:指的是将本地的文件 写到 服务器上.

    • 文件上传的要素:

    1.表单的提交的方式必须是POST.

    2.表单中必须有一个文件上传项:<input type=”file”>,而且文件上传项必须有name属性和值.

        * <input type=”file” name=”upload”/>

    3.表单的enctype属性的值必须是multipart/form-data

    • 文件上传的抓包分析:

    未修改enctype属性的时候:

     

    POST /WEB17_WEB/demo1/demo1.jsp HTTP/1.1

    Accept: text/html, application/xhtml+xml, */*

    X-HttpWatch-RID: 22325-10011

    Referer: http://localhost:8080/WEB17_WEB/demo1/demo1.jsp

    Accept-Language: zh-Hans-CN,zh-Hans;q=0.5

    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko

    Content-Type: application/x-www-form-urlencoded

    Accept-Encoding: gzip, deflate

    Host: localhost:8080

    Content-Length: 47

    Connection: Keep-Alive

    Cache-Control: no-cache

    Cookie: JSESSIONID=99CD51DA9A47D29200168968AD983E9E

     

    upload=C%3A%5CUsers%5Capple%5CDesktop%5Caaa.txt

     

    已经修改了enctype属性:

    POST /WEB17_WEB/demo1/demo1.jsp HTTP/1.1

    Accept: text/html, application/xhtml+xml, */*

    X-HttpWatch-RID: 22325-10026

    Referer: http://localhost:8080/WEB17_WEB/demo1/demo1.jsp

    Accept-Language: zh-Hans-CN,zh-Hans;q=0.5

    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko

    Content-Type: multipart/form-data; boundary=---------------------------7e02e526160b66

    Accept-Encoding: gzip, deflate

    Host: localhost:8080

    Content-Length: 224

    Connection: Keep-Alive

    Cache-Control: no-cache

    Cookie: JSESSIONID=99CD51DA9A47D29200168968AD983E9E

     

    -----------------------------7e02e526160b66

    Content-Disposition: form-data; name="upload"; filename="C:UsersappleDesktopaaa.txt"

    Content-Type: text/plain

     

    Hello shouyi

    -----------------------------7e02e526160b66—

    【文件上传的原理】

    根据分割线将请求体的部分分成几块:

    * 判断 每块是 普通项还是文件上传项.

        * 普通项:获得名称和值.

        * 文件上传项:获得文件名 和 文件内容输入流.

    【文件上传的技术】

    JspSmartUpload: jspSmartUpload组件是应用JSP进行B/S程序开发过程中经常使用的上传下载组件,它使用简单,方便。现在我又为其加上了下载中文名字的文件的支持,真个是如虎添翼,必将赢得更多开发者的青睐。-Model1年代的文件上传的工具.

    FileUpload Apache commons下面的一个子项目,用来实现Java环境下面的文件上传功能,与常见的SmartUpload齐名.应用在Model2年代了.

    Servlet3.0 :

    Struts2 :

     

    1.2.2.2 步骤分析:

    设计一个文件上传页面:

    提交到Servlet

    接收普通项:request.getParameter();

    接收上传项:Part

    通过Part对象中的方法完成文件的上传.

    1.2.3 代码实现

    package com.itheima.servlet;

     

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.OutputStream;

     

    import javax.servlet.ServletException;

    import javax.servlet.annotation.MultipartConfig;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import javax.servlet.http.Part;

     

    /**

     * 文件上传的Servlet

     */

    @WebServlet("/UploadServlet")

    @MultipartConfig

    public class UploadServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

           

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 接收普通项:

    request.setCharacterEncoding("UTF-8");

    String desc = request.getParameter("desc");

    System.out.println("文件描述:"+desc);

    Part part = request.getPart("upload");

    // 获得上传的文件的大小

    long size = part.getSize();

    System.out.println("文件大小"+size);

    String type = part.getContentType();

    System.out.println("文件类型"+type); // text/plain  image/jpeg 

    String name = part.getName();

    System.out.println(name);

    // 获得文件名:

    String header = part.getHeader("Content-Disposition");

    System.out.println(header);

     

    int idx = header.lastIndexOf("filename="");

    String fileName = header.substring(idx+10, header.length()-1);

    System.out.println(fileName);

     

    // 获得文件内容:

    InputStream is = part.getInputStream();

     

    // 获得文件上传路径:

    String path = this.getServletContext().getRealPath("/upload");

     

    OutputStream os = new FileOutputStream(path+"/"+fileName);

    int len = 0;

    byte[] b = new byte[1024];

    while((len = is.read(b))!=-1){

    os.write(b, 0, len);

    }

    is.close();

    os.close();

     

    }

     

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    doGet(request, response);

    }

     

    }

    1.2.4 总结:

    1.2.4.1 文件名重名的问题:

    UUID随机产生一个文件名.

    1.2.4.2 文件上传的目录分离:

    按用户分 :一个用户创建一个或多个路径.

    按时间分 :按月,星期,天进行划分.

    按个数分 :一个路径中存3000个文件.

    按分离算法分 :按照一定的算法进行划分.

     

    1.3 案例三:使用动态代理的方式统一网站的字符集编码

    1.3.1 需求:

    在一个表单中分别使用getpost提交到Servlet中,在Servlet中直接调用getParameter方法解决中文乱码的问题!!!

    1.3.2 分析:

    1.3.2.1 技术分析:

    【动态代理】

    增强一个类中的某个方法.对程序进行扩展.Spring框架中AOP.

    什么是代理:

    【入门案例】

    class MyInvocationHandler implements InvocationHandler{

     

    private Waiter waiter;

     

    public MyInvocationHandler(Waiter waiter) {

    this.waiter = waiter;

    }

     

    @Override

    // 执行目标对象的任何一个方法 都相当于执行了invoke方法.

    /**

     * proxy:产生代理对象.

     * method:代表正在调用的方法.

     * Object[]:在调用的方法的参数.

     */

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    // System.out.println("aaaaa");

    // System.out.println(method.getName());

    if("server".equals(method.getName())){

    // 增强server.

    System.out.println("微笑...");

    return method.invoke(waiter, args);

    }else{

    // 不增强:

    return method.invoke(waiter, args);

    }

    // return null;

    }

     

    }

    1.3.3 代码实现:

    package com.itheima.encoding;

     

    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.annotation.WebFilter;

    import javax.servlet.http.HttpServletRequest;

     

    @WebFilter(urlPatterns="/*")

    public class GenericCharacterEncodingFilter implements Filter{

     

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

     

    }

     

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

    throws IOException, ServletException {

    final HttpServletRequest req = (HttpServletRequest) request;

     

    // req产生代理对象:

    HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(),req.getClass().getInterfaces(), new InvocationHandler() {

     

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    // 增强getParameter:

    if("getParameter".equals(method.getName())){

    // 增强.

    // 根据请求方式:

    String type = req.getMethod();

    if("get".equalsIgnoreCase(type)){

    // 调用原有的getParameter

    String value = (String)method.invoke(req, args);

    String s = new String(value.getBytes("ISO-8859-1"),"UTF-8");

    return s;

     

    }else if("post".equalsIgnoreCase(type)){

    req.setCharacterEncoding("UTF-8");

    return method.invoke(req, args);

    }

     

    }

    // 不增强:

    return method.invoke(req, args);

    }

    });

     

    chain.doFilter(myReq, response);

    }

     

    @Override

    public void destroy() {

     

    }

     

    }

     

    1.3.4 总结:

    1.3.4.1 【类的加载器:了解】

    类加载器就是将class文件加载到内存.

     

    JDK中提供的类加载器:

    * 引导/系统类加载器 Javajre7lib t.jar

    * 扩展类加载器 Javajre7libext*.jar

    * 应用类加载器 :自定义的类,类路径下的所有class文件.

     

    类的加载器的机制 :全盘委托机制.

    引导类加载器

        |

    扩展类加载器

        |

    应用类加载器

     

    class A{

        String s;

    }

     

    class文件由应用类加载器获得到,没有加载,向上一层委托向扩展类加载器委托,向上一层进行委托委托给引导类加载器.引导类加载器查看class哪些它负责,将自己负责的这个class进行加载.不是其负责的就向下传递扩展类加载器.扩展类加载器查看是否是其管理的class,如果是加载,不是就再向下到应用类加载器.

     

  • 相关阅读:
    c:forTokens标签循环输出
    jsp转long类型为date,并且格式化
    spring中@Param和mybatis中@Param使用区别(暂时还没接触)
    734. Sentence Similarity 有字典数组的相似句子
    246. Strobogrammatic Number 上下对称的数字
    720. Longest Word in Dictionary 能连续拼接出来的最长单词
    599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小
    594. Longest Harmonious Subsequence强制差距为1的最长连续
    645. Set Mismatch挑出不匹配的元素和应该真正存在的元素
    409. Longest Palindrome 最长对称串
  • 原文地址:https://www.cnblogs.com/nextgg/p/7642852.html
Copyright © 2011-2022 走看看