SpringMVC基本概念和使用

  • Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。

基本架构流程

  • 核心思想 MVC分层设计

1.入门配置

  1. 导包: 最基本的Spring和SpringMVC 8个包,包括web
  2. 配置SpringMVC 设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 开启注解扫描 -->
<context:component-scan base-package="code.controller"/>

<!-- 视图解析器对象 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>

<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven />

</beans>
  1. web 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<display-name>SpringMVC Project</display-name>

<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:SpringMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<!--映射监听-->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>

4.处理函数书写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package code.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping(path = "/test") //一级路径
public class helloController{

// 书写一个方法对请求作出回应
@RequestMapping(path = "/hello") // 二级路径
public String SayHello(){
System.out.println("hello SrpingMVC.");
return "success";
}
}

2.基本配置

  1. 架构图理解
  2. RequestMapping注解
    1
    2
    3
    4
    5
    6
    7
    8
    9
    1.RequestMapping注解Controller下形成一级路径,再书写在func下形成二级目录
    2.path属性 = value 属性
    3.method属性 post get
    4.headers属性 选择接受必须携带哪些headers的url
    5.params属性 选择接受符合规定的参数的url
    6.参数绑定
    1.普通数据类型,直接通过同名方法参数获取
    2.bean对象类型,通过构建javabean 并通过与对象属性相同的属性名获取
    3.绑定集合类型,通过 list[] 或 map[''] 对应封装
  3. 配置过滤器解决中文乱码问题 (web.xml)中
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--配置监听器解决中文乱码问题-->
<filter>
<filter-name>characterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
  1. 自定义类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1.自建转换类 实现 Converter<>接口
2.Srping.xml中配置
<!--配置自定义类型转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<!--加载可用的类型转换器对象-->
<bean class="code.utils.StringToDate"></bean>
</set>
</property>
</bean>
<!-- 开启SpringMVC框架注解的支持 -->
<mvc:annotation-driven conversion-service="conversionService"/>

  1. 获取 Servlet ,session , reqeust, response
    1
    2
    3
    4
    5
    6
    7
    8
    9
    在参数位置引用: HttpServletRequest 和 HttpServletResponse
    @RequestMapping("/Servlet")
    public String testServlet(HttpServletRequest request, HttpServletResponse response){
    System.out.println(request); //request
    System.out.println(request.getSession()); //session
    System.out.println(request.getSession().getServletContext()); //servlet
    System.out.println(response); //response
    return "success";
    }
  2. 强制绑定该参数名的传入参数 @RequestParam(“”)

  3. restfule 编程风格 @PathVariable

    1
    2
    3
    4
    5
    6
    7
    通过 / 后直接跟{参数},减少使用 ?传参和方法名
    @RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable String id){
    System.out.println(id);
    return "success";
    }

  4. 拿到整个post请求的请求体: @RequestBody
  5. 拿到请求的Header @RequestHeader
  6. 拿到请求的cookie值 @CookieValue(value=””)
  7. 函数执行前的方法 @ModelAttribute

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ModelAttribute 会先于当前目录下的方法执行,可以利用其性质先进行封装判断后把值传给处理函数
    @ModelAttribute
    public Account testModelAttribute1(String name,String passwd){
    Account account = new Account();
    account.setName(name);
    account.setPasswd(passwd);
    account.setUser(new User("kid",20));
    return account;
    }


    @RequestMapping("/testModelAttribute")
    public String testModelAttribute2(Account account){
    System.out.println(account);
    return "success";
    }
  8. SessionAttributes 设置session域的共有数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Model默认吧数据存到request 如果要设置到session 
需要在class前添加@SessionAttributes(value = {"msg"})注解

// set
@RequestMapping("/testSessionAttribute")
public String testSessionAttribute(Model model){
model.addAttribute("msg","hello world"); // 为model添加数据
// model 会把数据存到request中
System.out.println("testSessionAttribute");
return "success";
}

// get
@RequestMapping("/getSessionAttribute")
public String getSessionAttribute(ModelMap modelMap){
String msg = (String) modelMap.get("msg"); //取出session的值
System.out.println("getSessionAttribute");
System.out.println(msg);
return "success";
}

// del
@RequestMapping("/delSessionAttribute")
public String delSessionAttribute(SessionStatus status){
status.setComplete(); // 清空session
System.out.println("清空session");
return "success";
}

3.视图解析器

1. 返回值是String 配置视图解析器,正常转发

2. 返回值是void,使用HttpServletrequest / response 转发或者重定向

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编写请求转发:
// request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
//重定向
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("你好!");
return;
}

3. 返回值是ModelAndView

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
ModelAndView mv = new ModelAndView();
User user = new User();
user.setUage(12);
user.setUname("kid");
mv.addObject("user",user); //设置request参数
mv.setViewName("success"); // 设置转发页面
return mv;
}

4. 开放静态资源加载 SpringMVC.xml

