SpringMVC3 环境搭建
下载相关JAR包
链接:https://pan.baidu.com/s/1o83rTwJ7S5YagllFfJcQmg
提取码:ufnk
搭建 SpringMVC3 环境
- 创建 JavaWeb项目
- 将 Spring 的核心 JAR 文件与 SpingMVC 的 JAR 文件都导入到
WebRoot/WEB-INF/lib
目录下 - 在
web.xml
中配置 Servlet,此步可以理解为是SpringMVC的执行入口<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <!-- 配置 SpringMVC 入口 --> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 指定 SpringMVC 配置文件所在路径 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!-- 启动容器时就要加载 SpringServlet --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
- 创建
resources
源码目录,在此目录下创建SpringMVC配置文件:springmvc-servlet.xml
,并键入如下内容:<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 配置处理器映射 指明访问某个URL时要进入的控制器类 --> <bean name="/index.html" class="controller.IndexController"/> <!-- 配置内部资源视图解析器 --> <!-- 视图路径:/WEB-INF/jsp/逻辑视图名.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
- 在
src
目录下创建控制器包controller
,在控制器包中创建控制器IndexController.java
,并键入如下信息:package controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class IndexController extends AbstractController { @Override protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { System.out.println("Hello SpringMVC"); // index 为逻辑视图名 真实的视图路径为:/WEB-INF/jsp/index.jsp return new ModelAndView("index"); } }
- 在
WebRoot/WEB-INF
下,创建jsp
文件夹,在里面创建index.jsp
文件,并键入如下内容:<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>首页</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h1>Hello SpringMVC</h1> </body> </html>
- 部署项目,并通过浏览器访问
http://localhost:8080/你的项目名/index.html
SprintMVC3 使用注解实现控制器类
支持注解配置
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.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">
<!-- IOC注解支持 -->
<context:component-scan base-package="controller"></context:component-scan>
<!-- MVC注解支持 -->
<mvc:annotation-driven/>
<!-- 内部资源视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
控制器改造
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class IndexController {
@RequestMapping("/index.html")
public ModelAndView index(){
return new ModelAndView("index");
}
}
// 等效于
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping("/index.html")
public String index(){
return "index";
}
}
SpringMVC3 请求映射映射
单映射
单级映射
访问URL:/index
@Controller
public class IndexController {
@RequestMapping("/index")Q
public String index() {
return "index";
}
}
多级映射
访问URL:/user/index
@Controller
public class IndexController {
@RequestMapping("/user/index")
public String index() {
return "index";
}
}
// 等效于
@Controller
@RequestMapping("/user")
public class IndexController {
@RequestMapping("/index")
public String index(){
return "user/index";
}
}
多映射
访问URL:/index
或 /
@Controller
public class IndexController {
@RequestMapping({"/index","/"})
public String index() {
return "index";
}
}
只允许GET请求
GET方式请求:/index
@Controller
public class IndexController {
@RequestMapping(value="/index",method=RequestMethod.GET)
public String index() {
return "index";
}
}
只允许POST请求
POST方式请求:/index
@Controller
public class IndexController {
@RequestMapping(value="/index",method=RequestMethod.POST)
public String index() {
return "index";
}
}
SpringMVC3 视图向控制器传递参数
提交单个参数
访问URL:/index?name=admin
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(String name){
System.out.println(name);
return "index";
}
}
// 等效于
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(@RequestParam String name){
System.out.println(name);
return "index";
}
}
// 等效于
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(@RequestParam("name") String name){
System.out.println(name);
return "index";
}
}
// 等效于
@Controller
public class IndexController {
@RequestMapping(value="/index",params="name")
public String index(String name){
System.out.println(name);
return "index";
}
}
提交多个参数
访问URL:/index?name=admin&age=20
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(String name, int age){
System.out.println(name);
System.out.println(age);
return "index";
}
}
// 等效于
public class IndexController {
@RequestMapping("/index")
public String index(@RequestParam String name, @RequestParam int age){
System.out.println(name);
System.out.println(age);
return "index";
}
}
// 等效于
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(@RequestParam("name") String name, @RequestParam("age") int age){
System.out.println(name);
System.out.println(age);
return "index";
}
}
// 等效于
@Controller
public class IndexController {
@RequestMapping(value = "/index", params = { "name", "age" })
public String index(String name, int age) {
System.out.println(name);
System.out.println(age);
return "index";
}
}
非必填参数
访问URL:/index
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(@RequestParam(required=false,value="name")String name) {
System.out.println(name); // null
return "index";
}
}
给参数设置默认值
访问URL:/index
@Controller
public class IndexController {
@RequestMapping("/index")
public String index(@RequestParam(required=false,value="name",defaultValue="匿名")String name) {
System.out.println(name); // 匿名
return "index";
}
}
将参数赋值给对象的属性
add.html
传来的参数名应该与pojo.User
类中的属性名相同,否则无法进行自动赋值- 无法给
pojo.User
类中的 Date 类型的属性自动赋值,需要在 Date 类型属性上添加注解@DateTimeFormat(pattern="yyyy-MM-dd")
- 控制器中的操作方法的参数不能添加
@RequestParam
注解
控制器操作方法
@RequestMapping(value = "/add.html", method = RequestMethod.POST)
public String addSave(User user) {
return "user/userlist";
}
pojo.User时间属性
@DateTimeFormat(pattern="yyyy-mm-dd")
private Date birthday;
SpringMVC3 控制器向视图传递参数
使用 ModelAndView 类实现
传入普通类型参数
控制器
@RequestMapping("/index")
public ModelAndView index() {
ModelAndView mView = new ModelAndView("index");
mView.addObject("username", "admin");
mView.addObject("password", "123456");
return mView;
}
视图
<h1>${username}</h1>
<h1>${password}</h1>
传入Map类型的参数
控制器
@RequestMapping("/index")
public ModelAndView index() {
ModelAndView mView = new ModelAndView("index");
Map<String, String> modelMap = new HashMap<String, String>();
modelMap.put("username", "admin");
modelMap.put("password", "123456");
mView.addAllObjects(modelMap);
return mView;
}
视图
<h1>${username}</h1>
<h1>${password}</h1>
传入对象类型的参数
控制器
@RequestMapping("/index")
public ModelAndView index() {
ModelAndView mView = new ModelAndView("index");
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
mView.addObject(user);
return mView;
}
视图
<h1>username:${user.username}</h1>
<h1>password:${user.password}</h1>
使用 Model 类实现
传入普通类型参数
控制器
@RequestMapping("/index")
public String index(Model model) {
model.addAttribute("username", "admin");
model.addAttribute("password", "123456");
return "index";
}
视图
<h1>${username}</h1>
<h1>${password}</h1>
传入 Map 类型的参数
控制器
@RequestMapping(value="/index")
public String index(Model model) {
Map<String, String> datas = new HashMap<String, String>();
datas.put("username", "admin");
datas.put("password", "123456");
model.addAllAttributes(datas);
return "index";
}
视图
<h1>username:${username}</h1>
<h1>password:${password}</h1>
向页面传递对象参数
控制器
@RequestMapping("/index")
public String index(Model model) {
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
model.addAttribute(user);
return "index";
}
视图
<h1>username:${user.username}</h1>
<h1>password:${user.password}</h1>
接受参数并返回到页面
访问URL:http://localhost:8080/smdemo/index?username=admin
控制器
@RequestMapping(value="/index",params="username")
public String index(String username, Model model) {
model.addAttribute("username",username);
return "index";
}
视图
<h1>${username}</h1>
使用 Map 类型实现
控制器
@RequestMapping("/index")
public String index(Map<String, Object> model) {
model.put("username","张三");
model.put("password","123456");
return "index";
}
视图
<h1>username:${username}</h1>
<h1>password:${password}</h1>
SpringMVC3 整合Spring与MyBatis
创建项目
-
创建 WEB 项目
SSM
-
将相关的 JAR 文件拷贝到
WebRoot/WEB-INF/lib
目录下 -
创建
resources
源码目录 -
将
log4j.properties
与database.properties
拷贝到 resources 目录中 -
在
resources
目录中创建spring-mvc.xml
与spring-mybatis.xml
-
在
src
目录中创建包dao
、service
、controller
和pojo
包 -
创建
WebRoot/WEB-INF/jsp
目录 -
创建
WebRoot/statics
目录
配置SSM
- 打开
WebRoot/WEB-INF/web.xml
文件,并键入如下代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!-- 指定SpringMVC配置文件的位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
<!-- 上下文加载监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置 springMVC 的 入口路径 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定 springmvc 配置文件所在的路径 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<!-- Tomcat容器启动时就启动SpringMVC服务 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 打开
spring-mvc.xml
文件,并键入如下代码:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- IOC注解支持 -->
<context:component-scan base-package="controller"/>
<!-- MVC注解支持 -->
<mvc:annotation-driven />
<!-- 视图层模板解析器配置 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 静态资源配置 -->
<mvc:resources location="/statics/" mapping="/statics/**"/>
</beans>
- 打开
spring-mybatis.xml
文件,并键入以下代码:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- IOC注解支持 -->
<context:component-scan base-package="dao,pojo,service"></context:component-scan>
<!-- 读取Property配置文件 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:database.properties" />
</bean>
<!-- 配置数据源 -->
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
<!-- 配置 SqlSessionFactory -->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="typeAliasesPackage" value="pojo" />
</bean>
<!-- 配置 Mapper 自动实现 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="dao" />
</bean>
<!-- 事务管理器 -->
<bean id="txMananger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
<!-- 支持注解实现事务 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
编写POJO类
根据数据库,编写相关表的 POJO 类
编写数据库操作
在 dao 包中创建接口与映射文件,使用 MyBatis 编写数据库操作
编写业务层
根据相关业务,编写业务层,调用 DAO 层获取数据
编写视图层
将相关视图模板拷贝到 WebRoot/WEB-INF/jsp 目录中,并将静态资源文件拷贝到 WebRoot/statics 目录中
编写控制器
根据相关业务,编写控制器,调用业务层获取数据,并加载相关视图模板与数据进行绑定,然后将最终的结果返回给用户
SpringMVC3 转发与重定向
转发
@RequestMapping(value = "/forward.html")
public String forward() {
return "forward:index.html";
}
重定向
@RequestMapping(value = "/redirect.html")
public String redirect() {
return "redirect:index.html";
}
SpringMVC3 Session与Reuqrest对象
使用 session 对象
@RequestMapping(value="/index.html")
public String index(HttpSession session){ ... }
使用 request 对象
@RequestMapping(value="/index.html")
public String index(HttpServletRequest request){ ... }
SpringMVC3 加载静态资源
- 创建静态资源目录:
WebRoot/statics
- 在 SpringMVC 的配置文件中进行配置:
<!-- 将 URL '/statics/ 与 本地物理路径 'WebRoot/statics/' 进行绑定 -->
<mvc:resources location="/statics/" mapping="/statics/**"></mvc:resources>
- 修改视图页面的静态资源路径:
<link rel="stylesheet" href="<%=basePath %>statics/css/custom.css">
<script src="<%=basePath %>statics/js/custom.js"></script>
SpringMVC3 异常处理
局部异常处理
- 在控制器中创建异常处理方法
@Controller
public class IndexController {
@RequestMapping(value = "/index")
public String index() {
throw new RuntimeException("出现异常");
}
// 异常处理操作 当 Index 控制器中出现 RuntimeException 异常时,则调用此方法
@ExceptionHandler(value={RuntimeException.class})
public String handlerException(RuntimeException e, HttpServletRequest req){
req.setAttribute("e", e);
return "error";
}
}
- 在
WebRoot/WEB-INF/jsp
目录下创建异常显示页面error.jsp
,并键入:
<h1>异常信息:${e.message}</h1>
全局异常处理
- 在 SpringMVC 的配置文件中添加全局异常处理配置
<!-- 全局异常处理 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.RuntimeException">error</prop>
</props>
</property>
</bean>
- 在控制器中抛出异常
@Controller
public class IndexController {
@RequestMapping(value = "/index")
public String index() {
throw new RuntimeException("出现异常");
}
}
- 创建错误页面
WEB-INF/jsp/error.jsp
,并键入如下信息:
<h1>异常信息:${exception.message}</h1>
SpringMVC3 中文乱码问题
在web.xml
中添加spring字符编码过滤器
<filter>
<filter-name>encodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
SpringMVC3 表单标签
声明 taglib 指令
<%@ taglib prefix="fm" uri="http://www.springframework.org/tags/form" %>
form 标签
modelAttribute 属性值应该与 @ModelAttribute 后的参数名称保持一致
View
<fm:form method="post" modelAttribute="user"> ... </fm:form>
Controller
@RequestMapping(value = "/add.html", method = RequestMethod.GET)
public String add(@ModelAttribute User user) { ... }
常用表单标签
名称 | 说明 |
---|---|
<fm:input /> | 单行输入框 |
<fm:password /> | 密码框 |
<fm:hidden /> | 隐藏域 |
<fm:textarea /> | 文本域 |
<fm:radiobutton /> | 单选框 |
<fm:checkbox /> | 复选框 |
<fm:select /> | 下拉列表框 |
<fm:error /> | 显示表单数据校验所对应的错误信息 |
常用属性
属性 | 描述 |
---|---|
path | 属性路径,表示表单对象属性 |
cssClass | 表单组件对应的CSS样式类名 |
cssErrorClass | 当提交表单后报错(服务端错误),采用的CSS样式类 |
cssStyle | 表单组件对应的CSS样式 |
htmlEscape | 绑定的表单属性值是否要对HTML特殊字符进行转换,默认为true |
SpringMVC3 JSR303校验框架
依赖的JAR文件
JSR 303 约束
约束 | 说明 |
---|---|
@Null | 被注释的元素必须为null |
@NotNull | 被注释的元素必须不为null |
@AssertTrue | 被注释的元素必须为 true |
@AssertFalse | 被注释的元素必须为 false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max, min) | 被注释的元素的大小必须在指定的范围内 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
JSR 303 应用
-
将相关 JAR 文件拷贝到 WebRoot/WEB-INF/lib 目录中
-
在 pojo 类的属性上添加校验注解
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
public class User {
@NotEmpty(message="用户编码不能为空")
private String userCode; //用户编码
@NotEmpty(message="用户名称不能为空")
private String userName; //用户名称
@NotNull(message="密码不能为空")
@Length(min=6,max=10,message="用户密码长度为6-10")
private String userPassword; //用户密码
@Past(message="必须是一个过去的时间")
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday; //出生日期
// ...
}
- 在控制器操作方法中指定要校验的入参
/**
* 第一个参数:需要校验的入参
* 第二个参数:校验后的结果对象
*/
@RequestMapping(value="/add.html",method=RequestMethod.POST)
public String addSave(@Valid User user,BindingResult bindingResult){
if(bindingResult.hasErrors()){
// 校验失败时的操作
return "user/useradd";
}
// 通过校验时的操作
}
- 在视图层显示错误信息
<fm:errors path="userCode"/>
SpringMVC3 REST风格的URL
访问URL:http://localhost:8080/项目名称/view/1
@RequestMapping(value="/view/{id} ",method=RequestMethod.GET)
// @PathVariable 注解将 URL 中的 {id} 与 入参 String id 进行绑定
public String view(@PathVariable String id,Model model){
System.out.print(id); // 输出:1
return "userview";
}
SpringMVC3 文件上传
依赖的JAR文件
单文件上传
- 在 SpringMVC 的配置文件中添加如下配置:
<!-- 上传配置 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 允许上传文件的大小设置为 5000000字节 -->
<property name="maxUploadSize" value="5000000"/>
<!-- 将请求的编码格式设置为 UTF-8 -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
- 编写文件上传表单
<form action="/upload.html" method="post" enctype="multipart/form-data">
<div>
<label for="pic">图片</label>
<input type="file" id="pic" name="pic"/>
<input type="submit" value="上传" />
</div>
</form>
- 编写控制器实现上传
@RequestMapping(value="/picmodify.html",method = RequestMethod.POST)
public String picmodify(@RequestParam(value = "pic",required = false)MultipartFile multipartFile,
HttpServletRequest request) {
// 判断是否为空
if(multipartFile.isEmpty()){
request.setAttribute("msg", "您没有指定上传文件");
request.setAttribute("url", "/admin/user/picmodify.html");
return "info";
}
// 设置上传文件存放的路径
String path = request.getSession().getServletContext().getRealPath("statics"+ File.separator+"uploads");
// 设置允许上传文件的最大字节数
long allowSize = 5 * 1024 * 1024;
// 设置允许上传文件的类型
String[] allowExt = {"jpg","png","gif","jpeg"};
// 获取上传文件的文件名
String oldFileName = multipartFile.getOriginalFilename();
// 获取上传文件的扩展名
String oldFileExt = FilenameUtils.getExtension(oldFileName);
// 获取上传文件的字节数
long oldFileSize = multipartFile.getSize();
// 验证上传文件的尺寸
if(allowSize < oldFileSize){
request.setAttribute("msg","您上传的文件太大,最大尺寸不能超过 "+ allowSize +" 个字节");
request.setAttribute("url","/admin/user/picmodify.html");
return "info";
}
// 验证上传文件的类型
if(!Arrays.asList(allowExt).contains(oldFileExt)){
request.setAttribute("msg","您上传的文件类型不正确");
request.setAttribute("url","/admin/user/picmodify.html");
return "info";
}
// 生成新文件
String newFileName = System.currentTimeMillis()+ new Random().nextInt(1000000)+"."+oldFileExt;
File newFile = new File(path,newFileName);
// 创建服务器目录
if(!newFile.exists()){
newFile.mkdirs();
}
// 迁移新文件
try {
multipartFile.transferTo(newFile);
request.setAttribute("msg","上传文件成功:"+newFileName);
} catch (IOException e) {
request.setAttribute("msg","上传文件失败");
request.setAttribute("url","/admin/user/picmodify.html");
e.printStackTrace();
}
return "info";
}
多文件上传
- 在 SpringMVC 的配置文件中添加如下配置:
<!-- 上传配置 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 允许上传文件的大小设置为 5000000字节 -->
<property name="maxUploadSize" value="5000000"/>
<!-- 将请求的编码格式设置为 UTF-8 -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
- 编写文件上传表单
<form action="/upload.html" method="post" enctype="multipart/form-data">
<div>
<label for="pic1">图片1</label>
<input type="file" id="pic1" name="pic"/>
</div>
<div>
<label for="pic2">图片2</label>
<input type="file" id="pic2" name="pic"/>
</div>
<input type="submit" value="上传" />
</form>
- 编写控制器实现上传
@RequestMapping(value="/upload.html",method=RequestMethod.POST)
public String addUserSave(@RequestParam(value ="pic", required = false) MultipartFile[] attachs, HttpServletRequest request){
String idPicPath = null;
for (int i = 0; i < attachs.length; i++) {
MultipartFile attach = attachs[i];
//判断文件是否为空
if(!attach.isEmpty()){
// 省略部分为单文件上传代码
}
}
return "info";
}
前后端分离实现文件上传
后端控制器
@RequestMapping(value = "/picmodify", method = RequestMethod.POST)
@ResponseBody
public Object picmodify1(
@RequestParam(value = "pic", required = false) MultipartFile multipartFile, HttpServletRequest request) {
Map<String,String> map = new HashMap<>();
// 判断上传的文件是否为空
if (multipartFile.isEmpty()) {
map.put("state", "0");
map.put("msg", "请选择文件");
return map;
}
// 设置存储路径
String savePath = request.getSession().getServletContext().getRealPath("statics/uploads");
// 设置允许上传的大小
long allowSize = 1024 * 1024 * 5;
// 设置允许上传的扩展名
String[] allowExtends = {"jpg", "png", "gif"};
// 验证上传文件的大小
long oldSize = multipartFile.getSize();
if (oldSize > allowSize) {
map.put("state", "0");
map.put("msg", "上传文件太大");
return map;
}
// 验证上传文件的扩展名
String oldFileName = multipartFile.getOriginalFilename();
String oldExtend = FilenameUtils.getExtension(oldFileName);
if(!Arrays.asList(allowExtends).contains(oldExtend)){
map.put("state", "0");
map.put("msg", "上传非法类型的文件");
return map;
}
// 生成要保存到服务器上的文件
String newFileName = System.currentTimeMillis() + new Random().nextInt(1000000) + "." + oldExtend;
File newFile = new File(savePath,newFileName);
if(!newFile.exists()){
newFile.mkdirs();
}
// 文件迁移
try {
multipartFile.transferTo(newFile);
map.put("state", "1");
map.put("msg", "上传成功");
} catch (IOException e) {
map.put("state", "0");
map.put("msg", "上传失败");
e.printStackTrace();
}
return map;
}
前端HTML
<form action="#" method="post" enctype="multipart/form-data">
<div class="form-group row">
<label for="pic" class="col-2 text-right m-0 col-form-label">头像上传:</label>
<input type="file" id="pic" name="pic" class="form-control col-3">
</div>
<div class="form-group row">
<div class="offset-2">
<input type="button" class="btn btn-primary pl-5 pr-5 mr-3" onclick="upload_handle()"
value="上传">
</div>
</div>
</form>
前端脚本
function upload_handle() {
let file = $('#pic')[0].files[0];
let formData = new FormData();
formData.append("pic", file);
$.ajax({
url: "http://localhost/api/picmodify",
type: "post",
data: formData,
contentType: false,
processData: false,
resultType: "json",
success: function (res) {
console.log(res);
}
}
);
}
SpringMVC3 响应JSON数据
依赖的JAR文件
返回JSON数据
给方法加注解 @ResponseBody
@RequestMapping("/index")
@ResponseBody // 该注解告诉容器不加载模板,而是直接返回内容到页面
public String index() {
Map<String, String> maps = new HashMap<String, String>();
maps.put("id", "1");
maps.put("name", "zhangsan");
return JSONArray.toJSONString(maps);
}
给类加注解 @RestController
@RestController
public class IndexController{
@RequestMapping("/index")
public String index(){
Map<String, String> maps = new HashMap<String, String>();
maps.put("id", "1");
maps.put("name", "zhangsan");
return JSONArray.toJSONString(maps);
}
}
中文乱码解决
使用注解解决
@RequestMapping(value="/index",produces={"application/json;charset=UTF-8"})
@ResponseBody
public String index() { ... }
使用StringHttpMessageConverter类解决
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
使用FastJsonHttpMessageConverter类解决
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
JSON请求时406错误
报错原因
请求的 URL 后缀如果以 .html
结尾,例如:@RequestMapping("/index.html")
,Spring 将会以 HTML 的形式进行请求,而返回的数据为 JSON 数据,导致请求与响应的格式不统一,所以报 406 错误。
解决方案
只需将请求 URL 的后缀 .html
删除即可,例如 @RequestMapping("/index")
日期格式问题
注解方式解决
通过在POJO类字段上添加注解设置日期格式
public class User{
@JSONField(format="yyyy-MM-dd")
private Date birthday;
// ...
}
配置文件方式解决
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<!-- 解决 中文乱码 问题 -->
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
<!-- 解决 JSON 日期格式问题 -->
<property name="features">
<list>
<!-- Date的日期转换器,转换成的日期格式:yyyy-MM-dd HH:mm:ss -->
<value>WriteDateUseDateFormat</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
混合模式
如果同时使用了 注解方式 和 配置文件方式 解决日期问题,则以 注解方式 为准!
SpringMVC3 多视图解析器
配置XML文件
<!-- 视图层模板解析器配置
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>-->
<!-- 多视图解析器 -->
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="favorParameter" value="true" />
<property name="mediaTypes">
<map>
<entry key="html" value="text/html;charset=UTF-8" />
<entry key="json" value="application/json;charset=UTF-8" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
</bean>
编写控制器
@RequestMapping("/show/{id}")
@ResponseBody
public User getUserById(@PathVariable int id){
return service.getUserById(id);
}
SpringMVC3 自定义转换器
创建自定义转换器
创建 tools.StringToDateConverter
类
package tools;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
public class StringToDateConverter implements Converter<String, Date> {
private String datePattern;
public StringToDateConverter() {
}
public StringToDateConverter(String datePattern) {
this.datePattern = datePattern;
}
@Override
public Date convert(String s) {
Date date = null;
try {
date = new SimpleDateFormat(datePattern).parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
配置自定义转换器
在 SpringMVC 配置文件中配置以下代码:
<!-- 定义转换器 -->
<bean id="myConversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="tools.StringToDateConverter">
<constructor-arg type="java.lang.String">
<value>yyyy-MM-dd</value>
</constructor-arg>
</bean>
</list>
</property>
</bean>
<!-- MVC注解支持 -->
<mvc:annotation-driven conversion-service="myConversionService">
<!-- 中文乱码解决 -->
<mvc:message-converters>
<bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
SpringMVC3 自定义编辑器
创建自定义编辑器
创建类 controller.BaseController
,并键入如下信息:
package controller;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
public class BaseController {
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
System.out.println("initBinder被调用了...");
dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(
new SimpleDateFormat("yyyy-MM-dd"), true));
}
}
使用自定义编辑器
打开控制器类,让其继承 BaseController 类
@Controller
public class UserController extends BaseController{ ... }
SpringMVC3 自定义拦截器
创建自定义拦截器
package interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import pojo.User;
public class SysInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (null == user) {
response.sendRedirect(request.getContextPath() + "/401.jsp");
return false;
}
return true;
}
}
配置自定义拦截器
访问 http://localhost:8080/SSM/sys/*
路径将进入拦截器进行拦截验证
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/sys/**"/>
<bean class="interceptor.SysInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
SpringMVC3 邮箱发送
添加依赖
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
创建配置文件
创建 /resources/spring-mail.xml 配置文件,并键入如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 发送邮件的服务器配置 -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.qq.com"/>
<property name="port" value="465"/>
<property name="username" value="****@qq.com"/>
<property name="password" value="****"/>
<property name="defaultEncoding" value="utf-8"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
<prop key="mail.smtp.socketFactory.port">465</prop>
</props>
</property>
</bean>
<!-- 邮件内容配置 -->
<bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="subject" value="[i旅行]请激活您的账户"/>
<property name="from" value="123456@qq.com"/>
</bean>
</beans>
创建业务层代码
/service/MailService.java
package service;
public interface MailService {
/**
* 发送邮件
* @param to 收件人
* @param message 正文
*/
void send(String to, String message);
}
/service/MailServiceImpl.java
package service;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class MailServiceImpl implements MailService {
@Resource
private SimpleMailMessage mailMessage;
@Resource
private MailSender mailSender;
@Override
public void send(String to, String message) {
mailMessage.setTo(to);
mailMessage.setText("您的激活码是:" + message);
mailSender.send(mailMessage);
}
}
创建控制器层代码
/controller/LoginController.java
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import service.MailService;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Controller
public class LoginController {
@Resource
private MailService mailService;
/**
* 发送邮件
* @param to 收件人
* @param message 正文
* @return
*/
@RequestMapping(value = "/mail")
@ResponseBody
public Object mail(@RequestParam String to,@RequestParam String message){
Map<String, Object> map = new HashMap<>();
mailService.send(to,message);
map.put("to",to);
map.put("message",message);
return map;
}
}
测试
使用 postman 进行测试
SpringMVC4 集成Swagger
Swagger简介
Swagger 是一个Restfull API 文档的在线自动生成工具,可以直接运行,在线测试 API。
Swagger 支持多种语言,比如:JAVA、PHP 等。
官方网站为:https://swagger.io/
环境准备
- JDK1.8
- Spring4.1.7
集成配置步骤
- 在
pom.xml
文件中添加 Swagger2 相关依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.4.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.verson}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.verson}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.verson}</version>
</dependency>
-
下载配置类
SwaggerConfig.java@ComponentScan
设置 Swagger 扫描包@EnableSwagger2
使 Swagger2 生效@Configuration
自动在本类上下文加载一些环境变量信息
-
将 配置类 拷贝到 控制器包 中
-
在 spring-mvc.xml 中添加如下代码:
<mvc:default-servlet-handler />
-
给控制器类添加API说明
- 通过在 API 上添加注解实现,API文档的同步效果
@Api
表明可供 Swagger 展示的结构类(用在类上面)@ApiOperation
描述 API 方法(用在方法上)@ApiParam
单个参数描述@ApiModel
用对象接收参数(用在 Bean 组件类上)@ApiModelProperty
用对象接收参数是,描述对象属性(用在 Bean 组件类属性上)
-
访问 Swagger
访问http://IP:prot/{context-path}/swagger-ui.html
’
Swagger 帮助手册
http://docs.swagger.io/swagger-core/apidocs
SpringMVC4 JSON日期格式化
spring-mvc.xml
<!-- MVC 注解支持 -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
<property name="fastJsonConfig">
<bean class="com.alibaba.fastjson.support.config.FastJsonConfig">
<property name="dateFormat">
<value>yyyy-MM-dd</value>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>