springmvc-入门

本文详细介绍了如何使用Maven搭建Spring MVC项目,包括添加依赖、配置、webapp结构,以及Controller的响应机制,涵盖核心控制方法、三大组件和自定义类型转换。还涵盖了Controller中处理不同类型的请求、页面跳转、数据回写和注解的使用。
摘要由CSDN通过智能技术生成


SpringMVC 是一种基于Java 的实现 MVC 设计模型的请求驱动类型的轻量级Web框架。

1 maven从0搭建

1.1 添加依赖

<!--spring-->
<dependency>
   <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.10</version>
</dependency>
<!--spring-webmvc-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.10</version>
</dependency>
<!--servlet-->
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
</dependency>
<!--jsp-->
<dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.0</version>
</dependency>

1.2 添加spring-mvc配置

<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="com.test"/>
</beans>

1.3 创建webapp

创建maven项目后,src/main下添加webapp文件夹及下级文件及文件夹,如下图:
在这里插入图片描述
web.xml文件内容:

<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">
    <!--springmvc核心控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</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>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--编码过滤器,解决乱码问题-->
    <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>
</web-app>

注意:/代表对所有请求都进行过滤操作,都要经过dispatcherServlet,但是某些静态资源通过dispatcherServlet是找不到的,所以需要在spring-mvc.xml中增加排除过滤的配置
<mvc:resources mapping="/文件夹/**" location="/文件夹/"/> 或者dispatcherServlet找不到时交由tomcat找的配置<mvc:default-servlet-handler/>。

1.4 测试Controller

@Controller
public class TestController {

    @RequestMapping("/test")
    @ResponseBody
    public String printSome(){
        return "spring mvc test";
    }
}

tomcat配置:
在这里插入图片描述
启动tomcat,测试结果:
在这里插入图片描述

2 核心解析

2.1 核心控制处理方法

DispatcherServlet中doDispatch方法:

 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;

                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    //1 查询handler,返回处理器执行链
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                    //2 请求执行handler
                    //2.1 获取处理器适配器
                    HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
                    //2.2 执行handler,并返回结果
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
                // 3 视图解析器进行处理
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }

        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if (multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }

        }
    }

2.2 三大组件

处理器映射器、处理器适配器、视图解析器是springmvc的三大组件,spring-webmvc包下org/springframework/web/servlet/DispatcherServlet.properties
中配置了这三大组件:

# 处理器映射器
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
	org.springframework.web.servlet.function.support.RouterFunctionMapping

# 处理器适配器
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter

# 视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

2.3 修改视图解析器默认参数

修改视图解析器中默认值:
(UrlBasedViewResolver中默认prefix、suffix均为"")

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!--前缀,给controller中的返回值加前缀,可指定路径-->
	<property name="prefix" value="/"></property>
	<!--后缀,给controller中的返回值加后缀,可指定文件类型-->
	<property name="suffix" value=".jsp"></property> 
</bean>

3 Controller响应

3.1 页面跳转

3.1.1 返回字符串

@RequestMapping("/test")
public String test1(){
    return "test";
}

返回值为:视图解析器中默认的参数prefix+“test”+suffix,如果要跳转去执行另一个controller方法,返回值可以为:

forward:路径
redirect:路径

3.1.2 返回ModelAndView对象

@RequestMapping("/test2")
public ModelAndView test2(){
    ModelAndView modelAndView = new ModelAndView();
    //重定向
    //modelAndView.setViewName("redirect:test.jsp");
    //转发
    modelAndView.setViewName("forward:test.jsp");
    modelAndView.addObject("user","marry");
    return modelAndView;
}

test.jsp中可以通过${user}显示。

3.2 回写数据

3.2.1 输出流

@RequestMapping("/test3")
public void test3(HttpServletResponse response) throws IOException {
     response.getWriter().print("testspringmvc");
 }

3.2.2 返回字符串

增加@ResponseBody注解:

@RequestMapping("/test4")
@ResponseBody
 public String test4(){
     return "test4";
 }

3.2.3 返回对象或集合

添加jackson依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>

spring-mvc.xml中添加配置,为处理器适配器配置消息转换参数,指定使用jackson进行对象或集合的转换:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
        </list>
    </property>
</bean>

或者使用springmvc的注解驱动:

<!--自动加载RequestMappingHandlerMapping和 RequestMappingHandlerAdapter-->
<mvc:annotation-driven/>
3.2.3.1 返回对象
@RequestMapping("/test6")
@ResponseBody
public Map test6() throws Exception {
    Map<String,Object> map = new HashMap();
    map.put("name","kk");
    map.put("skil",new String[]{"lis","lll"});
    return map;
}
3.2.3.2 返回集合
@RequestMapping("/test7")
@ResponseBody
public List test7() throws Exception {
    List<Object> list = new ArrayList<>();
    Map<String,Object> map1 = new HashMap();
    map1.put("name","kk");
    map1.put("skil",new String[]{"lis","lll"});
    list.add(map1);
    Map<String,Object> map2 = new HashMap();
    map2.put("name","ss");
    map2.put("skil",new String[]{"ooo","ppp"});
    list.add(map2);
    return list;
}

4 Controller请求

4.1 基本数据类型参数

@RequestMapping("/test8")
@ResponseBody
public String test8(String userName)  {

    return String.format("user:%s",userName);
}

请求方式:/test8?userName=kk

4.2 POJO类型参数

 @RequestMapping("/test9")
 @ResponseBody
 public User test9(User user)  {
     return user;
 }

请求方式:/test9?userName=kk
注意:
①userName需与User中的字段相同
②需要引入依赖jackson
两者都满足,才能实现自动映射

4.3 数组类型参数

@RequestMapping("/test10")
@ResponseBody
public String test10(String[] parms)  {
    return Arrays.toString(parms);
}

请求方式:/test10?parms=kk&parms=ss&&parms=pp

4.4 集合类型参数

@RequestMapping("/test11")
@ResponseBody
public List<User> test11(@RequestBody List<User> users)  {
    return users;
}

请求方式:postman中以POST请求方式发送请求,请求参数为json格式字符串,见下图。
在这里插入图片描述
也可以在使用前端页面发送ajax请求时指定contentType为json格式。

4.5 自定义类型转换器

客户端输入字符串,controller中的接收参数为Date,如果不自定义转换器,报错如下:
在这里插入图片描述
自定义一个日期类型转换器:

//string类型转换为Date类型
public class DateConvert implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        try {
            return new SimpleDateFormat("yyyy-MM-dd").parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

spring-mvc.xml文件中添加配置:

<mvc:annotation-driven conversion-service="converterService"/>

<bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean">
     <property name="converters">
         <list>
             <bean class="com.test.convert.DateConvert"/>
         </list>
     </property>
 </bean>

自定义类型转换器的好处:
①可以实现数据类型校验,不符合转换规则的数据可以在提交时就阻断;
②减少重复进行数据转换的代码。

5 注解

注解说明
@RequestMapping用于指定请求的URL
@ResponseBody用于指定按照返回的类型返回数据
@RequestBodypost请求时,接收请求参数值
@RequestParam将请求参数与方法参数名进行映射,并可设置参数是否必传
@PathVariable获取请求路径中参数的值,如/user/{id},(@PathVariable(value=“id”) int id)
@RequestHeader获取请求头,(@RequestHeader(value=“User-Agent”,required = false) String userAgent)
@CookieValue获取指定Cookie的值,(@CookieValue(value = “JSESSIONID”) String jid)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值