victory的博客

长安一片月,万户捣衣声

0%

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 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行

阅读全文 »

处理响应数据 ModelAndView

处理请求数据
项目的ParamController.java的类中加入以下代码:

/**
 * SpringMVC处理请求过程中,往作用域中放值有以下三种方式
 * 总结:根据ModelAndView源码调试,不管使用以下那种方式,最终都会把model数据和view数据封装到一个ModelAndView中
 */
//往作用域中放值方式1
//    @RequestMapping(value="/param", method=RequestMethod.POST)
//    public ModelAndView param(){
//        ModelAndView mav = new ModelAndView();
//        //javaWEB: request.setAttribute(xxx) 
//        mav.addObject("username", "root");//往request作用域中放值
//        mav.setViewName("success");//设置视图名称,实现页面跳转
//        return mav;
//    }
    
    //往作用域中放值方式2
//    @RequestMapping(value="/param", method=RequestMethod.POST)
//    public String param(Map<String, Object> map){
//        map.put("username", "admin");//向作用域中放值
//        return "success";//返回视图名称
//    }

//往作用域中放值方式3
@RequestMapping(value="/param", method=RequestMethod.POST)
public String param(Model model){
    model.addAttribute("usernaem", "zhangsan");//向作用域中放值
    return "success";//返回视图名称
}

并在param.jsp页面获取request作用域中的值

<!-- ${requestScope.username } -->
    ${username}

REST风格 GET/POST/PUT/DELETE请求

*REST:即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。

浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不
支持,Spring3.0 添加了一个过滤器(HiddenHttpMethodFilter),可以将这些
请求转换为标准的 http 方法
,使得支持 GET、POST、PUT 与 DELETE 请求。

HiddenHttpMethodFilter支持REST风格的过滤器:可以将POST请求转换为PUT或DELETE请求

阅读全文 »

SpringMVC之HelloWorld

springMVC的搭建过程:

1.导入jar

2.在web.xml配置springMVC的核心(前端)控制器DispatcherServlet
作用:加载springMVC的配置文件,在下方的配置方式下,DispatcherServlet
自动加载配置文件,此时的配置文件有默认的位置和名称
默认位置:WEB-INF下,默认名称:-servlet.xml,
例如以下配置方式的文件名:springMVC-servlet.xml
当加载了配置文件,springMVC就会根据扫描组件找到控制层

<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

3.创建一个POJO,在此类上加上@Controller注解,springMVC就会将此类作为控制层加载,让其处理请求响应
4.在控制层中,需要在方法上设置@RequestMapping(value=”hello”),
springMVC就是通过此注解将请求路径与控制层中的方法进行匹配,此时请求路径为localhost:8080/projectName/xxx
5.处理请求的方法会返回一个字符串,即视图名称,最终会通过配置文件中配置的视图解析器实现页面跳转
方式:prefix + 视图名称 + suffix,此为最终跳转的页面路径

阅读全文 »