Spring MVC使用总结

一、配置

1、pmo.xml文件中加入spring所需依赖

	<!--spring所需依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.3.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.8.RELEASE</version>
    </dependency>

    <!--其他需要的包-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.4</version>
    </dependency>

2、添加框架支持

右击我们的项目文件夹,选择add framework support
在这里插入图片描述
然后在窗口中分别选中spring和springmvc,并且选择spring是,记得勾选springconfig.xml

如果没有看见spring相关选项,说明系统已经默认,可以到Project StruStructure—Mudules–删掉Spring项…然后回头再来选一次即可看见
在这里插入图片描述

3、完善目录结构

创建相关文件夹

在这里插入图片描述

4、xml文件配置

1、配置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_3_1.xsd"
         version="3.1">

  <display-name>Archetype Created Web Application</display-name>

  <!--开始页面-->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <!--配置Spring IoC配置文件路径-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>

  <!--配置ContextLoaderListener用以初始化Spring IoC容器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--配置DispatcherServlet-->
  <servlet>
    <!--Spring MVC会根据servlet-name配置,找到/WEB-INF/dispatcher-servlet.xml作为配置文件载入Web工程中-->
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <init-param>
      <!--配置dispatcher.xml作为mvc的配置文件-->
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>

    <!--使得Dispatcher在服务器启动的时候就初始化-->
    <load-on-startup>2</load-on-startup>
    <async-supported>true</async-supported>


  </servlet>
  <!--servlet拦截配置-->
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

</web-app>

2、配置applicationContext.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:tx="http://www.springframework.org/schema/c"
       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">


</beans>

3、配置Spring MVC配置文件dispatcher-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" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--启用spring的一些annotation -->
    <context:annotation-config/>

    <!--使用注解驱动-->
    <mvc:annotation-driven />

    <!--自动扫描装配-->
    <context:component-scan base-package="example.controller" />

    <!--静态资源映射-->
    <!--本项目把静态资源放在了webapp的statics目录下,资源映射如下-->
    <mvc:resources mapping="/css/**" location="/WEB-INF/statics/css/"/>
    <mvc:resources mapping="/js/**" location="/WEB-INF/statics/js/"/>
    <mvc:resources mapping="/image/**" location="/WEB-INF/statics/image/"/>

    <!--定义视图解析器-->
    <!--找到Web工程/WEB-INF/view文件夹,且文件结尾为jsp的文件作为映射-->
    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/view/" p:suffix=".jsp" />

    <!--如果有配置数据库事务,需要开启注解事务的,需要开启这段代码-->
    <!--
    <tx:annotation-driven transaction-manager="transactionManager" />
    -->
</beans>

二、简单使用

Controller实例:

@Controller("myController")
@RequestMapping("/role")
public class RoleController{
    
    
	@Autowired
	private RoleService roleService = null;

	@RequestMapping(value = "/getRole", method = RequestMethod.GET)
	public ModelAndView getRole(@RequestParam(value = "id", required = false) Long id){
    
    
		Role role = roleService.getRole(id);
		ModelAndView mv = new ModelAndView();
		mv.setViewName("roleDetails");
		mv.addObject("role", role);
		return mv;
	}
}

@Controller代表该类是一个控制器类,Spring MVC 扫描的时候就会把它作为控制器加载进来。
@RequestMapping指定了对应的请求的URI以及请求类型(如果没有配置请求类型,那么所有的请求都会响应),Spring MVC在初始化的时候就会将这些信息解析,存放起来,于是就有了HandlerMapping。
@RequestParam(value = “id”, required = false) Long id代表获取一个HTTP请求的长整型参数——id,默认情况下要求该参数不能为空,可以设置配置项required=false,代表允许参数为空。如果要获取的是Session中的数据,则可以使用 @SessionAttribute(“userName”) String userName来获取。
mv.setViewName(“roleDetails”) 代表返回的数据模型为roleDetails. jsp(配置里配置了.jsp)。但是在目前的前端技术中普遍使用Ajax技术,往往需要后台返回JSON数据给前端使用,这就需要修改为mv. setView(new MappingJackson2JsonView())
mv. addObject(“role”, role)代表给数据模型添加了一个角色对象,这样就可以通过将数据渲染到视图中来呈现给用户。
那么jsp文件就可以用如下代码来呈现数据:

<c:out value="${role.id}"></c:out>

三、详解

1、接收参数

Spring MVC比较智能化,如果传递过来的参数名称和HTTP的保存一致,那么无需任何注解也可以获取参数。

示例代码:

扫描二维码关注公众号,回复: 12310693 查看本文章
@RequestMapping("/commonParams")
public ModelAndView commonParams(String roleName, String note){
    
    
	System.out.println("roleName =>" + roleName);
	System.out.println("note =>" + note);
	ModelAndView mv = new ModelAndView();
	mv.setViewName("index");
	return mv;
}

如果参数名称和HTTP请求参数名称一致,那么就可以直接获取参数,这样的方式允许参数为空。

在没有任何注解的情况下,Spring MVC也有映射POJO的能力。只要将参数设置为POJO,并且POJO的属性和HTTP请求参数名称一致,那么它们就能有效传递参数。

如果参数名称和HTTP请求参数的名称不一致,则可以采用@RequestParam注解获取参数:

public ModelAndView requestParam(@RequestParam(value = "role_name", required = false) String roleName, String note){
    
    
	...... 
}

如果参数被@RequestParam注解,那么默认情况下不能为空,如果希望允许它为空,那么要修改它的配置项required为false,代表允许参数为空。

如果参数通过URL传递,那么获取参数需要@RequestMapping和@PathVariable两个注解协作完成:

@RequestMapping("/getRole/{id}")
public ModelAndView pathVariable(@PathVariable("id") Long id){
    
    
	......
}

{id}代表接收一个参数,注解@PathVariable表示从URL的请求地址中获取参数。

如要接收JSON参数,则可用如下代码实现:

public ModelAndView addRoles(@RequestBody List<Role> roleList){
    
    
	......
}

注解@RequestBody表示要求Spring MVC将传递过来的JSON数组数据,转换为对应的Java类型。@RequestBody主要用来接收前端传递给后端的json字符串中的数据(请求体中的数据),GET方式无请求体,所以前端只能使用POST方式进行提交。

2、重定向

通过返回带有redirect的字符串实现重定向:

@RequestMapping("/addRole")
public String addRole(Model model, String roleName, String note){
    
    
	Role role = new Role();
	role.setRoleName(roleName);
	role.setNote(note);
	roleService.insertRole(role);
	
	//绑定重定向数据模型
	model.addAttribute("roleName", roleName);
	model.addAttribute("note", note);
	model.addAttribute("id", role.getId());
	
	return "redirect:./showRoleJsonInfo.do";
}

这里的Model是一个数据模型,可以给它附上对应的数据模型,然后通过返回字符串来实现重定向的功能。

通过返回视图实现重定向:

@RequestMapping("/addRole2")
public ModelAndView addRole2(ModelAndView mv, String roleName, String note){
    
    
	Role role = new Role();
	role.setRoleName(roleName);
	role.setNote(note);
	roleService.insertRole(role);
	
	//绑定重定向数据模型
	mv.addAttribute("roleName", roleName);
	mv.addAttribute("note", note);
	mv.addAttribute("id", role.getId());
	mv.setViewName("redirect:./showRoleJsonInfo.do");
	
	return mv;
}

通过RedirectAttribute数据模型实现重定向(代码最简洁):

@RequestMapping("/addRole3")
public String addRole3(RedirectAttributes ra, Role role){
    
    
	//绑定重定向数据模型
	ra.addFlashAttribute("role", role);

	return "redirect:./showRoleJsonInfo2.do";
}

使用RedirectAttributes方法后,Spring MVC会将数据保存到Session中,重定向后就会将其清除。

3、保存并获取属性参数

注解@RequestAttribute(获取一次请求的参数)
@RequestAttribute主要的作用是从HTTP的request对象中取出请求属性,只是它的范围周期是在一次请求中存在。

