spring mvc 和 struts2 优缺点:
spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,速度更快;
struts2可以用属性接收参数,方法共享,而spring mvc只能用参数来注入;
spring3 mvc的验证也是一个亮点,支持JSR303
DispatcherServlet 是spring mvc的核心控制器,作用是将请求分发给spring控制器。
web.xml配置:
<!-- 配置spring mvc servlet -->
<servlet>
<servlet-name>MVC</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<!-- 加载SpringMVC的xml到 spring的上下文容器中 -->
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/mvc*.*</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MVC</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
可以在mvc-context.xml中配置资源访问路径 mapping作为访问路径 location配置实际资源路径
<mvc:resource mapping="/resources/**" location="/resource/" />
mvc-context.xml(spring mvc 上下文配置文件)
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
<!-- 配置注解驱动,在项目中可以使用注解来标注控制器 -->
<mvc:annotation-driven />
<!-- 自动扫描的包名 -->
<context:component-scan base-package="com.beijing.action">
</context:component-scan>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
<value>messages</value>
</property>
</bean>
<!-- 国际化 -->
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver">
</bean>
<!-- 支持上传文件 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
<!-- 资源视图解析器,返回的视图会在自动映射在/WEB-INF/jsp包下,后缀为.jsp 约定优于配置的开发模式-->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.InternalResourceView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑 -->
<property name="suffix" value=".jsp" />
</bean>
<!-- 拦截器,对于/my/*下的访问路径都会进行拦截,mappingURL为注入属性 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/my/*" />
<bean class="com.beijing.action.MyInteceptor">
<!-- 注入须要拦截的action -->
<property name="mappingURL" value="onsubmit.action"></property>
</bean>
</mvc:interceptor>
</mvc:interceptors>
</beans>
Login.java
import java.io.File;
import java.io.IOException;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
/*
* @Controller:声明此类为控制器
*
* 全局路径:/my
*
* @SessionAttributes:声明user_in_session为session级属性;
* 具体用法见testSession()方法;
* 如有多个属性则用{"abc","def"}
*
*/
@Controller
@RequestMapping("/my")
@SessionAttributes("user_in_session")
public class Login {
/*
* 请求方式可以为 GET post
* 参数status=1才会执行此方法
* 访问路径为:http://localhost:8080/testSpringMVC/my/onsubmit.action?status=1&userid=123&username=abc
* 前台参数userid对应后台参数id,必填项;
* 为user传递参数: 请求:username=abc ,会自动封装成user对象,可为空;
*/
@RequestMapping(params="status=1",value="/onsubmit",method={RequestMethod.GET,RequestMethod.POST})
public ModelAndView onSubmit(@RequestParam("userid") int id,User user)
throws Exception {
System.out.println("onSubmit~~~~~~~~~~~");
System.out.println("id:"+id);//输出 id:1
System.out.println("username: "+user.getUsername());//如果不传递user则输出:username: null
return new ModelAndView("success");
}
/*
* @RequestBody:获取请求体
* @ResponseBody:返回
* 前台ajax请求实例:如下
* $.ajax({
type : 'POST',
url : 'http://localhost:8080/testSpringMVC/my/login.action',
data : '{username:abc}',// http body 部分
contentType : 'application/json',
dataType : 'text',
success : function(data) {
alert(data);//弹出{username:abc,password:12345}
}
})
* @ModelAttribute:接收请求参数,赋值方式:username=nihao
* 如:http://localhost:8080/testSpringMVC/my/login.action?username=nihao
*
*/
@RequestMapping(value="/login",method={RequestMethod.POST})
@ModelAttribute
public @ResponseBody String login(@RequestBody String body,@ModelAttribute User user) {
System.out.println("user:"+user.getUsername());//输出:user:nihao
System.out.println("body:"+body);//输出 :body:{username:abc}
return "{username:abc,password:12345}";
}
/*
* jsp里可以获取到此session
* <%
Object s = session.getAttribute("user_in_session");
out.print(s);//输出nihao
%>
*/
@RequestMapping(value="/session")
public ModelAndView testSession(ModelMap model){
//放入的user_in_session属性拥有了session级作用域
model.addAttribute("user_in_session", "nihao");
//model.addAttribute(user); -- 这里,user为一个实例,而前台可以获取这个实例,键为"user"
return new ModelAndView("success");
}
/*
* 先访问testSession方法,将nihao放到session中
* 再访问testSession2方法,会取出值:nihao
*
* 或者参数设置为:@ModelAttribute("user_in_session") String username
* 这时参数username 被赋值:nihao ;
*/
@RequestMapping(value="/session2")
public ModelAndView testSession2(ModelMap model){
System.out.println(model.get("user_in_session"));//输出nihao
return new ModelAndView("success");
}
/*
* @ModelAttribute :标注模型属性为password,值为String password
*
* url:http://localhost:8080/testSpringMVC/my/testModelAttribute.action?password=nishishui
* 则输出nishishui
*/
@RequestMapping(value="/testModelAttribute")
public void test(@ModelAttribute("password") String password){
System.out.println(password);//输出:nishishui
}
/*
* 上传单个文件
* 须要jar包
* commons-fileupload-1.2.2.jar
* commons-io-2.1.jar
* <form action="./upload.action" method="post" enctype="multipart/form-data">
* <input type="file" name="file" />
* <input type="submit" value="Submit" />
* </form>
*
*@RequestParam : 标注的参数为必填,若required = false 则可为空
*/
@RequestMapping(value = "/upload")
public void upload(@RequestParam(value = "file", required = true)
MultipartFile file) {
//首先检查file是否复合规格
//保存到绝对路径
String path = "F:/apache-tomcat-6.0.37-windows-x64/apache-tomcat-6.0.37/webapps/img";
File f = new File(path,"123.jpeg");
if(!f.exists()){
f.mkdir();
}
try{
//Transfer the received file to the given destination file.
file.transferTo(f);
}catch (Exception e) {
//保存异常
}
}
/*
* 批量上传:
*
* 如果文件参数为空,则报客户端语法错误
* The request sent by the client was syntactically incorrect.
* 前台参数files和后台files参数对应
* <form action="./upload2.action" method="post" enctype="multipart/form-data">
<input type="file" name="files" />
<input type="file" name="files" />
<input type="submit" value="Submit" />
</form>
*/
@RequestMapping(value="/upload2")
public void upload2(@RequestParam MultipartFile[] files) throws IllegalStateException, IOException{
String path = "F:/apache-tomcat-6.0.37-windows-x64/apache-tomcat-6.0.37/webapps/img";
for (MultipartFile file : files) {
File f = new File(path,file.getOriginalFilename());
file.transferTo(f);
}
}
/*
* 第一种表单验证 ,这种验证须要在User类上添加注释
* 引用标签库:<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
* <!-- commandName:参数名称 action:路径 -->
<form:form commandName="user" action="./valid.action">
<!-- path:user对象的属性-->
username:<form:input path="username" />
<form:errors path="username" element="div" />
password:<form:input path="password" />
<form:errors path="password" element="div" />
<input type="submit" value="submit"/>
</form:form>
@Valid:实现对user对象验证
*
*/
@RequestMapping(value="/valid")
public ModelAndView save(@Valid User user, BindingResult result){
return new ModelAndView("success");
}
/*
* 绑定校验器:UserValidator
*/
@InitBinder
public void initBinder(DataBinder binder){
System.out.println("第一步");
binder.setValidator(new UserValidator());
}
/*
* 利用校验器:Validator来验证参数
*
* 访问此方法时,打印顺序:第一步 第二步 第三步 第四步
* 校验user时,会查找绑定的校验器 UserValidator,校验器检查是否支持当前对象supports
* 接下来执行validate方法把错误信息绑定到errors对象上。
*/
@RequestMapping(value = "/valid2")
public String save2(@Valid User user, BindingResult result) {
System.out.println("第四步");
if (result.hasErrors()) {
return "redirect:/success";
}
return "success";
}
}
User.java
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
public class User {
@NotEmpty(message="用户名不能为空")
@Size(min=3,max=6,message="用户名必须在3~6位之间")
private String username = null;
@NotEmpty(message="密码不能为空")
private String password = null;
private String password2 = null;
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return this.username;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return this.password;
}
public void setPassword2(String password) {
this.password2 = password;
}
public String getPassword2() {
return this.password2;
}
}
UserValidator.java
import org.springframework.validation.Validator;
import org.springframework.validation.Errors;
public class UserValidator implements Validator {
@SuppressWarnings("unchecked")
public boolean supports(Class clazz) {
System.out.println("第二步");
return clazz.equals(User.class);
}
//Errors就是Spring用来存放错误信息的对象。
//obj :校验对象
public void validate(Object obj, Errors errors) {
System.out.println("第三步");
User user = (User) obj;
if (!"admin".equals(user.getUsername())) {
errors.rejectValue("username", "usernameerror", null, "用户名不正确");
}
if (!"123456".equals(user.getPassword())) {
errors.rejectValue("password", "passworderror", null, "密码不正确");
}
if (!user.getPassword().equals(user.getPassword2())) {
errors.rejectValue("password2", "doublepassword", null,
"2次输入的密码不一致");
}
}
}
MyInteceptor.java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class MyInteceptor implements HandlerInterceptor {
public MyInteceptor() {
}
// 注册要拦截的url
private String mappingURL;
private String loginPage = "/login.html";
public void setMappingURL(String mappingURL) {
this.mappingURL = mappingURL;
}
/*
* 在controller执行前进行拦截;
* 如果返回true:则执行controller,如果false,则中断
*/
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String url = request.getRequestURL().toString();
if (url.lastIndexOf(mappingURL) >= 0) {
//判断是否登录
//返回登录页面
request.getRequestDispatcher(loginPage).forward(request, response);
return false;
}
return true;
}
/*
* 在controller执行后、渲染视图前拦截
*
*/
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
补充1:
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<!-- 将表单绑定到模型属性 -->
<sf:form method="post" modelAttribute="user" >
<!-- path:绑定在user实例中的属性 -->
<sf:input path="username" />
<sf:checkbox path="yes" />
<sf:password path="password" />
</sf:form>
补充2:
{username} 为占位符,与参数中的username对应,参数中的username接收访问路径中的username变量的
值;
例如:访问username/abc ,那么username接收到的值为abc
@RequestMapping(value="/{username}")
public void add(@PathVariable String username){
}
源码:点击打开链接