依赖包
<!-- 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命名空间
-
<!-- 添加注解驱动 -->
-
<mvc:annotation-driven/>
-
<!--
-
通过mvc:resources设置静态资源,这样servlet就会处理这些静态资源,而不通过控制器
-
设置不过滤内容,比如:css,js,img 等资源文件
-
location指的是本地的真是路径,mapping指的是映射到的虚拟路径。
-
-->
-
<mvc:resources mapping="/css/**" location="/css/"/>
方案二:使用默认的servlet处理静态资源(涉及spring-mvc.xml,web.xml)
在spring-mvc.xml中添加:
-
<!--启用默认Servlet-->
-
<mvc:default-servlet-handler/>
<mvc:default-servlet-handler/>
在web.xml中添加:
-
<!--增加对静态资源的处理,当前的设置必须在Spring的Dispatcher的前面-->
-
<servlet-mapping>
-
<servlet-name>default</servlet-name>
-
<url-pattern>*.css</url-pattern>
-
<url-pattern>/css/*</url-pattern>
-
</servlet-mapping>
方案三:修改spring的全局拦截设置为*.do的拦截(涉及web.xml)
-
<!-- 拦截所有请求 -->
-
<servlet-mapping>
-
<servlet-name>dispatcher</servlet-name>
-
<!--<url-pattern>/</url-pattern>-->
-
<url-pattern>*.do</url-pattern>
-
</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的样例:
- @Controller
- @RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
- public void addPet(@RequestBody Pet pet, Model model) {
- // implementation omitted
- }
方法仅处理request Content-Type为“application/json”类型的请求。
produces的样例:
- @Controller
- @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
- @ResponseBody
- public Pet getPet(@PathVariable String petId, Model model) {
- // implementation omitted
- }
方法仅处理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(); } }