spring mvc 总结

依赖包

<!-- spring依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.2.9.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.2.9.RELEASE</version>
    </dependency>
    
    <!-- 结束 -->
    
    <!-- slf4j日志依赖,不用log4j -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.14</version>
    </dependency>
    
    <!-- servlet运行依赖 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.1</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- jstl标签依赖 -->
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    
    <!-- springmvc返回json依赖 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.8.8</version>
    </dependency>
    
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.8.8</version>
    </dependency>
    
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.8</version>
    </dependency>
    
    
    <!-- springmvc文件上传依赖 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
    
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>
  
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <build>
    <plugin> 
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
            <source>1.7</source> 
            <target>1.7</target> 
            <encoding>UTF-8</encoding> 
        </configuration>
    </plugin>
</build>

springmvc初始化的方式

1.web.xml

<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">


    <!-- spring mvc -->
    <servlet>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    
</web-app>

2.类初始化需要servlet 3.0以上

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.setInitParameter("contextConfigLocation", "classpath:spring-mvc.xml");
        registration.addMapping("/");
    }

}

springmvc 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    
   
    

   
     
    <!-- 不用默认的扫描  用自定义的扫描 -->
    <context:component-scan base-package="com.controller" use-default-filters="false">
      <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan>
    
    <!-- 对应的整合spring的配置配置文件不扫描springmvc的注解,为了避免重复扫描创建两个对象 -->
    <!-- <context:component-scan base-package="com.controller">
      <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
      <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
    </context:component-scan> -->
    
    
    <!-- <context:component-scan base-package="com.handler"></context:component-scan> -->

    <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    
    <!-- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/view/" p:suffix=".jsp" /> -->

<!--自定义视图-->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
       <property name="order" value="100"></property>
    </bean>

<!--自定义视图--> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="100"></property> </bean> <!-- <mvc:view-controller path="/success" view-name="/success"/> -->
<!--静态文件的控制访问交由servlet去处理 比如当访问 /aaa/a.html时直接访问页面 配置后需添加mvc:annotation-driven--> <mvc:default-servlet-handler />

<!--配置后一些springmvc会初始化一些默认的配置比如异常,返回 json的处理等-->
<mvc:annotation-driven />

<mvc:interceptors>
<!--全局拦截器--> <bean class="com.interceptor.FirstInterceptor"></bean> <mvc:interceptor>
<!--拦截指定路径--> <mvc:mapping path="/aaaa/"/> <bean class="com.interceptor.SecondInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> <!--SimpleMappingExceptionResolver 自定义异常解析--> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionAttribute" value="myexception"></property> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean> <!-- springmvc上传文件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="5242880"></property> </bean> </beans>
<context:component-scan base-package="com.jit" resource-pattern="/**/services/**/*.class"></context:component-scan>

 springmvc 不拦截静态资源

方案一:拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml)
注意:需引入mvc命名空间
  1.  <!-- 添加注解驱动 -->
  2.  <mvc:annotation-driven/>
  3.  <!--
  4.  通过mvc:resources设置静态资源,这样servlet就会处理这些静态资源,而不通过控制器
  5.  设置不过滤内容,比如:css,js,img 等资源文件
  6.  location指的是本地的真是路径,mapping指的是映射到的虚拟路径。
  7.  -->
  8.  <mvc:resources mapping="/css/**" location="/css/"/>

方案二:使用默认的servlet处理静态资源(涉及spring-mvc.xml,web.xml)

