天天看點

Spring中常用注解,以及亂碼問題

1、@RequestMapping 這是一個用來處理請求位址映射的注解,可以用于類、方法上。用于類上表示整個類的父路徑。 2、@RequestBody 不能處理get請求 參數是不會被Servlet轉化統一放在request對象的Param參數集中 不能處理Content-Type為application/x-www-form-urlencoded編碼格式的資料(Http協定中,如果不指定Content-Type,則預設傳遞的參數就是application/x-www-form-urlencoded類型) 3、@RequestParam 可以處理get、post請求 參數會被Servlet轉化統一放在request對象的Param參數集中 4、@ResponseBody 用于controller層的方法上,用于:将方法傳回的對象、值,通過适當的轉換器轉換為指定的格式之後,寫入到response對象的body區,通常用來傳回JSON資料或者是XML資料,此注解不會再走視圖處理器,而是直接将資料寫入到輸入流中,他的效果等同于通過response對象輸出指定格式的資料。

5、@PathVariable将URL中的{xxx}占位符綁定到處理方法的入參中

例子url:/{id};入參:@PathVariable("id") String id

6、@Controller  用于标記在一個類上,使用它标記的類就是一個SpringMVC Controller 對象。分發處理器将會掃描使用了該注解的類的方法 7、@Service 用于标注業務層元件 8、@Repository 用于标注資料通路元件,即DAO元件 9、@Component 當元件不好歸類的時候,我們可以使用這個注解進行标注

Spring會把帶有@Controller @Service @Repository @Component四個注解的類納入Spring的管理。使用spring注入,減少代碼耦合。

10、@RequestBody和@RequestParam比較

兩個注解都用于接受參數。@RequestBody不能處理Content-Type為application/x-www-form-urlencoded,@RequestBody不能處理get請求。而@RequestParam則可以。是以推薦使用@RequestParam。

11、@RequestBody和@ResponseBody 一個用于接受參數。一個用于傳回參數。兩個注解會調用HttpMessageConverter的read和write方法 @RequestBody調用HttpMessageConverter的read方法,調用實作類AbstractHttpMessageConverter的read方法,根據輸入類型分别調用AbstractHttpMessageConverter的實作類。假設參數類型為String則調用StringHttpMessageConverter的readInternal方法。該方法會從HttpInputMessage中擷取字元集,使用該字元集讀取參數(HttpInputMessage中的字元集為web.xml中CharacterEncodingFilter的encoding值); @ResponseBody調用HttpMessageConverter的write方法,AbstractHttpMessageConverter的write方法,StringHttpMessageConverter的writeInternal方法。該方法會從HttpOutputMessage中擷取字元集。使用該字元集傳回(HttpOutputMessage中的字元集為:StringHttpMessageConverter配置的ISO-8859-1)是以傳回類型為String時會導緻亂碼。

12、@ResponseBody導緻的亂碼解決方式

  • 修改spring_mvc.xml中HttpMessageConverter字元集
<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>  
           
<mvc:annotation-driven> 标簽,自動注冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapter 兩個bean,是spring MVC為@Controllers分發請求所必須的。
<mvc:message-converters> 标簽,設定字元集和json處理類
           
  • 重寫StringHttpMessageConverter類:

spring_mvc.xml

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="xyz.chanjkf.utils.JsonStringHttpMessageConverter"/>
    </mvc:message-converters>
</mvc:annotation-driven>
           
/**
 * content-type:application/json請求的亂碼
 * @author yi
 */
public class JsonStringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private final Charset defaultCharset;

    public JsonStringHttpMessageConverter() {
        this(DEFAULT_CHARSET);
    }

    public JsonStringHttpMessageConverter(Charset defaultCharset) {
        super(new MediaType[]{new MediaType("application", "json", defaultCharset), MediaType.ALL});
        this.defaultCharset = defaultCharset;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return String.class.equals(clazz);
    }

    @Override
    protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
        Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
        return StreamUtils.copyToString(inputMessage.getBody(), charset);
    }

    @Override
    protected Long getContentLength(String s, MediaType contentType) {
        Charset charset = this.getContentTypeCharset(contentType);
        try {
            return Long.valueOf((long)s.getBytes(charset.name()).length);
        } catch (UnsupportedEncodingException var5) {
            throw new IllegalStateException(var5);
        }
    }

    @Override
    protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
        Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
        StreamUtils.copy(s, charset, outputMessage.getBody());
    }

    private Charset getContentTypeCharset(MediaType contentType) {
        return contentType != null && contentType.getCharSet() != null?contentType.getCharSet():this.defaultCharset;
    }
}
           

maven依賴:

<dependency>  
    <groupId>org.codehaus.jackson</groupId>  
    <artifactId>jackson-mapper-asl</artifactId>  
    <version>1.9.13</version>  
</dependency>  
<dependency>  
    <groupId>org.codehaus.jackson</groupId>  
    <artifactId>jackson-core-asl</artifactId>  
    <version>1.9.13</version>  
</dependency>