方式一:配置方式
步骤:
1,MVC框架要做的事情:
a) 将url映射到java或java类的方法;
b)封装用户提交的数据;
c) 处理请求——调用相关的业务处理----封装相应的数据;
d)将响应的数据进行渲染,jsp,html等;
2, 相关准备工作:
使用约定化配置,能够进行junit测试,异常处理,本地化,国际化,数据验证类型转换,拦截器。
3, 了解结构:
4,案例:
案例框架:
(1)新建工程:springmvc
(2)导入相应包:
(3)配置web.xml文件-------配置分发器:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 配置springmvc核心分发器,对所有的url后缀为action的进行过滤 -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- 改变springmvc配置文件的位置和名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
注意:<p>DispatcherServlet类将加载springmvc的配置文件,会产生一个spring的子容器,该子容器存放实例</p>
(4)添加springmvc的配置文件,默认在web-inf下添加[DispatcherServlet]----name-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- 声明一个Controller -->
<bean name="/home.action" class="cn.itcast.controller.HomeController"/>
<!-- 配置视图jsp解析器 内部资源视图解析器 前缀+逻辑名+后缀 /WEB-INF/pages/ index .jsp -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
(5)编写HelloController类:
package cn.itcast.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
/**
* @Description:
* @Author: 潘光友
* @Company: http://java.itcast.cn
* @CreateDate: 2016-5-23
*/
public class HomeController extends AbstractController{
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
System.out.println(request.getRequestURI());
return new ModelAndView("index"); //逻辑名
}
}
(6)编写index.jsp文件:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my Spring MVC JSP page2. <br>
</body>
</html>
(7)在浏览器访问效果:
方式二:注解方式
(1)新建项目springmvcnew;
(2)添加包:
(3)配置web.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 配置springmvc核心分发器,对所有的url后缀为action的进行过滤 -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 改变springmvc配置文件的位置和名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvcnew-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
(4)配置springmvcnew-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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 注解开发方式 -->
<mvc:annotation-driven/>
<!-- 包自动扫描 -->
<context:component-scan base-package="cn.itcast.controller"/>
<!-- 配置视图jsp解析器 内部资源视图解析器 前缀+逻辑名+后缀 /WEB-INF/pages/ index .jsp -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
(5)编写HomeController类:
package cn.itcast.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
//http://localhost:8080/springmvcnew/home.action
@RequestMapping("/home2")
public String gohome(HttpServletRequest request){
//System.out.println(request.getRequestURL());
return "index"; //返回逻辑名
}
}
(6)编写index.xml文件:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
This is my JSP page SpringMVC new. <br>
</body>
</html>
(7)在浏览器测试效果:
补充:数据处理:
package cn.itcast.controller;
<span style="font-size:18px;">import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import cn.itcast.domian.User;
@Controller
public class data_deal {
@RequestMapping("/data")
/*@RequestParam("data_name")----data_name是提交的域的名称
例如传值:http://localhost:8080/springmvcnew/data.action?data_name=panzhanggui
*/
public String data(@RequestParam("data_name") String name){
System.out.println(name);
return "data";
}
@RequestMapping("/user")
public String user(User user){
System.out.println(user);
return "data";
}
}
</span>
传值路径:
<a target=_blank href="http://localhost:8080/springmvcnew/data.action?data_name=panzhanggui">http://localhost:8080/springmvcnew/data.action?data_name=panzhanggui</a>
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
跳转结果的方式:
1,设置ModelAndCiew对象。根据View的名称,和视图解析器跳转到指定的页面。
页面:视图解析器的前缀+View name+视图解析器的后缀。
<span style="font-size:18px;">@RequestMapping("/hello2")
public ModelAndView hello(HttpServletRequest requst,HttpServletResponse response){
ModelAndView mv=new ModelAndView();
//封装要显示视图的数据
mv.addObject("msg", "hello annotation");
//视图名
mv.setViewName("index");
return mv;
}</span>
2,通过servletAPI对象来实现(不需要视图解析器)。
<span style="font-size:18px;"> @RequestMapping("/hello3")
public void hello3(HttpServletRequest requst,HttpServletResponse response) throws Exception{
response.getWriter().println("hello spring mvc use httpserrtvlet api");
}</span>
springmvc实现文件上传
1,通过common-fileuoload实现。导入相关jar包。
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
2,配置springmvc的解析器。
<!-- 声明CommonsMultipartResolver解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为1MB -->
<property name="maxUploadSize">
<value>1048576</value>
</property>
相关实现的类:
import java.io.File;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class FileUpload {
@RequestMapping(value="/upload")
public String upload(@RequestParam(value="file",required=false)//
MultipartFile file,HttpServletRequest request,ModelMap model){
//服务器端upload文件夹物理路径
String path=request.getSession().getServletContext().getRealPath("upload");
//获取文件名
String fileName=file.getOriginalFilename();
//实例化一个File对象,表示目标文件(含物理路径)
File targetFile=new File(path,fileName);
if(!targetFile.exists()){
targetFile.mkdirs();
}
//将上传文件写到服务器上指定的文件
try {
file.transferTo(targetFile);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
model.put("fileUrl", request.getContextPath()+"/upload"+fileName);
return "result";
}
}
springMVC拦截器:
1.DispatcherServlet
SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet。DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller来处理。 所以我们现在web.xml中加入以下配置:
<!-- 配置springmvc核心分发器,对所有的url后缀为action的进行过滤 -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 改变springmvc配置文件的位置和名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvcnew-servlet.xml</param-value>
</init-param>
<!-- 改变springmvc配置文件的位置和名称 结束 -->
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
2.静态资源不拦截
如果只配置拦截类似于*.do格式的url,则对静态资源的访问是没有问题的,但是如果配置拦截了所有的请求(如我们上面配置的“/”),就会造成js文件、css文件、图片文件等静态资源无法访问。一般实现拦截器主要是为了权限管理,主要是拦截一些url请求,所以不对静态资源进行拦截。要过滤掉静态资源一般有两种方式,
第一种是采用<mvc:default-servlet-handler />,(一般Web应用服务器默认的Servlet名称是"default",所以这里我们激活Tomcat的defaultServlet来处理静态文件,在web.xml里配置如下代码即可:)
<!-- 该servlet为tomcat,jetty等容器提供,将静态资源映射从/改为/static/目录,如原来访问 http://localhost/foo.css ,现在http://localhost/static/foo.css -->
<!-- 不拦截静态文件 -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/js/*</url-pattern>
<url-pattern>/css/*</url-pattern>
<url-pattern>/images/*</url-pattern>
<url-pattern>/fonts/*</url-pattern>
</servlet-mapping>
Tomcat, Jetty, JBoss, and GlassFish 默认 Servlet的名字 -- "default"
Resin 默认 Servlet的名字 -- "resin-file"
WebLogic 默认 Servlet的名字 -- "FileServlet"
WebSphere 默认 Servlet的名字 -- "SimpleFileServlet"
如果你所有的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定:
<mvc:default-servlet-handler default-servlet-name="所使用的Web服务器默认使用的Servlet名称" />
3.自定义拦截器
SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法。preHandle在业务处理器处理请求之前被调用,postHandle在业务处理器处理请求执行完成后,生成视图之前执行,afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 。所以要想实现自己的权限管理逻辑,需要继承HandlerInterceptorAdapter并重写其三个方法。
首先在springmvc.xml中加入自己定义的拦截器我的实现逻辑CommonInterceptor,
<!--配置拦截器, 多个拦截器,顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
<mvc:mapping path="/" />
<mvc:mapping path="/user/**" />
<mvc:mapping path="/test/**" />
<bean class="com.alibaba.interceptor.CommonInterceptor"></bean>
</mvc:interceptor>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>
我的拦截逻辑是“在未登录前,任何访问url都跳转到login页面;登录成功后跳转至先前的url”,具体代码如下:
/**
*
*/
package com.alibaba.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.alibaba.util.RequestUtil;
/**
* @author tfj
* 2014-8-1
*/
public class CommonInterceptor extends HandlerInterceptorAdapter{
private final Logger log = LoggerFactory.getLogger(CommonInterceptor.class);
public static final String LAST_PAGE = "com.alibaba.lastPage";
/*
* 利用正则映射到需要拦截的路径
private String mappingURL;
public void setMappingURL(String mappingURL) {
this.mappingURL = mappingURL;
}
*/
/**
* 在业务处理器处理请求之前被调用
* 如果返回false
* 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
* 如果返回true
* 执行下一个拦截器,直到所有的拦截器都执行完毕
* 再执行被拦截的Controller
* 然后进入拦截器链,
* 从最后一个拦截器往回执行所有的postHandle()
* 接着再从最后一个拦截器往回执行所有的afterCompletion()
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if ("GET".equalsIgnoreCase(request.getMethod())) {
RequestUtil.saveRequest();
}
log.info("==============执行顺序: 1、preHandle================");
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
String url = requestUri.substring(contextPath.length());
log.info("requestUri:"+requestUri);
log.info("contextPath:"+contextPath);
log.info("url:"+url);
String username = (String)request.getSession().getAttribute("user");
if(username == null){
log.info("Interceptor:跳转到login页面!");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}else
return true;
}
/**
* 在业务处理器处理请求执行完成后,生成视图之前执行的动作
* 可在modelAndView中加入数据,比如当前时间
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("==============执行顺序: 2、postHandle================");
if(modelAndView != null){ //加入当前时间
modelAndView.addObject("var", "测试postHandle");
}
}
/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
*
* 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("==============执行顺序: 3、afterCompletion================");
}
}