0、pom.xml配置
<project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>gensoku</groupId>
<artifactId>TouhouProject</artifactId>
<version>1.0</version>
<packaging>war</packaging> <!-- 打包方式 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency> <!-- junit测试 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency> <!-- spring框架 -->
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency><!-- AOP模块 -->
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<dependency> <!-- tomcat大概需要 -->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency> <!-- jsp解析 -->
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<repositories>
<repository> <!-- 远程仓库 -->
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin> <!-- tomcat插件配置 -->
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<hostName>localhost</hostName>
<port>8080</port>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
<plugin> <!-- 模块测试的配置 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<configuration>
<includes>
<include>**/hellotest.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<resources>
<resource> <!-- 静态文件打包配置 -->
<directory>F:/java_demo/rumia_spring_web/pages</directory>
<includes>
<include>*.html</include>
<include>*.jsp</include>
</includes>
<targetPath>pages</targetPath>
</resource>
</resources>
</build>
</project>
1、Servlet前端控制器
拦截请求并分发至控制器、视图解析器等进行处理。
由两种应用上下文组成。
package gensoku;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
//前端servlet
public class myServlet extends AbstractAnnotationConfigDispatcherServletInitializer
{
@Override
protected String[] getServletMappings() //拦截映射
{
return new String[]{ "/" };
}
@Override
protected Class<?>[] getServletConfigClasses() //web配置
{
return new Class<?>[] { webConfig.class };
}
@Override
protected Class<?>[] getRootConfigClasses() //其他组件配置
{
return new Class<?>[] { rootConfig.class };
}
}
2、rootConfig上下文
一般是驱动应用后端的中间层和数据层组件。
package gensoku;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable
public class rootConfig
{
}
3、webConfig上下文
一般是控制器、视图解析器及处理器映射。
package gensoku;
import org.springframework.context.annotation.Bean;
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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import gensoku.data.newsData;
import gensoku.data.newsDataHub;
@Configuration
@EnableWebMvc
//@ComponentScan("gensoku")
public class webConfig extends WebMvcConfigurerAdapter
{
@Bean //控制器
public myController retController()
{
return new myController(retDatahub());
}
@Bean //数据读写器,插入4条数据进行测试
public newsDataHub retDatahub()
{
newsDataHub testhub = new newsDataHub();
testhub.addNewsData(new newsData(1, "day 1", "Rumia eats people"));
testhub.addNewsData(new newsData(2, "day 2", "Yokali hides people"));
testhub.addNewsData(new newsData(3, "day 3", "UUZ kills people"));
testhub.addNewsData(new newsData(4, "day 4", "Reimu beats people"));
return testhub;
}
@Bean //视图解析器
public ViewResolver viewResolver()
{
InternalResourceViewResolver rs = new InternalResourceViewResolver();
rs.setPrefix("/WEB-INF/classes/pages/"); //增加资源路径前缀
rs.setExposeContextBeansAsAttributes(true);
return rs;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer con)
{
con.enable(); //允许静态资源由默认servlet处理
}
}
4、Controller
控制器根据映射处理servlet传过来的请求,并将处理结果(主要是ModelAndView,包括视图名和模型数据)返回给视图解析器处理。
控制器即MVC的C,视图即V,模型即M.
package gensoku;
import static org.springframework.web.bind.annotation.RequestMethod.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import gensoku.data.newsDataHub;
@Controller
public class myController
{
private newsDataHub dataHub;
public myController()
{
dataHub = null;
}
public myController(newsDataHub ndh)
{
dataHub = ndh;
}
@RequestMapping(value = "/", method = GET) //请求映射,包括地址和方法
public String getHome()
{
System.out.println("GET : /home");
return "home.html"; //直接返回视图名
}
@RequestMapping(value = "/news", method = GET) //地址包含请求的参数(id)
public ModelAndView getNews(@RequestParam(value="id", required=false, defaultValue= "1") int id)
{
System.out.println("GET : /news id=" + id);
ModelAndView mv = new ModelAndView();
mv.setViewName("newslist.jsp"); //定义视图名
mv.addObject("newsName", dataHub.findNewsData(id).getName()); //以键值对方式加入模型数据
mv.addObject("newsContent", dataHub.findNewsData(id).getContent());
return mv; //返回视图及模型数据
}
@RequestMapping(value = "/secret/{magicNum}", method = GET) //地址以占位符形式包含路径参数
public ModelAndView checkSecret(@PathVariable("magicNum") int N)
{
ModelAndView mv = new ModelAndView();
mv.setViewName("secret.jsp");
mv.addObject("waitnum", N);
if(N == 514114)
mv.addObject("ans", "Right!");
else
mv.addObject("ans", "Wrong!");
return mv;
}
}
5、模块测试
主要对控制器进行了测试。
package gensoku;
import org.junit.Test;
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.springframework.test.web.servlet.MockMvc;
import gensoku.data.newsData;
import gensoku.data.newsDataHub;
public class hellotest
{
@Test
public void testing() throws Exception
{
System.out.println("---testing---");
newsDataHub ndh = new newsDataHub(); //定义并初始化数据读取器
for(int i=0; i<10; i++)
{
ndh.addNewsData(new newsData(i, "rumia_"+i, "^-^"));
}
myController mc = new myController(ndh);
MockMvc mc_test = standaloneSetup(mc).build(); //针对控制器生成mock
mc_test.perform(get("/")).andExpect(view().name("home.html")); //利用mock对控制器进行请求,并校验其返回视图名
mc_test.perform(get("/news?id=2")).andExpect(view().name("newslist.jsp"))
.andExpect(model().attributeExists("newsName")); //校验模型数据是否包含某键
mc_test.perform(get("/secret/1234")).andExpect(view().name("secret.jsp"))
.andExpect(model().attributeExists("ans"));
}
}
6、JSP及tomcat服务器测试
利用java装配就不需要web.xml,但是tomcat版本需要在7以上。
为了方便测试没有搭建完整的服务器,而是利用了maven的tomcat插件直接嵌入执行,需要利用pom中的resource标签打包静态文件(html和jsp等)。
这里利用jsp进行简单渲染(直接将控制器返回的ModelAndView数据填上了),代码结构大概如下:
<head></head>
<body>
<h1>Fake News</h1>
<br>
Name : ${requestScope.newsName}
<br>
Content : ${requestScope.newsContent}
<br>
</body>
这里的一个大坑在于,如果测试时直接命令:
mvc clean tomcat7:run
只是将mvc代码嵌入tomcat执行,不会将静态资源打包进去,因此读取静态资源都会出现404的情况,因此测试时需要先打包成war再强制其读取war执行:
mvc clean package tomcat7:run-war-only
这样就可以读取静态资源了。