在spring-mvc.xml中添加:

  1.  <!--启用默认Servlet-->
  2.  <mvc:default-servlet-handler/>

    <mvc:default-servlet-handler/>

 在web.xml中添加:

  1.  <!--增加对静态资源的处理,当前的设置必须在Spring的Dispatcher的前面-->
  2.  <servlet-mapping>
  3.  <servlet-name>default</servlet-name>
  4.  <url-pattern>*.css</url-pattern>
  5.  <url-pattern>/css/*</url-pattern>
  6.  </servlet-mapping>

方案三:修改spring的全局拦截设置为*.do的拦截(涉及web.xml)

  1.  <!-- 拦截所有请求 -->
  2.  <servlet-mapping>
  3.  <servlet-name>dispatcher</servlet-name>
  4.  <!--<url-pattern>/</url-pattern>-->
  5.  <url-pattern>*.do</url-pattern>
  6.  </servlet-mapping>

spring获取注解类

 ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);

拦截器,配置多个拦截器的执行顺序   会先执行第一个拦截器的preHandle 第二个拦截器的preHandle   之后反序

public class FirstInterceptor implements HandlerInterceptor{

    /**
     * 控制器访问后,渲染视图后,通常释放资源
     */
    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("FirstInterceptor:afterCompletion");
    }

    /**
     * 控制器访问后,渲染视图前调用,通常改变请求值
     */
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView view) throws Exception {
        //System.out.println(view==null);
        view.addObject("openid", "12121212");
        //arg3.addObject("openid", "123456");
        System.out.println("FirstInterceptor:postHandle");
        
    }

    /**
     * 请求控制类之间被调用,通常被用为权限,日志,事物等
     */
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2) throws Exception {
        System.out.println("FirstInterceptor:preHandle");
        return true;
    }

}

springmvc  控制类全局异常处理

/**
 * 全局处理异常
 * @author Administrator
 *
 */
@ControllerAdvice
public class HandlerException {
    
    
    @ExceptionHandler({Exception.class})
    public ModelAndView handlerException(Exception e){
        e.printStackTrace();
        ModelAndView view = new ModelAndView("error");
        view.addObject("error",e);
        return view;
    }

}

自定义异常

@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="页面没找到")
public class MyException extends RuntimeException{

    private static final long serialVersionUID = 1L;

}

控制类

@RequestMapping("/testMyException")
    public String testMyException(){
        int i = 9;
        if(i==9){
            throw new MyException();
        }
        return "hello"; 
        
    }

自定义视图,比如返回pdf  excel

@Component
public class MyView implements View{

    @Override
    public String getContentType() {
        return "text/html";
    }

    @Override
    public void render(Map<String, ?> model, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        response.getWriter().write("111111111111111");
        
    }

}

控制类

@RequestMapping("/testMyView")
    public MyView testMyView(HttpServletRequest request,HttpServletResponse response,
            HttpSession session,Principal principal,Locale Locale,Writer writer,Reader reader){
        System.out.println("121212");
        //@CookieValue("j")
        return new MyView();
    }

consumes、produces 示例

Content-Type   MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。

 常见的媒体格式类型如下:

  •     text/html : HTML格式
  •     text/plain :纯文本格式      
  •     text/xml :  XML格式
  •     image/gif :gif图片格式    
  •     image/jpeg :jpg图片格式 
  •     image/png:png图片格式

   以application开头的媒体格式类型:

  •    application/xhtml+xml :XHTML格式
  •    application/xml     : XML数据格式
  •    application/atom+xml  :Atom XML聚合格式    
  •    application/json    : JSON数据格式
  •    application/pdf       :pdf格式  
  •    application/msword  : Word文档格式
  •    application/octet-stream : 二进制流数据(如常见的文件下载)
  •    application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

   另外一种常见的媒体格式是上传文件之时使用的:

  •     multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

value:  指定请求的实际地址, 比如 /action/info之类。
method:  指定请求的method类型, GET、POST、PUT、DELETE等
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
params: 指定request中必须包含某些参数值是,才让该方法处理
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求

cousumes的样例:

 
  1. @Controller  
  2. @RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")  
  3. public void addPet(@RequestBody Pet pet, Model model) {      
  4.     // implementation omitted  
  5. }  

方法仅处理request Content-Type为“application/json”类型的请求。

produces的样例:

  1. @Controller  
  2. @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")  
  3. @ResponseBody  
  4. public Pet getPet(@PathVariable String petId, Model model) {      
  5.     // implementation omitted  
  6. }  

方法仅处理request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json;

springmvc 控制类文件下载

    /**
     * 文件下载
     * @return
     */
    public ResponseEntity<byte[]> down(){
        ResponseEntity<byte[]> responseEntity = null;// = new ResponseEntity<byte[]>(body, headers, statusCode)
        return responseEntity;
    }

springmvc 控制类数据绑定,可用于表单提交html转义编码放置xss攻击等

@InitBinder
    public void initBinder(WebDataBinder binder) {
        // String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
            }
            @Override
            public String getAsText() {
                Object value = getValue();
                return value != null ? value.toString() : "";
            }
        });
        
        // Date 类型转换
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(DateUtils.parseDate(text));
            }
        });
        
        // Timestamp 类型转换
        binder.registerCustomEditor(Timestamp.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                Date date = DateUtils.parseDate(text);
                setValue(date==null?null:new Timestamp(date.getTime()));
            }
        });
    }

