欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringMVC_3.x_入门指南_3

程序员文章站 2024-02-01 13:15:10
...

SpringMVC 3.x

博文目录:

  1. 接收表单值
  2. 文件的上传
  3. 静态资源访问
  4. 视图解析器
  5. 拦截器
  6. 异常处理

 

使用springmvc如何接收页面的传值

 

 我们仍然使用前两篇博文中搭建好的框架!再新添一些东西,用来完成这篇新博文,木有高深的东西,仅仅为了记录一个入门程序员的实战历程!不喜勿喷,欢迎交流!

目前的进度仍然是没有连接数据库的!
新建一个Student类

package com.cn.pojo;

public class Student {

	private Integer id;
	private String name;
	private String address;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
}

  新建StudentController

@Controller
@RequestMapping("/student")
public class StudentController {

	@RequestMapping(value="/add",method=RequestMethod.GET)
	public String addForm(){
		System.out.println("addForm...");
		return "student/add";
	}
	
	@RequestMapping(value="/add",method=RequestMethod.POST)
	public String add(Integer id,String name,String address,String country){
		System.out.println("id="+id+",name="+name+",address="+address+",country"+country);
		return "student/add";
	}
}

  新建student文件夹,在此文件夹中新建add.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>添加学生</title>
  </head>
  <body>
    <h1>添加学生</h1>
    <form action="/student/add" method="post">
    	学号:<input type="text" name="id"/> <br/>
    	姓名:<input type="text" name="name"/> <br/>
    	地址:<input type="text" name="address"/> <br/>
    	国籍:<input type="text" name="country"/> <br/>
    	<input type="submit" value="添加"/> <br/>
    </form>
  </body>
</html>

 

 启动服务器,访问:localhost/student/add
到达add.jsp,填写完整的表单,提交!!!
在控制台会显示接收到的信息!!!!
id=1,name=tom,address=hangzhou,country=USA

问题:
如果我的表单列表非常多,那样的话,我的方法中岂不是要写非常多的参数用来接收!这是我不想要的,有些参数是在一个对象中的(id,name,address),能否使用对象来接收呢?试试呗!!

 

@RequestMapping(value="/add",method=RequestMethod.POST)
public String add(Student student,String country){
	System.out.println("id="+student.getId()+",name="+student.getName()+",address="+student.getAddress()+",country="+country);
	return "student/add";
}

 

 经验证,完美实现接收,真是太棒了!

问题:
如果我的Student类中也有一个属性叫country,那么传的参数是给student,还是参数列表中的country呢?

package com.cn.pojo;

public class Student {

	private Integer id;
	private String name;
	private String address;
	private String country;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	
}

 

@RequestMapping(value="/add",method=RequestMethod.POST)
public String add(Student student,String country){
	System.out.println("student.country: "+student.getCountry()+",country: "+country);
	return "student/add";
}

 你猜出结果了吗?结果是让人惊叹的!竟然同时给两项都赋值了。

student.country=country=**

问题
如果Student中有一个属性是Country对象,Country类中有一个属性是country,那么我们的传值又是怎样的呢?

结论:
值只会直接传值,也就是说,不会给Student对象中的Country对象赋值!

那么如何给我们的student对象中的Country对象赋值呢?
使用下面的表单样式可以实现:

<form action="/student/add" method="post">
	学号:<input type="text" name="id"/> <br/>
	姓名:<input type="text" name="name"/> <br/>
	地址:<input type="text" name="address"/> <br/>
	国籍:<input type="text" name="coun.country"/> <br/>
	<input type="submit" value="添加"/> <br/>
</form>

 coun是Student类中的Country类型的变量;



既然说过了基本的表单,我们把特殊的文件上传一块说了吧!!!
其实文件上传也是表单提交,只是有那么一点点的区别。
我们新建一个用于文件上传的JSP,放到views下面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>文件上传</title>
  </head>
  <body>
    <h1>文件上传</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
    	Name:<input type="text" name="desc"/> <br/>
    	<input type="file" name="file"/> <br/>
    	<input type="submit" value="上传" />
    </form>
  </body>
</html>

 

文件上传的表单有几点需要注意:
一定要设置enctype="multipart/form-data"
上传表单的组件是:input type="file"
使用method="post"进行提交

我们新建一个UploadController

@Controller
public class UploadController {

	@RequestMapping(value="/upload",method=RequestMethod.GET)
	public String uploadForm(){
		return "upload";
	}
	