示例代码如下:

@RequestMapping(value = "/getRole", method = RequestMethod.GET)
	public ModelAndView getRole(@RequestAttribute(value = "id", required = false) Long id){
    
    
		Role role = roleService.getRole(id);
		ModelAndView mv = new ModelAndView();
		mv.setViewName(new MappingJackson2JsonView());
		mv.addObject("role", role);
		return mv;
	}

注解@SessionAttributes(保存数据到HTTP的Session对象中)

在控制器中可以使用注解@SessionAttributes来设置对应的键值对,不过这个注解只能对类进行标注,不能对方法或参数注解。它可以配置属性名称或者属性类型。它的作用是当这个类被注解后,Spring MVC执行完控制器的逻辑后,将数据模型中对应的属性名称或者属性类型保存到HTTP的Session对象中。

示例代码如下:

@Controller("myController")
@RequestMapping("/attribute")
//可以配置数据模型的名称和类型,两者取或关系
@SessionAttributes(names = {
    
    "id"}, types = {
    
    Role.class})
public class AttributeController{
    
    
	@Autowired
	private RoleService roleService = null;

	@RequestMapping("/sessionAttributes")
	public ModelAndView sessionAttrs(Long id){
    
    
		Role role = roleService.getRole(id);
		ModelAndView mv = new ModelAndView();
		mv.setViewName("sessionAttribute");
		mv.addObject("role", role);
		mv.addObject("id", id);
		return mv;
	}
}

注解@SessionAttribute(获取Session对象中的数据)

@RequestMapping("/sessionAttribute")
public ModelAndView sessionAttr(@SessionAttribute("id") Long id){
    
    
	Role role = roleService.getRole(id);
	ModelAndView mv = new ModelAndView();
	mv.setViewName(new MappingJackson2JsonView());
	mv.addObject("role", role);
	return mv;
}

@SessionAttribute注解的参数默认不可以为空,如果需要允许为空,修改配置项required为false即可。

注解@CookieValue和注解@RequestHeader

从Cookie和HTTP请求头获取对应的请求信息

示例代码:

@RequestMapping("getHeaderAndCookie")
public String testHeaderAndCookie(@RequestHeader(value="User-Agent", required=false, defaultValue="attribute") String userAgent,
 @CookieValue(value="JSESSIONID", required=true, defaultValue="MyJsessionId") String jsessionId){
    
    
	System.out.println("User-Agent: " + userAgent);
	System.out.println("JSESSIONID: " + jsessionId);
	
	return "index";
}

defaultValue为默认值,当没有获取到数据时,该值取默认值。

4、拦截器

Spring要求处理器的拦截器都要实现接口HandlerInterceptor,这个接口定义了三个方法:

  1. preHandle:在处理器之前执行的前置方法。
  2. postHandle:在处理器之后执行的后置方法。
  3. afterCompletion:无论是否产生异常都会在渲染视图后执行的方法。
    当只想实现三个拦截器中的一到两个时,只要继承这个接口,根据需要覆盖掉原有的方法就可以了。

拦截器代码示例:

public class RoleInterceptor extends HandlerInterceptorAdapter{
    
    

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
    
    
		System.err.println("preHandle");
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception{
    
    
		System.err.println("postHandle");
	}
	
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception{
    
    
		System.err.println("afterCompletion");
	}
	
}

还需要进一步配置,拦截器才能为我们所用:

<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/role/*.do"/>
		<bean class="com.ssm.chapter15.interceptor.RoleInterceptor"/>
	</mvc:interceptor>
</mvc:interceptors>

用元素mvc:interceptors配置拦截器,在它里面可以配置多个拦截器。
其中class配置指定为开发的拦截器,path则是告诉Spring MVC该拦截器拦截什么请求,它使用了一个正则式的匹配。

5、验证表单

5.1、注解验证
Spring提供了对Bean的功能校验,通过注解 @Valid 标明哪个Bean需要启用注解式的验证。

注解 详细信息
@Null 被注释的元素必须为null
@NotNull 被注释的元素必须不为null
@AssertTrue 被注释的元素必须为true
@AssertFalse 被注释的元素必须为false
@Min(value) 被注释的元素必须为一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须为一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须为一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须为一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits(integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式

其中@DecimalMax(value)和@Max(value) 的区别在于@DecimalMax(value)可以通过把数字设为字符串来处理非常大的数字,比如@DecimalMax(“9999999999.999999999”),而@Max(value)则不行,它只能设置正常大小的数字@Max(9999)。

示例代码:

public class Transaction{
    
    
	
	@NotNull//不能为空
	private Long productId;

	@Future//只能是将来的日期
	@DateTimeFormat(pattern = "yyyy-MM-dd")//日期格式化转换
	@NotNull//不能为空
	private Date date;

	@Min(1)//最小值为1
	@Max(100)//最大值为100
	@NotNull//不能为空
	private Integer quantity;

	@NotNull//不能为空
	@DecimalMax("500000.00")//最大金额为5万元
	@DecimalMin("1.00")//最小交易金额1元
	private Double amount;

	//邮件
	@Pattern(//正则式
		regexp = "^([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@" + "([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$",
		//自定义消息提示
		message="不符合邮件格式")
	private String email;

	//Size(min = 0, max = 256)//0到255个字符
	private String note;
}

这样就定义了一个POJO,用以接收表单的信息,并且给每一个字段加入了对应的校验,它会生成默认的错误信息。

用控制器完成表单的校验:

@Controller
@RequestMapping("/validate")
public class ValidateController{
    
    
	
	@RequestMapping("/validate")
	public class ValidateController{
    
    
		
		@RequestMapping("/annotation")
		public ModelAndView annotationValidate(@Valid Transaction trans, Errors errors){
    
    
			//是否存在错误
			if(errors.hasErrors()){
    
    
				//获取错误信息
				List<FieldError>errorList = errors.getFieldErrors();
				for(FieldError error : errorList){
    
    
					//打印字段错误信息
					System.err.println("fied :" + error.getField() + "\t" + "msg:" + error.getDefaultMessage());
				}
			}
			ModelAndView mv = new ModelAndView();
			mv.setViewName("index");
			return mv;
		}
	}
}

使用 @Valid 标注,表明这个Bean将会被检验,而另一个类型为Errors的参数则是用于保存是否存在错误信息的,当采用JSR303规范进行校验后,它会将错误信息保存到这个参数中,进入方法后使用其hasErrors方法,便能够判断其验证是否出现错误。

5.2、使用验证器

6、文件上传

前端代码示例:

<form method="post" action="./file/upload.do" enctype="multipart/form-data">
	<input type="file" name="file" value="请选择上传的文件"/>
	<input type="submit" value="提交"/>
</form>

注意,要把enctype定义为"multipart/form-data",否则Spring MVC会解析失败,有了它就会提交到URL为./file/upload.do的请求上。

控制器代码示例:

@Controller
@RequestMapping("/file")
public class FileController{
    
    
	
	//使用MultipartFile
	@RequestMapping("/uploadMultipartFile")
	public R uploadMultipartFile(MultipartFile file){
    
    
		R request = new R();
		if(!file.isEmpty()) {
    
    
			String fileName = file.getOriginalFilename;
			file.transferTo(new File("F:\\workPicture\\" + fileName));
			request.success();
		}
		else {
    
    
			request.false();
		}
		return request;
	}
}

使用MultipartFile和Part其中之一就可以实现文件上传,它们的好处是把代码从Servlet API中解放出来,这体现了spring的思维,高度的解耦性,同时也简化了许多关于文件的操作。
springBoot默认的配置中,上传文件最大为1M,同时上传的文件数量最多为10个,如要修改默认配置可以在配置文件中添加:

#上传文件最大为10M
spring.servlet.multipart.max-file-size=10MB
#整个的上传文件最大为100MB
spring.servlet.multipart.max-request-size=100MB

猜你喜欢

转载自blog.csdn.net/lyc686/article/details/108751594