SpringMVC

本文详细介绍了SpringMVC的工作原理,包括前端控制器、处理器映射、适配器和视图解析过程,并指导了环境搭建步骤,涵盖了XML配置和注解方式。此外,还讲解了RESTful风格、前后台传参、过滤器和拦截器,以及JSON处理和编码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 概述

Spring MVC 是Spring3.0 后发布的,基于Java 实现的MVC的轻量级Web 框架,底层仍然是Servlet;
用于接收请求,响应处理结果,管理界面层中的控制器对象;

2. 原理

2.1 原理图

在这里插入图片描述

2.2 说明

1)浏览器发送请求到前端控制器(DispatcherServlet);
2)前端控制器收到请求后,将请求转给处理器映射器(HandlerMapping);
3)处理器映射器根据配置信息(XML或注解)查找 Handler,返回给前端控制器;
4)前端控制器调用处理器适配器(HandlerAdapter)去执行Handler;
5)处理器适配器执行Handler,即具体的Controller 方法;
6)Handler 执行完毕,向处理器适配器返回ModelAndView (SpringMVC 一个底层对象);
7)处理器适配器再向前端控制器返回 ModelAndView ;
8)前端控制器请求视图解析器(ViewResolver)去执行视图解析,根据逻辑视图名解析成真正的视图(JSP);
9)视图解析器向前端控制器返回View;
10)前端控制器进行视图渲染,将模型数据(ModelAndView 对象中)填充到request域;
11)前端控制器向用户响应结果。

2.3 组件

2.3.1 前端控制器(DispatcherServlet)

就是一个Servlet,负责接收请求,响应处理结果;
相当于转发器或中央处理器,减少其他组件的耦合度。
位置:web.xml

2.3.2 处理器映射器(HandlerMapping)

根据用户请求的url,通过XML 配置或注解查找要执行的Handler。
位置:web.xml 中 classpath指定的文件中。如:classpath:dispatcher-servlet.xml

2.3.3 处理器适配器(HandlerAdapter)

按照特定的规则(HandlerAdapter 要求的规则)去执行Handler。
位置:与处理器映射器同文件

2.3.4 处理器(Handler)

具体的Controller 方法。

2.3.5 视图解析器(ViewResolver)

根据逻辑视图名解析成真正的视图(View 对象)。

2.3.6 视图(View)

视图类型:jsp、jstlView、freemarkerView、pdfView等。

3. 环境搭建(XML)

3.1 创建 Maven 项目并导入jar

pom.xml

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1.3-b06</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <!--POM右键 Maven ⇒ Reimport -->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

3.2 创建Module

1)项目右键Add Support 选择Web。
2)Project Structure ⇒ Artifacts ⇒ 选中项目 ⇒ WEB-INF下创建 lib 文件文件夹 ⇒ 添加jar 包

3.3 web.xml

	<servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!--配置dispatcher.xml作为mvc的配置文件-->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.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>

3.4 dispatcher-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: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.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">
    <!--处理器映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--视图解析器:DispatcherServlet 给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--Handler-->
    <bean id="/hello" class="com.chengyu.controller.HelloController"/>
</beans>

3.5 controller

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // ModelAndView 模型和视图
        ModelAndView mv = new ModelAndView();
        // 封装对象,放到ModelAndView中。Model
        mv.addObject("msg","HelloSpringMvc!");
        // 封装要跳转的视图,放到ModelAndView中
        mv.setViewName("hello"); // /WEB-INF/jsp/hello.jsp
        return mv;
    }
}

3.6 hello.jsp

${msg}

3.7 项目结构

在这里插入图片描述

4. 环境搭建(注解)

相较于XML 配置,3.1~3.3、3.6 的内容是一致的,下记两点不同。

4.1 dispatcher-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: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.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">
    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.chengyu.controller"/>
    <!-- 让SpringMvc 不处理静态资源 (.css,.js,.html,.mp3...) -->
    <mvc:default-servlet-handler/>
    <!-- 注册注解驱动,简化了纯Spring 中的配置。
    Spring 中想要使@RequestMapping 生效,需要注册DefaultAnnotationHandlerMapping 和AnnotationMethodHandlerAdapet -->
    <mvc:annotation-driven/>
    <!--视图解析器:DispatcherServlet 给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

4.2 controller

@Controller
//@RequestMapping("/controller")
public class HelloController {
    @RequestMapping("/hello")
    public String hello(Model model){
        model.addAttribute("msg","HelloSpringMvcAnnotation!");
        return "hello"; // hello.jsp
    }
}

5. RestFul 风格

5.1 概念

是一个资源定位及资源操作的风格,基于这个风格设计的软件可以更简介,更有层次,更易于实现缓存等机制。

5.2 例子

传统风格:
http://localhost:8080/03_restful/add?a=1&b=2

@Controller
public class RestFulController {
    @RequestMapping("/add")
    public String add(int a, int b, Model model){
        model.addAttribute("msg",a + b);
        return "hello";
    }
}

RestFul 风格:
http://localhost:8080/03_restful/addRestFul/1/2

@Controller
public class RestFulController {
    @RequestMapping("/addRestFul/{a}/{b}")
    public String addRestFul(@PathVariable int a, @PathVariable int b, Model model){
        model.addAttribute("msg",a + b);
        return "hello";
    }
}

5.3 约束请求类型

@RequestMapping 替换为:
@GetMapping
@PutMapping
@DeleteMapping
@PostMapping

@Controller
public class RestFulController {
    @GetMapping("/addRestFulGet/{a}/{b}")
    public String addRestFulGet(@PathVariable int a, @PathVariable int b, Model model){
        model.addAttribute("msg",a + b);
        return "hello";
    }
}

5.4 优点