	@RequestMapping(value="/upload",method=RequestMethod.POST)
	public String upload(String desc,MultipartFile file){
		System.out.println("desc= "+desc);
		System.out.println("name: "+file.getName());
		System.out.println("ContentType: "+file.getContentType());
		System.out.println("OriginalFilename: "+file.getOriginalFilename());
		System.out.println("Size: "+file.getSize());
		
		return "upload";
	}
}

 

启动容器,访问:localhost/upload
选择一个文件上传,哈哈,报错了吧!!!

写道
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?

意思是:你配置文件上传解析器了吗?呵呵,我们确实啥都没有配置呢!!


在springmvc-servlet.xml中添加一项文件上传解析器:

<!-- 文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="100000"/>
</bean>

 SpringMVC提供的文件上传解析器,CommonsMultipartResolver,下面配置的一个属性:

maxUploadSize,你懂的!当然是最大上传体积呀,单位是字节(Byte)!!

文件上传要用到:commons-fileupload,所以我们要在我们的pom.xml中加入我们的commons-fileupload

<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.3</version>
</dependency>

 

启动服务器,选择一个英文名的图片:1.jpg
获得的输出结果为:
desc: hello
name: file
ContentType: image/jpeg
OriginalFilename: 1.jpg
Size: 28119

getName方法获取的是表单的name值,而getOriginalFilename获取的是图片的名称;

怎么存呢?
使用到IO部分内容,这里不多说,只说一种最简单的!

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(String desc,MultipartFile doc){
	System.out.println("desc= "+desc);
	System.out.println("name: "+doc.getName());
	System.out.println("ContentType: "+doc.getContentType());
	System.out.println("OriginalFilename: "+doc.getOriginalFilename());
	System.out.println("Size: "+doc.getSize());
	
	try {
		doc.transferTo(new File("c:/upload",doc.getOriginalFilename()));
	} catch (Exception e) {
		e.printStackTrace();
	}
	
	return "upload";
}

 

 以OriginalFilename为文件名,存到c盘的upload目录中。

如果我们上床一个带中文的图片:2013课表.png
OriginalFilename: 2013è??è?¨.png

产生了乱码!!!怎么解决呢?转码呗!

@RequestMapping(value="/upload",method=RequestMethod.POST)
public String upload(String desc,MultipartFile doc){
	try {
        //将原来的编码转为UTF-8格式,然后存储
		String fileName=new String(doc.getOriginalFilename().getBytes("ISO8859-1"), "UTF-8");
		doc.transferTo(new File("c:/upload",fileName));
	} catch (Exception e) {
		e.printStackTrace();
	}
	
	return "upload";
}

 文件上传暂时告一段落!下面干点啥呢?

一个网站如果只有文字是不是太单调了,我们是不是可以添点图片(非网上的图片)进去呢?

于是我们在webapp文件夹下建立了一个img文件夹,里面放了一张美女的图片1.jpg!


SpringMVC_3.x_入门指南_3
            
    
    博客分类: SpringMVC 异常处理视图解析器文件上传下载接收表单 
 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>home.jsp</title>
  </head>
  <body>
    This is my JSP page. <br>
    <img alt="" src="/img/1.jpg">
  </body>
</html>

 

 启动服务器,输入:localhost/home

写道
警告: No mapping found for HTTP request with URI [/img/1.jpg] in DispatcherServlet with name 'springmvc'

 前面我们也提到过,所有的请求都要经过 *控制器 SpringMVC认为图片也是要请求的,所以我们还需要配置对静态资源的访问;

最好的方式是让所有的静态文件夹放到一个文件夹中:static,注意:在struts中不能使用这个文件夹名称!!我暂时还不清楚为啥?知道的可以跟我说一下!

在springmvc-servlet.xml中配置对静态资源的访问:

<!-- 静态资源 -->
<mvc:resources location="/static/" mapping="/static/**"/>

 这样的话,所有的static中的静态资源都可以被我们访问到了!!!


问题:
我申请的域名是:www.t.com,但是我的主页在服务器上是/home请求的,我如何通过只访问www.t.com就相当于访问www.t.com/home呢?

我们可以在springmvc-servlet.xml中配置视图控制器:viewController

<!-- 视图控制器 -->
<mvc:view-controller path="/" view-name="/home"/>

 最后我们再来看一下SpringMVC中的拦截器