1
2
<!--前段控制器,那些静态资源不控制-->
<mvc:resources mapping="/js/**" location="/js/" />

5. AJAX的小案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
前段ajax请求
<script src="js/jquery-3.3.1.min.js"></script>
<script>
//页面加载,绑定单击事件
$(function () {
$("#btn").click(function () {
// alert("hello world by js.");
// 发送ajax请求
$.ajax({
url:"user/testAjax",
contentType:"application/json;charset=UTF-8",
data:'{"uname":"kid","uage":18}',
dataType:"json",
type:"post",
success:function (data) {
alert(data.uname);
alert(data.uage);
}
})
})
})
</script>

controller 执行
// testAjax
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user){
System.out.println("ajax data 已收到...");
System.out.println(user);
user.setUname("kid1999");
return user;
}

注意:ajax数据传输使用的是json springmvc对json传输的封装,使用的jackson包(需要提前导入)

6. 传统文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
1.前端 设置
<form action="fileupload" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br>
<input type="submit" value="upload">
</form>
2.后端接收
@RequestMapping("/fileupload")
public String fileupload(HttpServletRequest request) throws Exception {
System.out.println("upload success...");
// 使用fileupload组件完成文件上传
// 上传的位置
String path = request.getSession().getServletContext().getRealPath("/upload/");
// 判断路径是否存在
File file = new File(path);
if(!file.exists()){
// 创建文件夹
file.mkdirs();
}

// 解析request对象 获取文件上传项
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 解析request
List<FileItem> items = upload.parseRequest(request);
// 遍历
for (FileItem item:items) {
// 判断,当前item对象是否是上传文件项
if(item.isFormField()){
// 普通表单
}else {
String filename = item.getName();
// 文件名设置 唯一值
String uuid = UUID.randomUUID().toString().replace("-","");
filename = uuid + "_" + filename;
item.write(new File(path,filename)); // 完成文件上传
item.delete(); //清空临时缓存
}
}
return "success";
}

注意: 需要依赖commons-io和fileupload组件

7. SpringMVC的文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1.前端
<form action="/springmvcUpload" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"><br>
<input type="submit" value="upload">
</form>
2.后端SpringMVC处理
// SpringMVC文件上传
@RequestMapping("/springmvcUpload")
public String springmvcUpload (HttpServletRequest request,MultipartFile upload) throws IOException {
System.out.println("upload success...");
// 先用
String path = request.getSession().getServletContext().getRealPath("/upload/");
File file = new File(path);
if(!file.exists()) file.mkdirs();
String uuid = UUID.randomUUID().toString().replace("-","");
String filename = upload.getOriginalFilename();
filename = uuid + "_" + filename;
upload.transferTo(new File(path,filename));
return "success";
}

3.SpringMVC.xml
<!--配置文件解析器对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value= "10485760"></property>
</bean>

注意:前端input的name 对应后端 MultipartFile 的参数名

8. 跨服务器文件上传 (略)

9. 异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    1.编写自定义异常类,做提示信息 SysException
public class SysException extends Exception{
// 存储提示信息
private String message;
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
public SysException() {
}
}
2.编写异常处理器 实现 HandlerExceptionResolver
public class SysExceptionSolver implements HandlerExceptionResolver {
// 处理业务逻辑
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
// 获取异常对象
SysException ex = null;
if(e instanceof SysException) ex = (SysException)e;
else ex = new SysException("系统正在维护....");
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("message",ex.getMessage());
mv.setViewName("error"); //跳转
return mv;
}
}
3.配置异常处理器 bean
<!--配置异常处理器-->
<bean id="sysExceptionSolver" class="code.Exception.SysExceptionSolver"/>

流程: 上抛错误到前端控制器,自定义异常处理器处理异常。
使用时上抛到该错误:
public String testError() throws SysException{ // 上抛异常
System.out.println("异常测试");
try {
int a = 10/0;
} catch (Exception e) {
// 控制台打印
e.printStackTrace();
// 抛出自定义异常信息
throw new SysException("查询所有用户出现错误。。");
}
return "success";
}

10. SpringMVC拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
1.编写拦截器,实现HandlerIntercepter
public class myIntercepter implements HandlerInterceptor {
// 预处理,controller 方法之前
// return true 放行。。
// return false 不放行
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle拦截器已生效。。。");
return true;
}

// 预处理,controller 方法之后,web页面之前
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
// 直接做请求转发
// httpServletRequest.getRequestDispatcher("").forward(httpServletRequest,httpServletResponse);
}
// 预处理,web页面之后 最后的方法
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

}
}

2.配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!--配置单个-->
<mvc:interceptor>
<!--拦截路径-->
<mvc:mapping path="/*"/>
<!--不拦截-->
<!--<mvc:exclude-mapping path=""/>-->
<!--配置bean-->
<bean class="code.intercepter.myIntercepter"/>
</mvc:interceptor>
</mvc:interceptors>

4.SSM整合。。