# spring mvc 拓展


<!--more-->


## 一、乱码问题

### 1.post请求乱码

```xml
<!-- 解决post乱码问题 -->
<filter>
  <filter-name>encoding</filter-name>
  <filter-class>
    org.springframework.web.filter.CharacterEncodingFilter
  </filter-class>
  <!-- 设置编码是UTF8 -->
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
  <init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>encoding</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
```

### 2.get请求乱码:需要修改**tomcat**中 **server.xml**配置

```xml
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080"
protocol="HTTP/1.1" redirectPort="8443"/>
```



## 二、设计模式

### 1.策略模式

策略模式（Strategy），就是⼀个问题有多种解决⽅案，选择其中的⼀种使⽤，这种情况下我们使⽤策略模式来实现灵活地选择，也能够⽅便地增加新的解决⽅案。⽐如做数学题，⼀个问题的解法可能有多种；再⽐如商场的打折促销活动，打折⽅案也有很多种，有些商品是不参与折扣活动要按照原价销售，有些商品打8.5折，有些打6折，有些是返现5元等。

结构：

- 策略（strategy)

  定义所有⽀持算法的公共接⼝。 Context 使⽤这个接⼝来调⽤某 ConcreteStrategy 定义的算法。

- 策略实现（ConcreteStrategy）

  实现了Strategy 接⼝的具体算法

- 上下文（context)

  维护⼀个 Strategy 对象的引⽤

  ⽤⼀个 ConcreteStrategy 对象来装配

  可定义⼀个接⼝⽅法让 Strategy 访问它的数据

示例：

- 非策略模式

  ```java
  public class Goods {
      private String goodsName;
      private double price;
      private double finalPrice;
      private String desc;
  
      public Goods(String goodsName, double price) {
          this.goodsName = goodsName;
          this.price = price;
      }
  
      /**
       * 折扣方法
       *
       * @param discountType 折扣类型
       * @return double
       */
      public double calculate(String discountType) {
          if ("85%".equalsIgnoreCase(discountType)) {
              finalPrice = price * 0.85;
              desc = "该商品8.5折优惠";
          } else if ("75%".equalsIgnoreCase(discountType)) {
              finalPrice = price * 0.75;
              desc = "该商品7.5折优惠";
          } else if ("65%".equalsIgnoreCase(discountType)) {
              finalPrice = price * 0.65;
              desc = "该商品6.5折优惠";
          } else {
              finalPrice = price;
              desc = "无折扣";
          }
          System.out.println(MessageFormat.format("商品：{0}， 原价为：{1}，{2}, 折后价格为：{3}", goodsName, price, desc, finalPrice));
          return finalPrice;
      }
  }
  
  //test
  @Test
  public void test1() {
    Goods good1 = new Goods("苹果", 100);
    good1.calculate("85%");
  
    Goods good2 = new Goods("电脑", 2000);
    good2.calculate("75%");
  
    Goods good3 = new Goods("衣服", 800);
    good3.calculate("65%");
  
    Goods good4 = new Goods("金条", 100000);
    good4.calculate("100%");
  }
  ```

  >缺点：
  >
  >- 增加方案，需要修改Goods源代码，违反 开闭原则
  >- 代码利用性差
  >- if else分支过多

