victory的博客

长安一片月,万户捣衣声

0%

上传和下载文件

注意:上传文件需要在springMVC.xml中配置如下所示bean:

<!-- 
    处理文件,将客户端上传的File文件处理为MultipartFile
    注意:文件解析器bean中的id必须设置为multipartResolver 
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置文件解析的编码,注意一定要和页面的pageEncoding保持一致 -->
    <property name="defaultEncoding" value="UTF-8"></property>
    <!-- 设置最大上传文件大小 -->
    <property name="maxUploadSize" value="88888888"></property>
</bean>
阅读全文 »

json表示方式

1.json有两种对象
(1)json对象:{key1:value1,key2:value2,…}
(2)json数组:[value1,value2,…]
2.解析方式
(1)Json对象解析方式:对象.key
(2)json数组解析方式:for循环遍历
3.java对象转换json
(1)Bean和map—>json对象
(2)List—>json数组

示例:
数据:
user:id=1,username=admin,age=23,sex=男

Xml方式:

1
2
3
4
5
6
7
8
<userinfo>
<user>
<id>1</id>
<username>admin</username>
<age>23</age>
<sex></sex>
</user>
</userinfo>

Json方式:

1
{id:1,username:admin,age:23,sex:男}

处理静态资源

在使用了SpringMVC的项目中,在使用css/js等静态资源时,需要在SpringMVC的配置文件中做以下配置:

<!-- 处理静态资源 -->
<!-- 
    配置Tomcat中默认的servlet,DefaultServlet
    注意:当DefaultServlet所设置的<url-pattern>的值和开发人员所配置
        的servlet的<url-pattern>相同,以开发人员所配置的servlet优先
    作用: 当客户端发送请求,由于DefaultServlet所设置的<url-pattern>的
        值和开发人员所配置的DispatcherServlet的<url-pattern>都是/,
        因此先通过DispatcherServelet处理请求,找该请求是否有相对应的处理器,
        有则处理,无则交给DefaultServlet处理
-->
<mvc:default-servlet-handler/>
<!-- mvc驱动 -->
<mvc:annotation-driven />

CharacterEncodingFilter编码过滤器

SpringMVC通过配置CharacterEncodingFilter编码过滤器来解决项目中的乱码问题,只需要在web.xml中配置CharacterEncodingFilter即可。

<!-- 配置编码过滤器 -->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

设置springMVC配置文件的位置以及名称并控制servlet的加载时间

设置springMVC配置文件的位置以及名称并控制servlet的加载时间只需要在web.xml文件中做以下配置即可:

快捷方式:Alt + / dispatcherservlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SpringMVC02</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 设置springMVC配置文件的位置以及名称 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        
        <!-- 
            设置servlet的加载时间
            默认在第一次访问时加载,若设置此标签,会将servlet的加载时间提前到项目启动时
            此标签中可以整数,但是写负整数和0和没有设置时一样的效果,只有设置为正整数才会将servlet的加载时间提前到项目启动时
            值越小,优先级越高
         -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

静态代理案例

通过静态代理来帮助发短信(短信发送类和代理类实现相同的接口)
SmsService.java(接口)

package proxy;

public interface SmsService {
    String send(String message);
}

SmsServiceImpl.java(实现类)

package proxy;

public class SmsServiceImpl implements SmsService{

    @Override
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }

}

SmsProxy.java(代理类)

package proxy;

public class SmsProxy implements SmsService{
    private final SmsService smsService;
    
    public SmsProxy(SmsService smsService){
        this.smsService = smsService;
    }
    
    @Override
    public String send(String message) {
        System.out.println("before method send()");
        smsService.send(message);
        System.out.println("after method send()");
        return null;
    }
}

Main.java(测试类)

package proxy;

public class Main {
    public static void main(String[] args){
        SmsService smsService = new SmsServiceImpl();
        SmsProxy smsProxy = new SmsProxy(smsService);
        smsProxy.send("java");
    }
}

运行结果

动态代理案例(JDK 动态代理机制)

假设我们需要通过中介租房子(告诉中介对房子的要求,由中介代我们租房子)

JDK动态代理机制和CGLIB动态代理机制的区别
1.JDK 动态代理只能代理实现了接口的类或者直接代理接口,而 CGLIB 可以代理未实现任何接口的类。 另外, CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。
2.就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。

动态代理和静态代理的区别、两种动态代理的区别
HireRoom.java(接口)

package hireroom;

public interface HireRoom {
    void hireRoom(String chaoxiang, String buju, int price);
}

HireRoomImpl.java(实现类)

package hireroom;

public class HireRoomImpl implements HireRoom{

    @Override
    public void hireRoom(String chaoxiang, String buju, int price) {
        System.out.println("我委托中介租一个朝向:" + chaoxiang + ",布局:" + buju + ",价格:" + price + "的房子");
    }

}

Agency.java(中介/代理类)

package hireroom;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Agency implements InvocationHandler{
    private Object target;
    
    public Agency(Object target){
        this.target = target;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before");
        Object result = method.invoke(target, args);
        System.out.println("after");
        return result;
    }

}

AgencyFactory.java(中介/代理工厂)

package hireroom;

import java.lang.reflect.Proxy;

public class AgencyFactory {
    public static Object getProxy(Object target){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), 
                new Agency(target));
    }
}

Main.java(测试)

package hireroom;

public class Main {
    public static void main(String[] args) {
        HireRoom hireRoom = (HireRoom) AgencyFactory.getProxy(new HireRoomImpl());
        hireRoom.hireRoom("坐南朝北", "两室一厅", 200000);
    }
}

运行结果1

再假设我们现在又有了想通过中介租车的需求,只需要再添加租车接口和实现类,然后通过上面的代理类完成租车。这也是动态代理的优点
HireCar.java(接口)

package hireroom;

public interface HireCar {
    void hireCar(String brand, int price);
}

HireCarImpl.java(实现类)

package hireroom;

public class HireCarImpl implements HireCar{

    @Override
    public void hireCar(String brand, int price) {
        System.out.println("租车:"+brand+price);
    }

}

Main.java

package hireroom;

public class Main {
    public static void main(String[] args) {
        HireRoom hireRoom = (HireRoom) AgencyFactory.getProxy(new HireRoomImpl());
        hireRoom.hireRoom("坐南朝北", "两室一厅", 200000);
        
        HireCar hireCar = (HireCar) AgencyFactory.getProxy(new HireCarImpl());
        hireCar.hireCar("宝马", 150000);
    }
}

运行结果2

获取Class对象的四种方式

反射可以动态获取类的信息,这需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。Java 提供了四种方式获取 Class 对象:

  1. 知道具体类的情况下可以使用:
Class alunbarClass = TargetObject.class;

但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化

  1. 通过 Class.forName()传入类的全路径获取:
Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
  1. 通过对象实例instance.getClass()获取:
TargetObject o = new TargetObject();
Class alunbarClass2 = o.getClass();
  1. 通过类加载器xxxClassLoader.loadClass()传入类路径获取:
Class clazz = ClassLoader.loadClass("cn.javaguide.TargetObject");

通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行

阅读全文 »