拦截器相当于Servlet中的过滤器和Struts中的拦截器。
怎么使用呢?
1,写我们自己的拦截器,继承SpringMVC提供的拦截器适配器类:HandlerInterceptorAdaptor

2,重写父类的preHandler方法,返回值为true则放行,返回值false则不放行;

3,在springmvc-servlet.xml中配置拦截器

对应的代码如下:

public class MyInterceptor extends HandlerInterceptorAdapter{

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("MyInterceptor...");
		//返回值为true则通过,false则不通过
		return false;
	}
}

 

<!-- 配置拦截器 -->
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.cn.interceptor.MyInterceptor"/>
	</mvc:interceptor>
</mvc:interceptors>

 path="/**" : 表示所有的请求都要经过此拦截器!


你要问了,我不想拦截掉所有的页面,至少你得让我看到/home页面吧!
我们可以排除掉一些页面,配置如下:

<!-- 配置拦截器 -->
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.cn.interceptor.MyInterceptor">
			<property name="excludeUrls">
				<list>
					<value>/home</value>
					<value>/</value>
				</list>
			</property>
		</bean>
	</mvc:interceptor>
</mvc:interceptors>

 在bean中添加property,里面装了若干个url,表示我们排除掉的url;

除了配置此list外,你需要在咱们的拦截器里接收配置的urls;
源码如下:

public class MyInterceptor extends HandlerInterceptorAdapter{
	
	private List<String> excludeUrls;//用来存放配置的urls

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println(request.getRequestURI());
		for (String url : excludeUrls) {
			if(request.getRequestURI().equalsIgnoreCase(url)){
				return true;
			}
		}
		if(request.getSession().getAttribute("curr_user")!=null){
			return true;
		}else{
			return false;
		}
	}
	//配置文件中的list,通过set方法向excludeUrls中添加配置的urls
	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}
	
}

  这样的话,我们就可以访问我们的/home和/了,但是我们的美女却找不到了!!!原因是我们无法访问到/static/里的内容,现修改如下:

public class MyInterceptor extends HandlerInterceptorAdapter{
	
	private List<String> excludeUrls;

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println(request.getRequestURI());
		for (String url : excludeUrls) {
			//如果url请求是以/static/开头的,直接通过...
			if(request.getRequestURI().equalsIgnoreCase(url)||request.getRequestURI().startsWith("/static/")){
				return true;
			}
		}
		if(request.getSession().getAttribute("curr_user")!=null){
			return true;
		}else{
			return false;
		}
	}

	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}
	
}

 对于拦截器拦截掉的请求,也就是return false;的情况,我们一般情况下是让其跳转到某一个页面(比如:登录页,/home等等),如何实现?

第一种方式:
直接使用preHandler中提供的response对象:

public class MyInterceptor extends HandlerInterceptorAdapter{
	
	private List<String> excludeUrls;

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println(request.getRequestURI());
		for (String url : excludeUrls) {
			if(request.getRequestURI().equalsIgnoreCase(url)||request.getRequestURI().startsWith("/static/")){
				return true;
			}
		}
		if(request.getSession().getAttribute("curr_user")==null){
			response.sendRedirect("/home");
		}
		return true;
	}

	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}
	
}

 第二种方式:

通过抛出异常,并配置异常处理来完成跳转:

//自定义异常
public class MyValidateException extends RuntimeException {

	private static final long serialVersionUID = 1L;

}

 

public class MyInterceptor extends HandlerInterceptorAdapter{
	
	private List<String> excludeUrls;

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println(request.getRequestURI());
		for (String url : excludeUrls) {
			if(request.getRequestURI().equalsIgnoreCase(url)||request.getRequestURI().startsWith("/static/")){
				return true;
			}
		}
		if(request.getSession().getAttribute("curr_user")!=null){
			return true;
		}else{
			//如果没有登录,抛出异常,调用异常解析器,决定跳转
			throw new MyValidateException();
		}
	}

	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}
	
}

  在springmvc-servlet.xml中配置异常解析器:

<!-- 异常解析器 -->
<bean id="handlerExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<property name="exceptionMappings">
		<props>
			<prop key="com.cn.exception.MyValidateException">redirect:/home</prop>
		</props>
	</property>
</bean>

 

 当出现:MyValidateException时,执行redirect到/home.

 

 

 

 

 

 

  • SpringMVC_3.x_入门指南_3
            
    
    博客分类: SpringMVC 异常处理视图解析器文件上传下载接收表单 
  • 大小: 23.4 KB