springmvc详解2

springmvc的配置文件的放置位置问题

  1. 第一种位置是和src平级的位置---config文件夹(source folder),此时需要在前端控制器配置中添加init-param标签实现加载springmvc配置文件,此时此配置文件最终保存到了classes文件夹中. 项目的部署地址我们可以从下图中找出:
  2. springmvc配置文件放到了WEB-INF文件夹中,此时文件的名称必须符合格式:前端控制器的<servlet-name>标签所定义的名称加中划线加servlet,例如:abc123-servlet.xml;此时前端控制器中init-param标签配置项就可以删除

重定向操作如何实现传参?

借助session,将request域对象中的键值对转存到session域对象中,如何转存:@SessionAttributes

  1. 第一种实现方式--可能存在弊端. 加入键值对只需要使用一次,那么在用完之后并没有从session域对象中消失,还一直占用空间,不合适;建议采用第二种方式. 当我们使用转发直接传递参数时会出现这样的错误:
    package com.offcn.controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.SessionAttributes;
    
    @Controller
    //将键值对放入session域对象中,value就是要放入的key名,由key找到对应的值
    @SessionAttributes(value = {"id"})
    public class RedirectController {
    
    	@RequestMapping("/redirect.action")
    	public String address1(int id,Model model) {
    		System.out.println("first:"+id);
    		//model和ModelAndView相当于request,都是向request作用域中添值
    		//model先把值存放到request作用域中,然后@sessionAttributes注解
    		//再把request作用域中的值存放到session中,往下传递
    		model.addAttribute("id", id);//存放进request作用域中
    		return "redirect:second.action";
    	}
    	
    	@RequestMapping("/second.action")
    	public String second(HttpServletRequest request) {
    		//二次请求时从session中获取键值对
    		HttpSession session = request.getSession();
    		Object id = session.getAttribute("id");
    		System.out.println("second:"+id);
    		session.setAttribute("att", id);//往页面传参
    		return "/main2.jsp";
    	}
    }
    

    注解@sessionAttributes的value的值时一个字符串数组,值是多个字符串,每个字符串表示一个key名称

  2. 此方式仅仅只能传递一次参数,同样也时借助session域对象

    package com.offcn.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;
    
    @Controller
    public class RedirectSecondController {
    
    	@RequestMapping("/redirectSecond.action")
    	public String second(int id,RedirectAttributes ra) {
    		System.out.println("first:"+id);
    		//RedirectAttributes同样实现将键值对保存到session域对象中,但是只在session对象中保存一次
    		//id值二次请求的时候拼接到url上了,想要获取id值可以用EL表达式
    		ra.addAttribute("id", id);
    		//如果不想二次请求中的url中出现id值可以使用此方法
    //		ra.addFlashAttribute("id",id);
    		return "redirect:/secondcon.action";
    	}
    	
    	@RequestMapping("/secondcon.action")
    	public String secondRedirect1(@ModelAttribute("id")int id) {
    		System.out.println("second"+id);
    		return "/main2.jsp";
    	}
    }

           

url的说明

在前端的页面中设置超链接或者js或者css等,都会涉及到url,所以url的设计有三种格式:在资源名称前面有/无/../;例如:/abc.actionabc.action../abc.action

三种格式分别要补齐完整的url路径,

第一种补齐时补到8080/,即端口位置

例如:<a href="/bcd.action">提交</a>

补齐后的绝对路径为: http://localhost:8080/bcd.action -->

第二种补齐时要看当前浏览器中地址栏url的情况,即当前页面的地址信息,有可能当前页面地址信息中会含有名称空间

<a href="abc.action">提交</a>

  1. 超链接没有/,表示相对路径,前面补齐的是当前浏览器地址里url去掉名称剩下的部分假如:当前页面的urlhttp://localhost:8080/day07-springmvc-url/index.jsp,那么就把index.jsp去掉, 之后剩下的就是http://localhost:8080/day07-springmvc-url/abc.action
  2. 假如:当前的urlhttp://localhost:8080/day07-springmvc-url/file/index.jsp,该中名称是带名称空间(file)的,那么把index.jsp去掉剩下http://localhost:8080/day07-springmvc-url/file/abc.action

第三种补齐时要看浏览器地址栏的url,只不过要根据url进行向前找路径情况

<a href="../cde.action">提交</a>

  1. ../是相对路径, 表示从当前url的资源名称部分向前找两级目录,找到的第二级目录的url,给其补齐. 假如:当前的urlhttp://localhost:8080/day07-springmvc-url/index.jsp,那么找两级之后8080/位置  http://localhost:8080/cde.action
  2. 假如:当前的urlhttp://localhost:8080/day07-springmvc-url/file/index.jsp,那么找两级之后是day07-springmvc-url/位置, 补全后为http://localhost:8080/day07-springmvc-url/cde.action 

