话说
亲爱的读者们,晚上好!SSH框架总结完毕后,今天初步总结下SpringMVC,我们依次总结了Hibernate==》Struts2==》Spring,今天邀请的明星是:SpringMVC!回头看看,就会发现总结顺序都有内在逻辑。在环境搭建、传参方面,今天的主角无疑简单得不能再简单。框架就是让底层东西越来越浅显易懂,类似快餐,可以让你很方便、很快滴吃饱。闲话少说,言归正传。
目录:
1、整体布局
2、环境搭建
3、参数传递
4、总结
因为笔者博客连贯性很强,所以每次都会重复写下开发环境,避免中途来参观的读者不知所云
IntelliJ IDEA(2017.2.5)
Maven Web项目
1、整体布局
2、环境搭建
1、导包
2、配置web.xml
3、Controller层测试
3、配置springmvc-servlet.xml
4、页面
1) 导包
因为SpringMVC是基于Spring的,所有导入spring-context、spring-mvc、spring-web这三个包。
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hmc.springmvc02</groupId>
<artifactId>springmvc02</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>springmvc02 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--Spring context-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>
<!--Spring mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>
<!--Spring web-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>springmvc02</finalName>
</build>
</project>
2) 配置web.xml
这一步非常核心。我们请求页面得第一站就是web,所以你访问的参数,怎么让springMVC来管理呢?就是通过这个DispatcherServlet类来管理的。一旦页面敲下类似**.htm的请求,马上就去找DispatchServlet去处理,处理过程是和注解结合起来的,所以当你要指定调用方法的时候,一切就那么连贯起来了。
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--配置Spring MVC 核心-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
</web-app>
3) Controller层测试
BookAction
这个Controller主要演示注解和方法调用。
package com.hmc.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* User:Meice
* 2017/11/9
*/
@Controller
public class BookAction {
@RequestMapping(name = "/list.htm")
public String list() {
System.out.println("显示图书列表");
return "list";
}
/* @RequestMapping(name = "/add.htm")
public String add() {
System.out.println("新增了图书");
return "add";
}
*/
/* @RequestMapping(name = "/update.htm")
public String update() {
System.out.println("修改了图书");
return "update";
}*/
@RequestMapping("/del.htm")
public void del() {
System.out.println("删除了图书");
}
}
我们访问页面,目的是调用方法,进行业务逻辑处理。怎么调用指定方法?过滤器就起作用了,首先过滤到,然后通过你在对应的方法上加的注解,就去找和注解名字相同的方法,调动后,如何返回页面呢?
这里就牵扯到了视图解析器。这个视图解析器,类似我们配置的struts2.xml.一会再做对比。先看如何配置的?
要想让注解生效,首先是需要扫描包的。这里还要提一下springMVC配置文件的命名规则,一般都是servlet-name+servlet.xml这种命名方式,而且要放到WEB-INF下面,否则提示:
java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/springmvc-servlet.xml]
在下的servlet-name是springmvc,所以这个配置文件名:springmvc-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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描包注解-->
<context:component-scan base-package="com.hmc.springmvc"/>
<!--Spring视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
之所以能够找到页面,而不至于走丢,核心在于这个类:InternalResourceViewResolver
配置方式浅显易懂,类似struts2.xml。想当年,我们在Struts2中想调用方法和返回界面,是这么配置的:
<!--配置-->
<action name="Book_list" class="com.hmc.struts2.action.BookAction" method="list">
<result name="success">/WEB-INF/Book/list.jsp</result>
</action>
当然,采用通配符是这么配置的:
<action name="*_*" class="com.hmc.struts2.action.BookAction" method="${2}">
<result name="success">/WEB-INF/{1}/{2}.jsp</result>
</action>
还要开启DynamicMethodInvocation及全局方法匹配就不在赘述。
所以,对比起来,springMVC理解起来还是很容易滴。
4) 配置springmvc-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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描包注解-->
<context:component-scan base-package="com.hmc.springmvc"/>
<!--Spring视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
5) 页面
很简单,取值就行。注意IDEA默认新建的JS页面EL表达式是关闭的,所以要开启:IsELIgnored=”false”,不然你看到的全都是${}
<%--
User: Meice
Date: 2017/11/9
Time: 15:59
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>图书列表</title>
</head>
<body>
<h2>图书列表界面</h2>
用户名:【${username}】<br/>
密码:【${pwd}】<br/>
对象:<br/>
${book}<br/>
【${book.name}】
<hr/>
</body>
</html>
3、参数传递
LoginController
传参:传单个参数与传对象。
这里传参更加简单。直接把属性作为方法参数即可,如果是个对象,直接用Map或者Model就可以。
package com.hmc.springmvc.controller;
import com.hmc.springmvc.model.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
* User:Meice
* 2017/11/9
*/
@Controller
public class LoginController {
/**
* SpringMVc 传参
*/
@RequestMapping("/login.htm")
public String login(@RequestParam(name = "username") String username, String pwd,@RequestParam int age) {
System.out.println("用户名:"+username+"\t"+"密码:"+pwd);
return "list";
}
/**
* 以上存在问题:
* 1)中文乱码?
* 2)如果用户名和密码都为空,也会提交用户名: 密码: ?
* 如何必须填写后才能登录?
* 当然前提是密码是String类型,默认为空串,假如密码为int pwd,那么不填写,页面就无法跳转,因为默认的空串
* 是无法自动转换为int类型的
*
* 3、@RequestParam 可以对必须要填写的参数做限制,否则报错
* But,@RequestParam(name = "username") String username这是没有效果的,因为默认为空串,还是可以的
* 只是针对Null值才有效。
*
* 如果没有填写,报错:HTTP Status 400 - Required int parameter 'age' is not present
*/
/**
* 传参
*/
//传参法一:Map<>
@RequestMapping("/login.htm")
public String login(String username, String pwd, Map<String,Object> ctx) {
System.out.println("用户名:"+username+"密码:"+pwd);
ctx.put("username",username);
ctx.put("pwd",pwd);
//传入对象
Book book = new Book(3,"《三国演义》");
ctx.put("book",book);
return "list";
}
//传参法二:Model
@RequestMapping("/login.htm")
public String list(String username, String pwd, Model model) {
System.out.println("用户名:"+username +" 密码:"+pwd);
model.addAttribute("username",username);
model.addAttribute("pwd",pwd);
//传参-对象
Book book = new Book(1,"《红楼梦》");
model.addAttribute(book);
return "list";
}
/**
* Book{id=1, name='《红楼梦》'}
* 由此发现,Model的底层还不是Map集合
*/
}
来来,这里我们要回忆下这这几个传参方式:我们从遥远的Servlet说起:
Servlet是这么传参的:
request.setAttribute();
Struts2有3种传参方式:
1)定义属性,生成set()方法;
2)定义对象,生成set()方法,页面用对象.属性;
3)定义对象为属性,然后实现ModelDriven,实现方法。中间传参用到了这个:
ActionContext.getContext.put();
我们的springMVC怎么传参呢?So Easy! 如果是不多的属性,直接给方法带参,参数名和界面表单元素name一致即可;若是对象,使用Model或者Map集合即可。Model本质还是个Map集合,放进去就是Put的事情,人家内部封装好了,参数直接就过去了。因为是转发请求,所以参数可以带过去。怎么带过去滴?问框架喽~
而且,页面直接取值,即便是集合,也可以直接.属性,而不用区分什么key,value之类的。所以EL表达式是真正的强大!
4、总结
1、框架那么多,木有对比,就木有“伤害”。对比了解,了解框架进化过程,会更好的理解框架本身;为什么要这么演化,怎么简化的,才是技术思想精进的真谛;
2、环境搭建时,springMVC是基于Spring的,web.xml方面依托的是DispatcherServlet;视图层servlet.xml,依靠的是视图解析器,主要是这个类:IntervalResourceViewResolver;
3、调用方法通过加注解@RequestMapping()即可,返回字符串就是对应页面即可;
4、参数传递。直接给对应方法带参即可,如果参数过多,就用对象。保存值就通过Map集合和Model来实现。
很简单,到后面的MyBatis也会很简单。当然,表面上运用都是简单的,复杂的运用还很多呢。
如果世界这么简单就好了。
好了,下期再会!