1)简介:路径简介,获取参数简介(名称可以不一致,类型会自动转换);
2)高效:支持缓存;
3)安全,隐藏参数。

6. 转发和重定向

6.1 请求和响应

@Controller
public class ModelTest {
    @RequestMapping("/test")
    public String testReqResp(HttpServletRequest req, HttpServletResponse resp){
        HttpSession session = req.getSession();
        System.out.println(session);
        req.setAttribute("msg",session);
        return "hello";
    }
}

6.2 转发

dispatcher-servlet.xml 中的视图解析器部分删除。

默认就是转发。test1 与 test2 等价。
test2 写法与视图解析器有无无关。

@Controller
public class ModelTest {
    @RequestMapping("/test1")
    public String test1(Model model){
        model.addAttribute("msg","123");
        return "/WEB-INF/jsp/hello.jsp";
    }
    @RequestMapping("/test2")
    public String test2(Model model){
        model.addAttribute("msg","123");
        return "forward:/WEB-INF/jsp/hello.jsp";
    }
}

6.3 重定向

浏览器地址发生变化。
test3 写法与视图解析器有无无关。

@Controller
public class ModelTest {
    @RequestMapping("/test3")
    public String test3(Model model){
        model.addAttribute("msg","123");
        return "redirect:/index.jsp";
    }
}

7. 前后台传参

7.1 同名参数

http://localhost:8080/03_restful/user/test1?name=chengyu

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/test1")
    public String test1(String name, Model model){
        model.addAttribute("msg",name);
        return "hello";
    }
}

7.2 不同名参数

http://localhost:8080/03_restful/user/test1?username=chengyu

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/test2")
    public String test2(@RequestParam("username") String name, Model model){
        model.addAttribute("msg",name);
        return "hello";
    }
}

7.3 对象参数

会自动匹配对象中属性,名称一样,可以直接传递。

http://localhost:8080/03_restful/user/test3?name=chengyu

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/test3")
    public String test3(User user, Model model){
        model.addAttribute("msg",user.getName());
        return "hello";
    }
}

8. 过滤器、拦截器

8.1 过滤器

过滤器是Servlet 规范中的一部分,任何Java web 项目都可以使用。
可以对所有要访问的资源进行过滤。

利用过滤器处理乱码。
web.xml

    <!-- SpringMvc 的乱码过滤器 -->
    <filter>
        <filter-name>encoding</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>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

自定义过滤器的操作与Servlet 相同,此处省略。

8.2 拦截器

拦截器是SpringMVC框架自己的东西,只有使用了SpringMVC 框架的工程才能使用。
只负责拦截访问控制器的方法,访问Jsp等页面部分不会进行拦截。
AOP 思想的应用。

注意:SpringMVC 拦截器针对HandlerMapping

MyInterceptor:

public class MyInterceptor  implements HandlerInterceptor {
	// 进入Handler 之前执行,多用于身份验证、授权等
    // true:放行,执行下个拦截器
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("===处理前===");
        return true;
    }
    // 进入Handler 方法后,返回ModelAndView 前执行,将共用模型数据传到视图,如菜单导航等,也可统一指定视图
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("===处理后===");
    }
    // 执行完Handler 之后执行,统一异常、日志处理(放在第一个拦截器的地位)
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("===清理===");
    }
}

dispatcher-servlet.xml

    <!--拦截器配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--拦截所有url 路径,包括子路径-->
            <mvc:mapping path="/**"/>
            <bean class="com.chengyu.controller.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

访问Controller 时会输出:

===处理前===
===处理后===
===清理===

9. JSON

JSON(JavaScript Object Notation),JS 对象标记语言,轻量级数据交换格式,层次清晰,有效的提升网络传输效率。本质是一个字符串!

9.1 JS 中JSON 字符串与对象转换

// 对象
var obj = {name:'chengyu',age:'30'};
// json 字符串
var json = '{"name":"chengyu","age":"30"}';

html:

<html>
<head>
    <title>Title</title>
    <script type="text/javascript">
        var user = {
            name:'chengyu',
            age:'30'
        };
        console.log(user);
        // 将JS 对象转为 Json
        var json = JSON.stringify(user);
        console.log(json);
        // 将Json 转为 JS对象
        var obj = JSON.parse(json);
        console.log(obj);
    </script>
</head>
<body>
${msg}
</body>
</html>

JSON 转字对象
在这里插入图片描述

9.2 Java 中对象转 JSON

9.2.1 引入第三方包 JackJson

lib 文件中也要添加引用。

    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
    </dependencies>
@Controller
public class JsonController {
    @RequestMapping(value = "/hello",produces = "application/json;charset=utf-8")
    @ResponseBody // 不走视图解析器
    public String jsonTest() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        User user = new User("chengyu",30,"大连");
        // String str = user.toString();
        String str = mapper.writeValueAsString(user);
        return str;
    }
}

user.toString() 返回的内容:
User{name=‘chengyu’, age=30, address=‘dalian’}

writeValueAsString 返回的内容:
{“name”:“chengyu”,“age”:30,“address”:“dalian”}

补充:
不走视图解析器方式一:
@Controller
@ResponseBody

不走视图解析器方式二:
@RestController

9.2.2 引入第三方包 FastJson

导包。lib 文件中也要添加引用。

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
    </dependency>

9.3 json 乱码

1)可以单独在Controller 中解决。

@RequestMapping(value = "/hello",produces = "application/json;charset=utf-8")

2)统一解决,修改配置文件,一劳永逸。
dispatcher-servlet.xml

    <!-- json 乱码-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                     </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
@Controller
public class JsonController {
    @RequestMapping("/hello1")
    @ResponseBody // 不走视图解析器
    public String jsonTest2() {
        User user = new User("chengyu",30,"大连");
        String str = JSON.toJSONString(user);
        return str;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值