本文介绍如何使用 JetBrains IntelliJ IDEA,快速搭建 Spring MVC 项目。
一、Create New Project,打开下图
在左侧选择Spring,勾选Spring - Spring MVC,选中Download,点击Next,到达如下界面。
在这里填写项目名称,例如HelloWorld,选择项目位置,其他内容无需修改,点击Finish,创建完成,这时应该会自动下载Spring MVC项目所需要的jar包,总共18+4个,下载完成后自动进入项目。
二、配置web.xml
创建项目的过程中,会自动向web.xml写入以下内容:
<?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">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
我们需要向其中加入如下几项内容:
1、<filter>
和<filter-mapping>
标签,目的是将编码格式全部指定为UTF-8编码格式。
<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>
2、<servlet-mapping>
标签。
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
与<servlet>
标签相对应,用于规定使用的路由映射。
其中<servlet-mapping>
中的<servlet-name>
和<servlet>
中的<servlet-name>
相同,<url-pattern>
用于规定使用该映射方式的URL。
添加完成后的 web.xml 内容大致为:
<?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">
<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>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
(这里先插入一段关于另一个xml文件(dispatcher-servlet.xml)的介绍,后面详讲)
dispatcher-servlet.xml 中的 dispatcher 即 web.xml 中的<servlet-name>
的内容,若在 web.xml 中配置为<servlet-name>myDispatcherServlet</servlet-name>
,则此处应为myDispatcherServlet-servlet.xml。
三、正式开始MVC项目
在M(Model)V(View)C(Controller)项目中,控制器(Controller)用于处理请求并生成响应,其处理过程中会使用到模型(Model)和视图(View),模型用于处理数据相关的信息,而视图则是为了将内容显示出来。
(一)建立控制器
1、在src文件夹中,建立一个名为controller的包,用于放置各控制器。
2、在controller中建立一个名为index的类,添加相应的注解,使之成为一个控制器。
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("index")
public class Index {
// method
}
这样我们收到的所有以/index
开头的URL请求就都会被转发到这个类来做处理了。
(注)这里解释一下,什么叫注解,通俗地讲,注解就是以一定的格式来标注该类/方法的各功能的语法,例如上面的@Controller
@RequestMapping
,@Controller
注解标注了Index
类为一个控制器类,@RequestMapping
标注了URL为何值时使用这个类/方法。
(二)建立视图页
接下来,我们就需要去建立视图页了,通常我们是不希望用户看到未渲染的视图,故不能直接放在web文件夹下,而WEB-INF文件夹恰好具有这样的性质,于是我们在web/WEB-INF文件夹下建立我们的view文件夹,用于存放视图页,例如在view文件夹下建立一个名为index.jsp的文件,内容假设为
<%@ page contentType="text/html;charset=UTF-8" language="java" trimDirectiveWhitespaces="true" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>内容${message}</p>
</body>
</html>
(三)注册到程序池
前面提到过dispatcher-servlet.xml文件,这里就要来讲讲它的具体用法了,我们刚刚建立了一个名为controller的包,但还没将其注册到dispatcher-servlet当中,因此需要在dispatcher-servlet.xml添加<context:component-scan base-package="controller"/>
。同样需要将view注册,即添加
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
最终的文件内容为:
<?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: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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="controller"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
(四)渲染视图
回到控制器,向Index类中添加index()方法。
@RequestMapping("index.html")
public String index() {
return "index";
}
Index.java整体内容如下:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("index")
public class Index {
@RequestMapping("index.html")
public String index() {
return "index";
}
}
至此,我们的MVC项目就初步完工了。
四、利用Tomcat进行调试
按下F5,选中Edit Configurations,打开调试配置界面,在左侧点击+,选择Tomcat Server,在提示Warning的地方点击Fix后即可Debug,默认是映射在8080端口,并默认添加项目名_war_exploded作为项目路径,这个可自行调整。这样就可以通过Tomcat将项目映射到8080端口了,在浏览器中打开http://localhost:8080/index/index.html
五、排雷
在完成了上面的步骤之后,大家(包括我)都兴致冲冲地打开了这个URL,结果就是一盆冷水浇下来了,一行大大的
HTTP Status 404 – 未找到
极其醒目。
这是为什么呢?这是因为项目的支持库文件都在lib文件夹里,但是在部署的时候却并不会被自动移到相应位置。
于是就需要我们手动将lib文件夹移动到web/WEB-INF文件夹下面,并打开idea的File→Project Struct→Librarie,在里面将项目结构重导一下,重启Tomcat,就可以发现,打开的不再是404报错啦!
但是,我们看到的和我们理想的好像也不太一样呀。我们写的是
<p>内容${message}</p>
但我们打开源代码看到的却只有
<html>
<head>
<title>Title</title>
</head>
<body>
<p>内容</p>
</body>
</html>
这显然不应该呀,${message}
去哪了呢?
嗯,这个时候就应该结束一下EL表达式(Expression Language)了,算了,篇幅有限,今天只讲用法,想了解的自行百度。
${message}
就是作为EL表达式的形式书写在JSP中,获取message的值并显示在该位置,而我们刚刚并没有对message赋值,当然就只能为空啦。
要怎么给它添加值呢,当然是回到控制器了呀。
给index()加上参数Model model
,再给model加上属性,就像这样,
@RequestMapping("index.html")
public String index(Model model) {
model.addAttribute("message","==>text");
return "index";
}
再重启一下Tomcat,来看看呢,是不是就对了呀。
<html>
<head>
<title>Title</title>
</head>
<body>
<p>内容==>text</p>
</body>
</html>
六、扩展:参数传递
=>例如将http://localhost:8080/index/param.html?paramName=paramValue
中的参数取出。
(一)原生API(基本不用)
@RequestMapping("param.html")
public void param(Model model, HttpServletRequest request) {
Object paramValue = request.getParameter("paramName");
}
(二)同名匹配(耦合性比较高,也不建议)
@RequestMapping("param.html")
public String param(Model model, Object paramName) {
Object paramValue = paramName;
model.addAttribute("message",paramValue);
return "index";
}
(三)@RequestParam 注解
@RequestMapping("param.html")
public String param(Model model, @RequestParam("paramName") Object paramValue) {
model.addAttribute("message",paramValue);
return "index";
}
(四)JavaBean 传参
在model包中建立一个Bean模型,命名为Params,内容为
package model;
public class Params {
private String param1;
private String param2;
public void setParam1(String param1) {
this.param1 = param1;
}
public void setParam2(String param2) {
this.param2 = param2;
}
public String getParam1() {
return param1;
}
public String getParam2() {
return param2;
}
}
在Index类中写入params方法:
@RequestMapping("params.html")
public String params(Model model,model.Params params) {
String message = String.format(
"param1=%s;param2=%s",
params.getParam1(),
params.getParam2()
);
model.addAttribute("message",message);
return "index";
}
=>上面的四种方法,既适用于GET传参,也适用于POST传参。
(五)PathVariable
除了上面的标准传参方式,还有一种特殊的传参,即参数是通过URL直接传输,但是又不会以参数的格式写在URL中,可以隐藏其参数的实质。依靠的是@PathVariable注解。
@RequestMapping("param.html/{paramName}")
public String param(Model model, @PathVariable("paramName") Object paramValue) {
model.addAttribute("message",paramValue);
return "index";
}
看起来@PathVariable和@RequestParam注解还是有很大的相似之处的。
有了上面这些功能,一个 Spring MVC 项目就基本成型了。
第一次在CSDN写文章,干脆就再多写一点吧,把文件功能也写了吧。
七、文件处理
(一)上传文件
普通的上传文件就不讲了,Sping MVC的方法肯定比它要方便很多。
1、导入相关的jar包,包括commons-fileupload-1.4.jar
和commons-io-2.6.jar
(我用的是这个版本,当你们看到这篇文章的时候,应该已经有更新的版本了)
2、在dispatcher-servlet.xml中加入
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
在Index类中添加upload方法
@RequestMapping(value = "upload.html", method = RequestMethod.POST)
public void handleAjax_addDownload(@RequestParam MultipartFile file) {
String fileName = file.getOriginalFilename();
InputStream ins = file.getInputStream();
// insert into database, etc.
}
(二)下载
既然上传有着不同于原生API的方式,那么下载显然也会有。
稍微简化一点写法吧,就假设现在已经有一个文件被读出来了,在字节数组byte[] fileBytes中,文件名为fileName,直接上代码。
@RequestMapping("/download.html")
public ResponseEntity<byte[]> download() {
// 将UTF-8编码格式的文件名字符串转成ISO-8859-1编码的格式。
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
// 建立一个响应头部。
HttpHeaders headers = new HttpHeaders();
向响应头部添加文件名
headers.setContentDispositionFormData("attachment", fileName);
// 在头部设置响应格式。
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 返回带有文件字节内容和头部的HTTP响应。
return new ResponseEntity<>(fileBytes, headers, HttpStatus.CREATED);
}
八、打包部署
出来在idea中进行调试我们还需要将项目能够打包部署到服务器,方法也很简单。
打开File→Project Struct→Artifacts,点击+,选择Web Application: Archive→For '_: war exploded,填写输出路径,并保存。
打开Build→Build Artifacts,选择All Artifacts→Build,即可导出war包,将其复制到Tomcat的webapps文件夹下,重启Tomcat,就会自动解包运行了。