四. 后台在设置url的时候,一般采用绝对路径,后台的绝对路径是包含项目名的

在后台/表示到项目名的位置的url,例如http://localhost:8080/day07-springmvc-url/ 

 @RequestMapping("/abc.action")此时带有/所以补齐的url中带有项目名, 完整格式是http://localhost:8080/day07-springmvc-url/ abc.action

请求方式的转换

1.在页面发出请求的时候,只见过get和post两种请求方式:

  1. 超链接、js文件加载<script src=”js/jquery.js”>、css文件加载<link href=”css/main.css”>都是发出get请求;
  2. 表单通过method属性设置get或者post请求
  3. 异步操作:type属性设置get或者post请求

2.请求方式:get、post、delete、put、head、trace、options

http协议只实现了get和post,所以页面只有两种请求方式被实现了:get和post;

那么其他的请求方式没有被实现,可以通过一种手段模拟其他请求方式,比如delete、put、head等等

3.如何实现模拟

  1. 必须是post请求才能模拟转换---原始请求是post
  2. 固定参数对请求的时候的数据key=value, 即  _method=delete/put/...

  3. 在后端控制器中@RequestMapping注解中添加对应的方式(属性=值)

  4. 需要配置一个过滤器---请求转换的过滤器                        请求方式和处理方式不匹配时会报405异常处理方式是加一个请求转换过滤器

    package com.offcn.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    public class PutController {
    	//传参方式的模拟,需要在requesmapping中使用requestmethod属性
    	//当有多个属性的时候,requestmapping中的value不能省略
    	@RequestMapping(value="/put.action",method = RequestMethod.PUT)
    	public String put(int id) {
    		System.out.println(id);
    		//在转发此main页面时是我们转化后的put请求,但是此时页面的响应使用的是
    		//Servlet中的doget请求方式,因为jsp本身就是一个简化的servlet,所以请求方式
    		//和处理请求的方式不匹配--405异常
    		return "redirect:/show.action";
    	}
    	
    	@RequestMapping("/show.action")//自适应请求方式,如果指定了method就是指定请求方式
    	public String show() {
    		return "/WEB-INF/main.jsp";
    	}
    }

    5.一般情况下可能会根据不同的CRUD操作,来对应不同的请求方式;即如果是查询操作--使用get请求、如果是保存操作--使用post请求、如果是修改操作--使用put请求、如果是删除操作--使用delete请求

数据校验

1.什么是数据校验?--- 是指用来校验数据是否合法---合乎规定

2.数据校验包括页面校验、后台校验;页面校验一般不安全,很容易出现校验被绕行;在对于数据安全要求较高的情况下要采用后台校验

3.在web项目中,规定了一种数据校验模式,称为JSR303校验方式,这种方式参考了Hibernate的数据校验方式,在springmvc中提供了实现JSR303校验的方式,主要在springmvc的框架中整合校验框架

实现步骤

  1. 需要的jar包---hibernate-validator包,jboss-logging包,validation-api包,classmate包
  2. 在springmvc的配置文件中添加校验器, 需要先添加工厂bean,在工厂中配置校验器,然后再引入配置文件对象,用来实现软编码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:mvc="http://www.springframework.org/schema/mvc"
        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.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
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    	<!-- 扫描包 -->
    	<context:component-scan base-package="com.offcn"></context:component-scan>
    	
    	<!-- 注解方式的适配器和注解方式的映射器 -->
    	<!-- mvc:annotation代替注解的适配器和映射器 -->
    	<mvc:annotation-driven validator="validatorFactory"></mvc:annotation-driven>
    	
    	
    	<!-- 视图解析器 -->
    	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	</bean>
    	
    	
    	<!-- 校验器的配置:先工厂,再校验器,这个是工厂 -->
    	<bean id="validatorFactory" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    		<!-- 通过属性添加,这个是校验器 -->
    		<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
    		<!-- 将配置文件加载对象注入到工厂中来 -->
    		<property name="validationMessageSource" ref="messageSource"></property>
    	</bean>
    	
    	
    	<!-- 读取配置文件 -->
    	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    		<property name="basenames">
    			<list>
    				<!-- 省略文件的扩展名,属性文件在这里引入 -->
    				<value>classpath:ValidationMessage</value>
    			</list>
    		</property>
    	</bean>
    </beans>

     

  3. 要在实体类的属性上面添加对应的注解, 了解有哪些校验注解?
  4. 处理请求的执行单元形参位置要添加注解@Validated Person person,BindingResult bindingResult,  @Validated注解和BindingResult属性成对出现. 如果我们没有自定义错误输出信息,框架也会有默认的错误信息输出注意message的值是通过{ }引入的,类似于EL表达式,但是没有$符号
  5. 最后校验结果送回到页面视图

  • 创建配置文件比如:ValidationMessage.properites
  • 将结果信息抽取到此配置文件中,使用键值对保存,然后再将key引用回到实体类的属性中去引入的时候格式是value="{key}"

