SpringMVC初探

本文介绍了SpringMVC的基础知识,包括创建项目、配置文件、控制类、测试类的编写,以及项目的部署。在配置中涉及了DispatcherServlet、WebConfig和RootConfig等。文章详细讲解了在IDEA中创建Web Application Artifact并部署到Tomcat的过程,并强调了Mockito在测试中的应用。
摘要由CSDN通过智能技术生成

mvc4th框架

上方的图片是《Spring实战第四版》给出的,DispatcherServlet处理请求,发给对应的控制器(Controller),控制器返回应答的模型数据和视图名称,DispatcherServlet再去找视图,做出应答发送给用户(浏览器)。下方的是第五版的,简化了服务器端的细节,实际上在服务器端仍然有那些流程。

mvc5th框架
以下内容参考Spring实战

1. 创建项目

通过maven创建项目,在pom.xml中添加依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>

maven的镜像源设置参考别处教程,这里不细说,只是提一下配置maven遇到的bug:

NoSuchMethodError,这个可能是版本问题,新版没有这个方法,或者是 jar包冲突 ,我遇到的情况是maven导入了这个包和另一个旧项目,之间发生了冲突。

PKIX path building failed

http\://maven.aliyun.com/nexus/content/repositories/central/.error=Could not transfer artifact com.github.stefanbirkner\:system-rules\:pom\:1.19.0 from/to alimaven (http\://maven.aliyun.com/nexus/content/repositories/central/)\: sun.security.validator.ValidatorException\: PKIX path building failed\: sun.security.provider.certpath.SunCertPathBuilderException\: unable to find valid certification path to requested target 

这个是在用阿里云镜像时常出现的bug,第一次遇到时发现是阿里云仓库导入依赖的写法不同,另一次解决不了干脆放弃阿里云,用 http://repo1.maven.org/maven2/ .看到阿里云仓库评论不止我遇到了这个问题。

maven遇到包无法导入的问题,进仓库删文件再reimport总是效果不错

2.写基本的配置文件、控制类、测试类

配置DispatcherServlet(SpittrWebAppInitializer)

package spittr.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SprittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] {RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};//将路径映射到DispatcherServlet,/为默认
    }
    //配置DispatcherServlet
    //扩展了AbstractAnnotationConfigDispatcherServletInitializer的类会自动配置DispatcherServlet和Spring应用上下文
}

WebConfig

package spittr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan("spittr.web")//扫描该目录下的控制器
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
//        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        return resolver;
    }

    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

RootConfig

package spittr.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;


@Configuration
@ComponentScan(basePackages={"spittr"},excludeFilters={@Filter(type=FilterType.ANNOTATION,value=EnableWebMvc.class)
})

public class RootConfig {
}

以上三个是配置类,接下来是控制器Controller

package spittr.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import static org.springframework.web.bind.annotation.RequestMethod.*;
import static org.springframework.web.bind.annotation.RequestMethod.GET;

@RequestMapping({"/","/homepage"})//处理对'/'、'/homepage'的请求
@Controller //声明为控制器,目的是找到它并生成Bean,和Conponent效果类似
public class HomeController {
    @RequestMapping(method=GET) //处理对'/'、'/homepage'的get请求
    public String home() {
        return "home";  //视图名为home,传回给DispatcherServlet
    }
}

在webapp->WEB-INF->views新建home.jsp文件,写入如下内容

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>hello</h1>
</body>
</html>

测试类

package spittr.web;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;

import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import spittr.web.HomeController;

public class HomeControllerTest {
    @Test
    public void testHomePage() throws Exception{
        HomeController controller = new HomeController();
        MockMvc mockMvc = standaloneSetup(controller).build();
        mockMvc.perform(get("/")).andExpect(view().name("home"));
    }
}

Mock的使用,https://segmentfault.com/a/1190000006746409

总之使用Mockito进行测试,导入依赖。这里值得学习。前后端分离Restful的开发方法,适合测试。

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.0.111-beta</version>
</dependency>
3.部署项目