springmvc    @ModelAttribute

    /**
     * 访问控制类首先被调用会把myUser放到requestScope中,页面可用EL表达式获取,也可以在控制类其他方法中获取,如果表单提交会把u合并
     * @return
     */
    @ModelAttribute("myUser")  
    public User getUser(){
        User u = new User();
        return u;
    }
    
    @RequestMapping("/addUser")
    public String addUser(@ModelAttribute("myUser") User u ){
        return "success";
    }

 springmvc 获取多文件

boolean isFileUpload = ServletFileUpload.isMultipartContent(request);

MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) req;

List<MultipartFile > files = multipartHttpServletRequest.getFiles("files");

String realPath = req.getSession().getServletContext().getRealPath("/");
 String path =  realPath + "\upload\"+year+"\"+month+"\";

 File filepath = new File(path);
        if (!filepath.exists())
            filepath.mkdirs();
        // 文件保存路径  
        String savePath = path + file.getOriginalFilename();  
        // 转存文件  
        file.transferTo(new File(savePath)); 

第一种方法:

     MultipartFile file = xxx; 
        CommonsMultipartFile cf= (CommonsMultipartFile)file; 
        DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 

        File f = fi.getStoreLocation();

  会在项目的根目录的临时文件夹下生成一个文件;

第二种方法:

    transferTo(File dest);

  会在项目中生成一个新文件;

第三种方法:   

  File f = (File) xxx 强转即可。前提是要配置multipartResolver,要不然会报类型转换失败的异常。
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="104857600"/>
        <property name="maxInMemorySize" value="4096"/>
    </bean>
  没试过;
第四种方法:
  Workbook wb = Workbook.getWorkbook(xxx .getInputStream());
  转换为输入流,直接读取;
第五种方法:
  byte[] buffer = myfile.getBytes();
  先转换为字节数组,没试过;

Filter Types 的5中类型:

1 . annotation  注解           org.springframework.stereotype.Controller        注解名(类型)

2. assignale  类名或者接口   org.example.someClass 

3. aspectj    简单点就是就是切面表达式

4.regex  正则表达式

5. custom  实现了 org.springframework.core.type.TypeFilter 接口的类型

复制代码
<beans>
<context:component-scan base-package="org.example">
<context:include-filter type="regex"
expression=".*Stub.*Repository"/>
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>
复制代码

use-default-filters="false"关闭默认filter

springmvc 自定义映射规则

https://segmentfault.com/a/1190000021376498?utm_source=tag-newest

 //自定义消息转换器

<mvc:annotation-driven>
      <mvc:message-converters register-defaults="true">
            <bean class="com.javazhan.controller.UTF8StringHttpMessageConverter"/>
      </mvc:message-converters>
</mvc:annotation-driven>

package com.javazhan.controller;

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: yandq
 * @Description:
 * @Date: Create in 11:50 2018/4/3
 * @Modified By:
 */
public class UTF8StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private volatile List<Charset> availableCharsets;
    private boolean writeAcceptCharset;

    public UTF8StringHttpMessageConverter() {
        this(DEFAULT_CHARSET);
    }

    public UTF8StringHttpMessageConverter(Charset defaultCharset) {
        super(defaultCharset, new MediaType[]{MediaType.TEXT_PLAIN, MediaType.ALL});
        this.writeAcceptCharset = true;
    }

    public void setWriteAcceptCharset(boolean writeAcceptCharset) {
        this.writeAcceptCharset = writeAcceptCharset;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return String.class == 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 str, MediaType contentType) {
        Charset charset = this.getContentTypeCharset(contentType);

        try {
            return (long)str.getBytes(charset.name()).length;
        } catch (UnsupportedEncodingException var5) {
            throw new IllegalStateException(var5);
        }
    }

    @Override
    protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
        if (this.writeAcceptCharset) {
            outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
        }

        Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
        StreamUtils.copy(str, charset, outputMessage.getBody());
    }

    protected List<Charset> getAcceptedCharsets() {
        if (this.availableCharsets == null) {
            this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
        }

        return this.availableCharsets;
    }

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



原文地址:https://www.cnblogs.com/jentary/p/6832899.html