一、Spring MVC异常处理
在Spring MVC支持异常处理。不会呈现给用户500界面。而是当出现异常时交给某个特定的控制器。
●局部配置
配置在@Controller的控制器类中,只有当前这个控制器类的控制单元出现异常时才能执行,其他类的控制单元出现异常不能执行.每个控制器类中可以有多个处理异常的方法。每个方法上面只需要有@ExceptionHandler,千万别添加了@RequestMapping注解。
●全局配置
因为@ControllerAdvice已经继承了@Component注解,所以类上只添加这个注解就可以了。
不需要在添加@Controller注解了。
如果配置了局部异常处理器和全局异常处理器,优先匹配局部异常处理器。
●使用配置文件配置 java
在Spring MVC中包含HandlerExceptionResolver组件,专门负责处理异常的。接口中只包含一个resolveException方法
SimpleMappingExceptionResolver,里面有个全局属性exceptionMappings,表示当出现了什么类型异常时跳转到指定的页面。
想要在异常出现时跳转到指定页面,只需要在springmvc.xml文件中添加异常解析器即可。 (配置文件优先级低于注解的方式)
●根据状态码跳转到指定页面
在Spring MVC框架中没有提供根据状态码跳转到特定的视图。想要实现根据状态码跳转到指定页面可以使用Java EE中提供的实现方案。
需要注意的是,如果在Spring MVC中配置了异常解析器,对特定的异常类型跳转到指定的视图,代表着异常已经被解决了。对于Tomcat来说就不是500了。
●跨域问题
发送ajax请求的时候 如果协议/IP/端口号只要有一个和当前请求地址不相同这种情况下就会产生跨域
127.0.0.1 和localhost是两个域 进行ajax请求访问的时候依然会产生跨域
•为何浏览器阻止跨域呢?
处于浏览器的安全保护,不可以使用js代码进行跨域访问,因为这种访问非常不安全
注意:跨域是可以往控制单元中发送请求,但是不可以进行响应,所以跨域发生在响应位置
•跨域处理方案:
①jsonp:只可以处理get请求跨域,核心思想是把ajax跨域请求地址封装到一个类似script标签中借助于src
②@crossorigin:springmvc推出的允许跨域 目前阶段基本使用不到这个注解,因为ajax请求都是在同一个项目中进行的,但是在response.setHeader("Access-Control-Allow-Origin","*");
●异常处理
javasE:try..catch throw/throws
javaEE:在web.xml中进行配置
<error-page>
<error-code>404</error-code>
<location>/ex2.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type> <location<>/ax.jsp</location>
</error-page>
•SpringMVC:
局部:@ExceptionHandler
全局:注解:@ExceptionHandler+@ControllerAdvice
配置:创建对象SimpleMappingExceptionResolver
二、Spring MVC数据校验
数据校验分为客户端数据校验和服务端数据校验。常用在登录、注册功能中。
据校验是软件开发过程中必不可少的一个环节。一个项目只有客户端数据校验是不严谨的,为了防止不法人员直接通过URL或HTTP工具非法访问服务端,发送非法数据,保险起见,服务端也应该具有数据校验,这种客户端和服务端都有数据校验时,称为双重校验。
客户端数据校验直接使用客户端脚本校验即可。例如在B/S模型项目中,可以选择使用JavaScript或jQuery进行客户端数据校验。服务端数据校验根据使用的技术完成校验。如果是Servlet技术可以自己编写校验逻辑,所有的校验过程都是通过正则表达式、等值判断等进行校验。而在Spring MVC中数据校验包含两种:(1)基于注解方式(2)自定义校验类的方式
●基于注解方式
•JSR介绍
JCP(Java Community Process)是一个开发的国际组织,里面包含了一些Java开发者和其他被允许加入的成员。JCP组织主要负责对Java社区进行发展和更新。维护的规范包含:J2ME、J2SE、J2EE、XML等相关规范。组织成员可以提交SR(Java Specification RequestsJava规范提案),待组织成员通过提案后会把相关内容加入到下一个版本的规范中。
• JSR 303介绍
JSR每个提案都带有数字名称。例如JSR 107、JSR 303等。一定要注意的是,对于JSR提案并不是数字越大就需要包含前面内容。例如JSR107主要是对缓存的提案、JSR 303是对数据校验的提案,这两个提案不存在包含和被包含的关系,也不存在版本先后的关系。
JSR 303是Java EE6规范的子规范。叫做Bean Validation。这些规范都是注解。在Java开发中使用的最多的JSR 303具体实现就是Hibernate框架中Hibernate-Validator。它对JSR 303的所有约定(constraint)都做了实现,同时还进行了一定的扩充。
●Hibernate Validator包含的内容
Hibernate Validator对JSR实现都存在于Validation-api.jar的javax.validation.constraints包中。
里面所有注解都包含message属性,表示校验不通过后日志打印的信息。但是不建议设置,因为默认的提示信息就非常好。Hibernate Validator对SR 303具体实现的解释:
@AssertFalse 类型必须是布尔,取值必须为false
@AssertTrue 类型必须是布尔,取值必须为true
@DecimalMax("3") 最大值为3,value属性是String类型。
@DecimalMin("1") 最小值为1,value属性是String类型。
@Digits(integer =10,fraction = 3) integer:整数位最大长度,fraction小数位最大长度
@Email 必须是邮箱地址。只要中间包含@,且@前后都具有超过1位的字符就能通过校验。字符可以是数字字母下划线
@Future 类型必须是时间类型,允许为null,如果设置值必须是一个将来的时间
@FutureOrPresent 类型必须是时间类型,允许为null,如果设置值必须是一个一个将来或现在的时间(精确到秒)
@Max(5) 最大值为5,value属性是long类型
@Min(1) 最小值为1,value属性是long类型。
@Negative 必须是负数,对数据类型没有要求。
@NegativeOrZero 必须是负数或零,对数据类型没有要求。
@NotBlank 用在String类型。不能是空白(null和"")
@NotEmpty 用在String类型。不能是空白(null和"")
@NotNull 不能为null,可以是"”。可以用在所有类型中。对于八大基本数据类型来说,永远不为null。
@Null 必须为Null。可以用在所有类型中。对于八大基本数据类型来说,永远不可能为null。
@Past 类型必须是时间类型,必须是一个过去的时间。精确到秒。
@PastOrPresent 类型必须是时间类型,必须是一个过去的时间或现在的时间。精确到秒。
@Pattern(regexp="w(1,6)") 必须满足正则表达式。regexp是必有属性。
@Positive 必须是正数,对数据类型没有要求。
@PositiveOrZero 必须是正数或零,对数据类型没有要求。
@Size(min =1,max =10) 用在String类型。个数必须在1和10之间
●Hibernate-Validator额外补充,这些注解都在Hibernate-validator.jar的org.hibernate.validator.constraints包中。
@Length(min =1,max = 10) 用在String类型。长度需要在1和10之间
@Range(min =1,max =10) 数据类型没有要求。取值范围需要在1和10之间
@URL(port =8080,host="127.0.0.1",protocol = "https") 需要是一个合法的URL。默认情况下只要是以http:开头即可。可以通过port限制端口、host限制主机名、protocol限制协议。
●注解方式的具体实现
•添加依赖
除了项目正常的依赖以外,额外需要导入Hibernate-validator依赖。
注意:对于Tomcat8插件来说,最高支持到6.1.x版本,对于更高的6.2.x或7.x版本是不支持的。导入后启动会报异常。如果希望使用更高版本的依赖,可以使用更高版本Tomcat(本机Tomcat)
•对于Tomcat8正确的依赖导入示范:
如果导入过其他版本的Hibernate-Validator,一定要先停止Tomcat8插件,再clean一下。否则即使导入的是下面版本,也会报上面的异常。
●在实体类属性上添加注解
示例中只是以NotNull和Length进行举例。
•@NotNull中message是可选属性,如果设置了message,在违反规则后日志会打印message中内容
•@Length是设置字符串长度
所以name必须不能是null的,且长度是2-6位。
这些注解虽然可以放在方法、属性、其他注解、构造方法、参数上。
• 编写控制单元 java
控制单元中必须添加@Valid注解,否则校验不生效
●自定义校验类方式
•准备好一个实体类
还是使用People实体类接收参数。里面不需要添加校验的注解。
● 新建校验类
新建com.bjsxt.validator.MyValidator。类名和类所在的包都是随意定义的,没有强制要求。
● 配置校验类
在springmvc.xml中配置校验类,让校验类生效。
配置步骤:
•配置校验类的Bean
•在mvc:annotation-driven中validator属性引用校验类Bean的id
三、i18n(国际化)
i18n是internationalization(国际化)的缩写。因为单词比较长,取首字母和末字母n,中间还有18个字母,所以叫做i18n。国际化主要是让同一个项目,在不做任何修改的情况下,在不同语言环境中显示不同语言文字。
Spring MVC的国际化是通过LocaleResolver区域解析器来解析用户所在区域。根据区域判断使用哪种语言。
●四个实现类
• AcceptHeaderLocaleResolver:根据请求头判断时区
•SessionLocaleResolver:根据Session判断时区
• CookieLocaleResolver:根据Cookie判断时区
•FixedLocaleResolver:固定时区
这些实现类都能实现国际化效果,主要区别是实现方式不相同。因为AcceptHeaderLocaleResolver是默认的LocaleResolver,且适用面比较广。
●AcceptLanguageLocaleResolver实现国际化
AcceptLanguageLocaleResolver是根据请求头的Accept-Language进行判断使用哪种语言进行显示。并且在响应时也会设置Content-Language属性为当前语言。
●一定要分清楚,语言的顺序是控制请求头Accept-Language取值及值的顺序。勾选以这种语言显示Google Chrome是控制当前浏览器所使用的语言。
但是访问服务端时,请求头参数Accept-Language中中文(zh-CN)在前面,英语(en-US)在后面。对于服务端来说,如果中英文环境都支持,响应给客户端的还是中文内容。
●代码实现步骤
• 新建配置文件
在src/main/resources中新建属性文件。属性文件语法:任意名_语言_国家.properties。例如:中文是zh、英文是en。如果为了更加精确是哪国使用的这个语言,可以在后面添加国家,因为美式英语和英式英语是不一样的。中国:CN、美国是US,国家缩写都是大写的。
新建suiyi_zh_CN,properties
bjsxt.username=用户名
bjsxt.password=密码
bjsxt.submit=登录
新建suiyi_en_US.properties
bjsxt.username=username
bjsxt.password=password
bjsxt.submit=login
文件中key是自定义的,bjsxt.username这就是key,随意起。但是value要和语言对应。所以在suiyi_en_US.properties的bjsxt.username的value值是英文的,在suiyi_zh_CN.properties中的值是中文的。
同时要保证不同的properties文件的key是相同的。因为Spring MVC会根据语言环境自动获取不同文件中指定名称(key)对应的值。
•添加配置
在springmvc.xml中添加额外配置。因为属性文件名称是随意起的,所以需要明确告诉Spring MVC国际化资源文件名称。只需要写名称不需要写后面的语言和国家缩写。
AcceptHeaderLocaleResolver是默认的LocaleResolver可以不配置,id属性可以省略也可以换成其他名称。
ResourceBundleMessageSource的id属性不能省略,且必须叫做messageSource。换名或省略id都会导致properties无法被加载。
●新建控制单元 xml
新建控制单元方法。该方法负责显示页面。
想让国际化生效,必须保证执行了Spring MVC框架。具体效果:必须先走控制器,转发到页面。直接访问SP页面国际化无效。因为直接访问JSP文件是不通过Spring MVC的,而国际化是Spring MVC这里提供的功能。
●新建页面
在webapp目录下新建form.jsp.
需要注意:
•在上面使用taglib执行引入标签库
•<spring:message code="属性文件的key"></spring:message>根据语言环境负责加载属性文件中key的值。中文环境就加载suiyi_zh_CN.properties文件内容,英文环境就加载suiyi_en_US.properties文件内容