- 策略模式

  ```java
  /**
   * 抽象策略类
   *
   * @author zhaojianqiang
   */
  public abstract class AbstractDiscount {
      private double finalPrice;
      private String desc;
  
      public AbstractDiscount(String desc) {
          this.desc = desc;
      }
  
      public abstract double discount(double price);
  
      public double getFinalPrice() {
          return finalPrice;
      }
  
      public void setFinalPrice(double finalPrice) {
          this.finalPrice = finalPrice;
      }
  
      public String getDesc() {
          return desc;
      }
  
      public void setDesc(String desc) {
          this.desc = desc;
      }
  }
  ```

  ```java
  /**
   * 策略模式： 持有策略类 AbstractDiscount 的引用
   *
   * @author zhaojianqiang
   */
  public class GoodsForStrategy {
      private String goodsName;
      private double price;
      private AbstractDiscount abstractDiscount;
  
      public GoodsForStrategy(String goodsName, double price, AbstractDiscount abstractDiscount) {
          this.goodsName = goodsName;
          this.price = price;
          this.abstractDiscount = abstractDiscount;
      }
  
      /**
       * 折扣方法
       *
       * @return double
       */
      public double calculate() {
          double finalPrice = abstractDiscount.discount(this.price);
          String desc = abstractDiscount.getDesc();
          System.out.println(MessageFormat.format("商品：{0}， 原价为：{1}，{2}, 折后价格为：{3}", goodsName, price, desc, finalPrice));
          return finalPrice;
      }
  }
  ```

  ```java
  /**
   * 策略模式： 持有策略类 AbstractDiscount 的引用
   *
   * @author zhaojianqiang
   */
  public class GoodsForStrategy {
      private String goodsName;
      private double price;
      private AbstractDiscount abstractDiscount;
  
      public GoodsForStrategy(String goodsName, double price, AbstractDiscount abstractDiscount) {
          this.goodsName = goodsName;
          this.price = price;
          this.abstractDiscount = abstractDiscount;
      }
  
      /**
       * 折扣方法
       *
       * @return double
       */
      public double calculate() {
          double finalPrice = abstractDiscount.discount(this.price);
          String desc = abstractDiscount.getDesc();
          System.out.println(MessageFormat.format("商品：{0}， 原价为：{1}，{2}, 折后价格为：{3}", goodsName, price, desc, finalPrice));
          return finalPrice;
      }
  }
  //75折.....等策略，只需不断添加策略类即可
  ```

  ```java
  @Test
  public void test2() {
    GoodsForStrategy good1 = new GoodsForStrategy("苹果", 100, new Discount85());
    good1.calculate();
  
    GoodsForStrategy good2 = new GoodsForStrategy("电脑", 2000, new Discount75());
    good2.calculate();
  
    GoodsForStrategy good3 = new GoodsForStrategy("衣服", 800, new Discount65());
    good3.calculate();
  
    GoodsForStrategy good4 = new GoodsForStrategy("金条", 100000, new Discount0());
    good4.calculate();
  }
  ```

  >优点：
  >
  >- 只需增加策略类，无需修改源码
  >- 代码简单，利用性强
  >- 去掉了大量if...else判断

### 2.模板方法模式

模板⽅法模式是指定义⼀个算法的⻣架，并允许⼦类为⼀个或者多个步骤提供实现。模板⽅法模式使得⼦类可以在不改变算法结构的情况下，重新定义算法的某些步骤，属于⾏为型设计模式。采⽤模板⽅法模式的核⼼思路是处理某个流程的代码已经具备，但其中某些节点的代码暂时不能确定。此时可以使⽤模板⽅法。

```java
/**
 * 模板方法类
 * <p>
 * 做饭
 *
 * @author zhaojianqiang
 */
public abstract class Cook {
    private void fire() {
        System.out.println("开火");
    }

    public abstract void cooking();

    private void eat() {
        System.out.println("开吃");
    }

    public void cook() {
        this.fire();
        this.cooking();
        this.eat();
    }
}
```

```java
public class Dumpling extends Cook{
    @Override
    public void cooking() {
        System.out.println("----今天煮饺子----");
    }
}

public class HotPot extends Cook{
    @Override
    public void cooking() {
        System.out.println("----今天涮火锅----");
    }
}
```

```java
@Test
public void test3() {
  Dumpling dumpling = new Dumpling();
  dumpling.cook();

  HotPot hotPot = new HotPot();
  hotPot.cook();
}
```

### 3.适配器模式

使得原本由于接⼝不兼容⽽不能⼀起⼯作、不能统⼀管理的那些类可以⼀起⼯作、可以进⾏统⼀管理

- 解决接⼝不兼容⽽不能⼀起⼯作问题，例：电源适配器

  ```java
  public class AC220 {
      public int outputAC220V() {
          int output = 220;
          System.out.println("输出交流电" + output + "V");
          return output;
      }
  }
  ```

  ```java
  public interface DC5 {
      int outputDC5V();
  }
  ```

  ```java
  public class PowerAdapter implements DC5 {
      private AC220 ac220;

      public PowerAdapter(AC220 ac220) {
          this.ac220 = ac220;
      }

      @Override
      public int outputDC5V() {
          int adapterInput = ac220.outputAC220V();
          // 变压器...
          int adapterOutput = adapterInput / 44;
          System.out.println("使⽤ PowerAdapter 输⼊AC:" + adapterInput + "V输出DC:" + adapterOutput + "V");
          return adapterOutput;
      }
  }
  ```

  ```java
   @Test
  public void test4() {
    DC5 dc5 = new PowerAdapter(new AC220());
    dc5.outputDC5V();
  }
  ```

- 解决不能统⼀管理的问题

  SpringMVC中处理器适配器（HandlerAdapter）机制就是解决类统⼀管理问题⾮常经典的场景

  其中 HandlerAdapter接⼝是处理器适配器的顶级接⼝，它有多个⼦类，包括:

  - AbstractHandlerMethodAdapter

  - SimpleServletHandlerAdapter

  - SimpleControllerHandlerAdapter

  - HttpRequestHandlerAdapter

  - RequestMappingHandlerAdapter