Tomcat与jdk之间有版本对应关系如下

web 版本jdk 版本tomcat 版本
version 2.2jdk 1.1tomcat 3.3
version 2.3jdk 1.3tomcat 4.1
version 2.4jdk 1.4tomcat 5.5
version 2.5jdk 1.5tomcat 6.0
version 3.0jdk 1.6tomcat 7.0
version 3.1jdk 1.7tomcat 8.0 或 tomcat 8.5
version 4.0jdk 1.8tomcat 9.0

这里记录下自己部署的流程:

在IDEA中点击右上角倒数第二个Project Structure->Artifacts,添加Web Application achieve,from 已有的Web Application explored(如果没有就先添加一个Web Application explored)。

在Tomcat中运行:选择Build->build artifacts,将得到的out文件夹中.war文件放到Tomcat的whatsapp目录下,运行bin目录中的startup.bat,访问localhost:端口/文件名,即是项目的首页。

在IDEA中运行:在运行窗口上edit configurations, 添加一个tomcat服务,填写目录与端口,在Before launch 中添加build artifact, 即之前的.war文件。

4.更多的控制器与测试

在写好了DispatcherServlet后,我们的功能都是由增加和修改控制器来完成。DispatcherServlet将请求发送给不同的控制器,控制器根据请求的类型和值返回视图名或其他信息(这些信息被称作模型),之后通过JSP把信息处理为HTML格式返回给用户。

看看我们的控制器

1.最普通的,仅返回视图名。

package spittr.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import static org.springframework.web.bind.annotation.RequestMethod.*;
import static org.springframework.web.bind.annotation.RequestMethod.GET;

@RequestMapping({"/","/homepage"})//处理对'/'、'/homepage'的请求
@Controller //声明为控制器,目的是找到它并生成Bean,和Conponent效果类似
public class HomeController {
    @RequestMapping(method=GET) //处理对'/'、'/homepage'的get请求
    public String home() {
        return "home";  //视图名为home,传回给DispatcherServlet
    }
}

2.处理带参数请求的控制器函数

@RequestMapping(method=RequestMethod.GET)
public List spittles(
        @RequestParam(value="max",
                defaultValue="50") long max,
        @RequestParam(value="count", defaultValue="20") int count) 
//通过请求传入两个参数,默认值分别为50,20
//如请求URL"/spittles?max=238900&count=50"
{
    return spittleRepository.findSpittles(max, count);//返回List,其他的视图名等都包括在模型中
}

3.处理路径参数的控制器函数

对于一个资源,形如"/spittles/show?spittle_id=12345"的请求,可以替换为"/spittles/12345"的形式,这样的形式可以直接识别要查找的资源,不必通过带参数的操作。

@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
public String spittle(
        @PathVariable("spittleId") long spittleId,
        Model model) {
    model.addAttribute(spittleRepository.findOne(spittleId));//模型中增加了ID
    return "spittle";
}

分析我们的测试例,使用mock测试

import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import spittr.Spittle;
import spittr.data.SpittleRepository;
import spittr.web.SpittleController;
import java.util.Date;

import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;

public class SpittleIDTest {
    @Test
    public void testSpittle() throws Exception {
        Spittle expectedSpittle = new Spittle("Hello", new Date());
        SpittleRepository mockRepository = mock(SpittleRepository.class);
        when(mockRepository.findOne(12345)).thenReturn(expectedSpittle);

        SpittleController controller = new SpittleController(mockRepository);
        MockMvc mockMvc = standaloneSetup(controller).build();
        mockMvc.perform(get("/spittles/12345"))
                .andExpect(view().name("spittle"))
                .andExpect(model().attributeExists("spittle"))
                .andExpect(model().attribute("spittle", expectedSpittle));
    }
}

很明显分为了两个部分,前半部分是服务器的内容预设。后半部分是进行访问,与之前预设内容比较。

这部分做完之后,我们可以看到如此的目录

mvc目录
之后就去看springboot了,一键建站还看什么springmvc
就这样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值