校验注解有

非空校验

  1. @NotNull----此注解通常用于给基本类型对应的包装类做非空校验
  2. @NotBlank----此注解用于给String类型做非空校验
  3. @NotEmpty----此注解用于对集合属性做非空校验

闭合区间校验

  1. @Size---对字符串、集合做区间校验,即最大和最小
  2. @Length---对字符串做区间校验,最长和最短
  3. @Range---对字符串、基本类型的包装类做区间校验,即最大值和最小值

其他

  1. @Email--邮箱格式校验
  2. @Pattern---自定义正则表达式实现校验

当客户进行数据添加之后,点击提交,在后台实现了数据校验,如果存在校验信息,说明客户所填写内容有不合理的,所以给客户响应页面的时候肯定原界面实体类,各种非空判断在这里进行

package com.offcn.bean;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;

public class Person implements Serializable{

	private static final long serialVersionUID = -1706595280202149906L;
	//id实现非空校验---id必须有值,不能为null
	//自定义校验提示---硬编码---软编码(将校验提示信息保存到配置文件)
	@NotNull(message = "{person_pid_isnotnull}")
	private Integer pid;
	
	@NotBlank(message = "{person_pname_isnotnull}")
	@Length(max = 16,min = 6)
	private String pname;
	
	private String pdate;
	
	@NotBlank(message = "邮箱不能为空")
	@Email(message = "{person_email}")
	private String email;
	
	private Double pweight;
	
	//自定义正则表达式实现手机号码校验
	@Pattern(regexp = "^1[3-9][0-9]{9}$",message = "手机号码格式不正确")
	private String phone;
	
	public Integer getPid() {
		return pid;
	}
	public void setPid(Integer pid) {
		this.pid = pid;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public String getPdate() {
		return pdate;
	}
	public void setPdate(String pdate) {
		this.pdate = pdate;
	}
	public Double getPweight() {
		return pweight;
	}
	public void setPweight(Double pweight) {
		this.pweight = pweight;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	
}

index页面,页面回显数据

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%-- <%
String url = request.getSession().getServletContext();
%> --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 将校验信息展示 -->
<!-- 判断键值对是否存在,存在才展示 -->
<c:if test="${errors != null }">
	<c:forEach items="${errors }" var="er">
		${er.defaultMessage }<br>
	</c:forEach>
</c:if>
<form action="person1.action">
	<input type="text" name="pid">
	<input type="text" name="pname">
	<input type="text" name="email">
	<input type="text" name="phone">
	<input type="submit" value="提交">
</form>
</body>
</html>

springmvc配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
    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.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
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 扫描包 -->
	<context:component-scan base-package="com.offcn"></context:component-scan>
	
	<!-- 注解方式的适配器和注解方式的映射器 -->
	<!-- mvc:annotation代替注解的适配器和映射器 -->
	<mvc:annotation-driven validator="validatorFactory"></mvc:annotation-driven>
	
	
	<!-- 视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	</bean>
	
	
	<!-- 校验器的配置:先工厂,再校验器,这个是工厂 -->
	<bean id="validatorFactory" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
		<!-- 通过属性添加,这个是校验器 -->
		<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
		<!-- 将属性配置文件加载对象注入到工厂中来 -->
		<property name="validationMessageSource" ref="messageSource"></property>
	</bean>
	
	
	<!-- 读取配置文件 -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basenames">
			<list>
				<!-- 省略文件的扩展名,属性文件在这里引入 -->
				<value>classpath:ValidationMessage</value>
			</list>
		</property>
	</bean>
</beans>

控制层

package com.offcn.controller;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import com.offcn.bean.Person;

@Controller
public class PersonController {

	@RequestMapping("/person1.action")
	//@Validated注解和BindingResult属性成对出现
	public String person1(Model model,@Validated Person person,BindingResult bindingResult) {
		//获取校验结果
		List<ObjectError> allErrors = bindingResult.getAllErrors();
		for(ObjectError oe : allErrors) {
			System.out.println(oe.getDefaultMessage());
		}
		
		//需要判断---有校验信息,回原界面;没有校验信息才到正常页面
		if(bindingResult.hasErrors()) {
			model.addAttribute("errors", bindingResult.getAllErrors());
			return "/index.jsp";
		}
		return "/WEB-INF/main.jsp";
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值