文章目录
- SpringMVC
- 一.环境准备
- 二.正式进入SpringMVC的世界
- 1.SpringMVC下的第一个helloWorld工程
- 2.SpringMVC中最强大的注解:@RequestMapping
- 3.SpringMVC中@PathVariable注解的使用
- 4.SpringMVC中Rest风格的URL地址
- 5.SpringMVC中获取请求参数
- 6.SpringMVC中发送响应参数(Map、Model和ModelMap这三者的关系图)
- 7.SpringMVC中视图解析
- 8.SpringMVC中数据校验
- 9.mvc:annotation-driven标签的解析
- 9.SpringMVC中数据格式化
- 10.SpringMVC中数据国际化
- 11.SpringMVC中文件上传
- 12.SpringMVC拦截器
- 13.SpringMVC国际化
- 13.SpringMVC异常处理
- 三.SpringMVC下WEB的三大组件的各种配置
- 四.SpringMVC中AJAX与JSON
- 五.SpringMVC执行流程
SpringMVC
一.环境准备
1.建立maven下的web工程
如果出现Cannot resolve plugin org.apache.maven.xxxxx等类似在pom.xml中出现的错误,请到本地仓库下删除相应jar包的文件夹,然后点击刷新
2.在pom.xml加入相关jar包依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.3</version>
</dependency>
3.创建web工程完成目录
- 在main目录下创建java与resources
注意:如果这里的java不是蓝色的,需要自己去目录结构里面设置
4.在web.xml中配置DispatcherServlet类
- 说明:这个类DispatcherServlet就是区别与普通MVC的最大特征,这是一个前置的控制器,会比servlet更早的拦截下请求,然后进行分发处理提高效率。
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--一定要配置初始化,来让springMVC.xml扫描全局注解-->
<!-- 配置DispatcherServlet的初始化參數:设置文件的路径和文件名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--/*和/都是拦截所有请求,/*比/的范围更大-->
<url-pattern>/</url-pattern>
</servlet-mapping>
5.在resources目录下创建springMVC的xml文件
- 切记一定要配置扫描全部包注解的标签
6.配置tomcat服务器
二.正式进入SpringMVC的世界
1.SpringMVC下的第一个helloWorld工程
- Java类的书写
/**
* 告诉springMVC这是一个处理器,可以处理请求
* @Controller,表示那个组件是控制器
*/
@Controller
public class MyFirstController {
/**
* /代表从当前目录下开始,"/hello"就是处理当前目录下的请求
*/
@RequestMapping(value = "/hell?")
public String myFirstRequest(){
System.out.println("请求收到了!");
/*success为跳转成功的页面,写成这样的省略模式需要在springMVC下进行相应配置 */
return "success";
}
}
- index.jsp的书写
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>
<a href="hello">helloWorld</a>
</body>
</html>
- 配置springMVC的xml文件在标签下
<!--开启注解扫描-->
<context:component-scan base-package="com.lhjitem"></context:component-scan>
<!--配置映射(视图)解析器:如何将控制器返回的结果字符串,转换为一个物理的视图文件-->
<bean id="irvr" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--prefix(前缀)是代表跳转页面文件的所在目录-->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!--suffix(后缀)表示文件的后缀名-->
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置springmvc框架注解的支持-->
<mvc:annotation-driven></mvc:annotation-driven>
2.SpringMVC中最强大的注解:@RequestMapping
2.1RequestMapping的属性
- value及path(默认):
作用:
-
就是告诉SpringMVC;这个方法用来处理什么请求;
-
这个/是可以省略,即使省略了,也是默认从当前项目下开始;
-
习惯加上比较好 /hello /hello
-
还可以进行模糊查询 :URL地址可以写模糊的通配符:?:能替代任意一个字符(0个多个都不行;)、*:能替代任意多个字符,和一层路径、**:能替代多层路径
-
模糊和精确多个匹配情况下,精确优先
- method:限定请求方式
据我们所知HTTP协议中请求方式有:
-
作用:【GET】, HEAD, 【POST】, PUT, PATCH, DELETE, OPTIONS, TRACE
-
method=RequestMethod.POST:只接受这种类型的请求,默认是什么都可以;
-
不是规定的方式报错:4xx:都是客户端错误
-
405 - Request method 'GET' not supported
- params:规定请求参数
param1: 表示请求必须包含名为 param1 的请求参数
-
eg:params={"username"}:
-
发送请求的时候必须带上一个名为username的参数;没带都会404
!param1: 表示请求不能包含名为 param1 的请求参数
-
eg:params={"!username"}
-
发送请求的时候必须不携带上一个名为username的参数;带了都会404
param1 != value1: 表示请求包含名为 param1 的请求参数,但其值不能为 value1
-
eg:params={"username!=123"}
-
发送请求的时候;携带的username值必须不是123(不带username或者username不是123)
{“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
-
eg:params={"username!=123","pwd","!age"}
-
请求参数必须满足以上规则;
-
请求的username不能是123,必须有pwd的值,不能有age
- headers:规定请求头;也和params一样能写简单的表达式
/**
* User-Agent:浏览器信息;
* 让火狐能访问,让谷歌不能访问
*
* 谷歌:
* User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
* 火狐;
* User-Agent Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
* @return
*
*/
@RequestMapping(value="/handle04",headers={"User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"})
public String handle04(){
System.out.println("handle04....");
return "success";
}
- consumes:只接受内容类型是哪种的请求,规定请求头中的Content-Type
- produces:告诉浏览器返回的内容类型是什么,给响应头中加上Content-Type:text/html;charset=utf-8
3.SpringMVC中@PathVariable注解的使用
3.1说明
用来接收占位符的值,以达到显示不同的种类
3.2获取不同图书实例,结合Rest理解
@Controller
public class BookController {
/**
* 处理查询图书请求
* @param id
* @return
*/
@RequestMapping(value="/book/{bid}",method=RequestMethod.GET)
public String getBook(@PathVariable("bid")Integer id) {
System.out.println("查询到了"+id+"号图书");
return "success";
}
4.SpringMVC中Rest风格的URL地址
4.1说明
系统希望以非常简洁的URL地址来发请求;
4.2怎样表示对一个资源的增删改查用请求方式来区分
-
传递的URL类似于这样:
/getBook?id=1 :查询图书
/deleteBook?id=1:删除1号图书
/updateBook?id=1:更新1号图书
/addBook :添加图书 -
Rest推荐;
url地址这么起名; /资源名/资源标识符
/book/1 :GET-----查询1号图书
/book/1 :PUT------更新1号图书
/book/1 :DELETE-----删除1号图书
/book :POST-----添加图书
系统的URL地址就这么来设计即可;
简洁的URL提交请求,以请求方式区分对资源操作; -
问题:
从页面上只能发起两种请求,GET、POST;
其他的请求方式没法使用;
5.SpringMVC中获取请求参数
5.1最简单的获取方法
直接给方法入参上写一个和请求参数名相同的变量。这个变量就来接收请求参数的值;
* 带:有值,没带:null;
@Controller
public class Request {
@RequestMapping("/hello")
public String test01(String username){
System.out.println("这个变量的值:" + username);
return "success";
}
}
5.2请求参数的注解
- @RequestParam:获取请求参数的;参数默认是必须带的;
= request.getParameter(“user”) - @RequestHeader:获取请求头中某个key的值;
= request.getHeader(“User-Agent”); - @CookieValue:获取某个cookie的值;
这三个注解都有三个属性
- value():指定要获取的参数的key
- required():这个参数是否必须的
- defaultValue():默认值。没带默认是null;
@RequestMapping("/hello")
public String test02(@RequestParam(value = "username",required = false,defaultValue = "这是默认值") String username,
@RequestHeader(value = "User-Agent",required = false,defaultValue = "这是默认值") String userAgent,
@CookieValue(value = "JSESSIONID",required = false)String jid){
System.out.println("这个变量的值:" + username);
System.out.println("请求头中浏览器的信息:" + userAgent);
System.out.println("cookie中的jid的值"+jid);
return "success";
}
5.3请求参数为一个pojo对象
SpringMVC会自动的为这个POJO进行赋值
- 将POJO中的每一个属性,从request参数中尝试获取出来,并封装即可;
- 还可以级联封装;属性的属性
- 请求参数的参数名和对象中的属性名一一对应就行
@RequestMapping("/person")
public String test03(Person person){
System.out.println("这个人是:" + person);
return "success";
}
<form action="person" method="post">
id:<input type="text" name="id"/><br>
姓名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age"/><br>
性别:<input type="text" name="sex"/><br>
民族:<input type="text" name="national"/><br>
<input type="submit" value="提交">
</form>
运行结果:
6.SpringMVC中发送响应参数(Map、Model和ModelMap这三者的关系图)
6.1获取方式
-
可以在方法处传入Map、或者Mode(接口)或者ModelMap。给这些参数里面保存的所有数据都会放在请求域(request)中。Map、或者Mode(接口)或者ModelMap这三者的关系图如下:
-
方法的返回值可以变为ModelAndView类型,既包含视图信息(页面地址)也包含模型数据(给页面带的数据;而且数据是放在请求域中;
request、session、application; -
SpringMVC提供了一种可以临时给Session域中保存数据的方式;
使用一个注解 @SessionAttributes(只能标在类上) -
ModelAttribute注解;
6.2简单获取Map、Model、ModelMap中的value
@RequestMapping("/hello1")
public String test01(Map<String ,String> map){
map.put("key1","value1");
return "success";
}
@RequestMapping("/hello2")
public String test02(Model model){
model.addAttribute("key1","value1");
return "success";
}
@RequestMapping("/hello3")
public String test03(ModelMap map){
map.addAttribute("key1","value1");
return "success";
}
pageContext:${pageScope.key1}<br>
request:${requestScope.key1}<br>
session:${sessionScope.key1}<br>
application:${applicationScope.key1}<br>
页面显示结果(都放在了request域中):
6.3方法的返回值可以变为ModelAndView类型
6.3.1使用说明
既包含视图信息(页面地址)也包含模型数据(给页面带的数据);
-
而且数据是放在请求域中;
-
request、session、application;
6.3.2具体应用
/**
* 返回值是ModelAndView;可以为页面携带数据
* @return
*/
@RequestMapping("/hello4")
public ModelAndView test04(){
//之前的返回值我们就叫视图名;视图名视图解析器是会帮我们最终拼串得到页面的真实地址;
//ModelAndView mv = new ModelAndView("success");
ModelAndView mv = new ModelAndView();
mv.setViewName("success");
mv.addObject("key1", "你好哦!");
return mv;
}
6.3.3运行结果
6.4SpringMVC提供了一种可以临时给Session域中保存数据的方式
6.4.1使用说明
使用一个注解 @SessionAttributes(只能标在类上)
推荐@SessionAttributes就别用了,可能会引发异常;
如果不想引发异常(在隐含模型中找不到对象信息,就会自动去session域中找,而session此时可能也没有
所以这个异常也就出现了)。
我们需要注意两点:
- 隐含模型中有@SessionAttributes标注的属性
- 如果隐含模型中找不到,那么一定要保证session域中要有
给session中放数据请使用原生API;
6.5ModelAttribute注解;
6.5.1使用说明
当我们进行全字段的数据库更新操作时,例如更新书籍的操作,据我们所知,在更新书籍时是不可能让我们修改书名和作者的。
但由于是全字段操作,SpringMVC会帮助我们创建一个新的JavaBean对象,然后将全字段的信息传入进去,但由于书名和作者我们无法修改,所以我们不会设置这两项的值。
但此时这个新对象,由于我们未传入数据,所以这两项的值为null。然后会覆盖掉数据库里面的信息,这是我们不希望看到的。
这个ModelAttribute的注解的作用是不让SpringMVC使用自己创建的新对象,而是直接使用数据库中的那个已经封装好的对象来供我们修改,这样就不会对关键数据造成影响
这只是ModelAttribute的其中之一的用处
6.5.2具体用法
- ModelAttribute:
-
参数:取出刚才保存的数据
-
方法位置:这个方法就会提前于目标方法先运行;
-
1)我们可以在这里提前查出数据库中图书的信息
-
2)将这个图书信息保存起来(方便下一个方法还能使用)
-
- 通过map储存到的人信息,取出来然后对个别信息进行修改。在提交,这样就不会把源数据的关键信息覆盖掉
/**
* 可以告诉SpringMVC不要new这个book了我刚才保存了一个book;
* 哪个就是从数据库中查询出来的;用我这个book?
*
*
* 同都是BindingAwareModelMap
* @param book
* @return
*/
@RequestMapping("/updateBook")
public String updateBook(@RequestParam(value="author")String author,
@ModelAttribute("haha")Book book
){
Object haha = model.get("haha");
//System.out.println("传入的model:"+model.getClass());
System.out.println("页面要提交过来的图书信息:"+book);
return "success";
}
- 使用一个方法把一个map保存到底层BlindingAwareModelMap中去(代替从数据库取pojo对象的过程),然后全局的ModelAttribute都能使用,这个过程称为在隐含模型中取对象信息
* 这个传入map的用法是ModelAttribute最常用的用法
* @ModelAttribute:
* 参数:取出刚才保存的数据
* 方法位置:这个方法就会提前于目标方法先运行;
* 1)我们可以在这里提前查出数据库中人的信息
* 2)将这个人信息保存起来(方便下一个方法还能使用)
*
* 参数的map:BindingAwareModelMap
*/
@ModelAttribute
public void hahaMyModelAttribute(Map<String, Object> map){
Person person = new Person(1,"XXX",20,"男","汉族");
System.out.println("数据库中查到的人是:"+person);
map.put("haha", book);
System.out.println("modelAttribute方法...查询了图书并给你保存起来了...他用的map的类型:"+map.getClass());
}
7.SpringMVC中视图解析
7.1说明
视图相关的执行途径都是接口,提供超高定制化的view处理,自己根据里面的抽象方法可定制来完成自己的需求
一句话:
视图解析器(ViewResolver)只是为了得到视图对象;视图对象才能真正的转发(将模型数据全部放在请求域中)或者重定向到页面
视图对象才能真正的渲染视图;
7.2视图解析流程
7.3视图国际化
7.3.1说明
当你导入jstl或者在springMVC.xml中配置了国际化,当解析视图时会自动创建一个jstlView对象,这是InternalResourceViewResolver
的子类
7.4问题
访问工程目录下的首页处理信息(CRUD),这是我们可以添加一个标签,让其经过spring的封装
<jsp:forward page=“所要处理的请求名”/>,然后直接转发到我们请求方法里面的那个jsp页面
8.SpringMVC中数据校验
8.1说明
数据校验:我们提交的数据必须是合法的
前端校验:js+正则表达式;
后端校验:由于浏览器可以禁用js,所以对于关键数据只进行前端校验是不行的,我们必须前端+后端
8.2数据校验流程图
8.3数据校验注解
8.3.1 JSR 303
这是一个提供校验的的规范,具体实现的其规范的是一个第三方的框架,名为:Hibernate Validator
8.3.2 Hibernate Validator
- 加入jar包
- 注解使用
对封装对象校验的实例(原生标签显示错误信息的写法也在里面):
@RequestMapping(value = "/emp", method = RequestMethod.POST)
public String addEmp(@Valid Employee employee, BindingResult result,
Model model) {
System.out.println("要添加的员工:" + employee);
// 获取是否有校验错误
boolean hasErrors = result.hasErrors();
Map<String, Object> errorsMap = new HashMap<String, Object>();
if (hasErrors) {
List<FieldError> errors = result.getFieldErrors();
for (FieldError fieldError : errors) {
System.out.println("错误消息提示:" + fieldError.getDefaultMessage());
System.out.println("错误的字段是?" + fieldError.getField());
System.out.println(fieldError);
System.out.println("------------------------");
errorsMap.put(fieldError.getField(),
fieldError.getDefaultMessage());
}
model.addAttribute("errorInfo", errorsMap);
System.out.println("有校验错误");
return "add";
} else {
employeeDao.save(employee);
// 返回列表页面;重定向到查询所有员工的请求
return "redirect:/emps";
}
}
在jsp页面做相应配置就可让用户看到自己那个地方有错误
<!--原生标签用的原理是,将错误信息保存到map中,然后通过用一个隐含模型中调用错误信息-->
lastName:<form:input path="lastName"/>
<form:errors path="lastName"/>-->${errorInfo.lastName }
<!--springMVC标签--> <!--原生表单标签-->
<br/>
email:<form:input path="email"/>
<form:errors path="email"/>-->${errorInfo.email }
<br/>
这个框架所支持的注解十分多切强大,建议阅读这个博客了解
9.mvc:annotation-driven标签的解析
9.1请求有问题时
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
当初出现问题时会依次配置这两个标签
-
两个如果能没配,动态资源(@RequestMapping映射的资源)能访问,静态资源(.html,.js,.img)不能访问。
原因:handlerMap中的DefaultAnnotationHandlerMapping没有保存静态资源映射的请求,
-
加上<'mvc:default-servlet-handler/>,不加<'mvc:annotation-driven/> ,静态资源加载出来,动态资源又加载不出来了。
原因:DefaultAnnotationHandlerMapping被替代,SimpleUrlHandlerMapping把所有请求都映射给tomcat;
-
加上<'mvc:default-servlet-handler/>,和加上<'mvc:annotation-driven/>;两者皆能访问。
原因:有SimpleUrlHandlerMapping静态资源没问题,handlerMappings中多出了一个RequestMappingHandlerMapping,所以动态资源可以访问
9.SpringMVC中数据格式化
9.1日期格式化
9.1.1注解
- @DateTimeFormat()
9.1.2注解属性
- pattern:规定日期显示的格式,例如:yyyy-MM-dd
9.1.3注意
一旦使用注解配置好后格式,以后的日期格式都要遵从这个
9.2数据格式化
9.2.1注解
- @NumberFormat()
9.2.2注解属性
- pattern:规定数据的格式,例如:##,###,###.##
9.2.3注意
实例:传入工资20000.98–>经过格式化20,000.98
一旦使用注解配置好后格式,以后的数据格式都要遵从这个
10.SpringMVC中数据国际化
10.1说明
书接8中的数据校验问题,如果出现错误提示用户那个地方出现问题的信息,对这个信息可以进行国际化显示
但如果没有国际化需求,在每个Hibernate Validator注解中都有一个message属性来直接显示错误信息
10.2步骤
-
创建两个properties文件专门存放错误信息的国际化配置(配置时还可以对相对应的注解属性信息进行显示)
-
然后根据那个字段错误进行配置(如果对同一字段的四种类型都做了配置,那么会精确优先)
字段错误的分类:
由上及下逐渐模糊 -
在springMVC中交给spring控制
<!-- 管理国际化资源文件,同理id必须是messageSource,理由是隐含模型代码中调用错误文件时的对象名就是这个 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="errors"></property>
</bean>
11.SpringMVC中文件上传
11.1配置
- 下载上传所需的jar包
2. 在springMVC.xml中配置九大组件的下载组件
11.2具体实现
单文件上传
@Controller
public class UploadFile {
@RequestMapping("/uploadFile")
public String test01(@RequestParam(value = "username",required = false)
String username,
@RequestParam("lalala") MultipartFile file,
Model model) throws IOException {
System.out.println("文件的名字"+file.getOriginalFilename());
System.out.println("文件的大小"+file.getSize());
//文件保存
try {
file.transferTo(new File("D:\\JAVA_Files\\"+file.getOriginalFilename()));
model.addAttribute("msg","文件上传成功!");
} catch (Exception e) {
model.addAttribute("msg","文件上传失败!"+e.getMessage());
}
return "forward:/index.jsp";
}
}
多文件上传
@Controller
public class UploadFiles {
/*多文件上传*/
@RequestMapping("/uploadFiles")
public String test01(@RequestParam(value = "username",required = false) String username,
@RequestParam("lalala") MultipartFile[] files,
Model model){
for (MultipartFile file : files) {
if(!file.isEmpty()){
try {
file.transferTo(new File("D:\\JAVA_Files\\"+file.getOriginalFilename()));
model.addAttribute("msg","文件上传成功!");
} catch (Exception e) {
model.addAttribute("msg","文件上传失败!"+e.getMessage());
}
}
}
return "forward:/index.jsp";
}
}
12.SpringMVC拦截器
12.1说明
SpringMVC提供了拦截器机制;允许运行目标方法之前进行一些拦截工作,或者目标方法运行之后进行一些其他处理;
Filter:javaWeb(适用范围大)
HandlerInterceptor:SpringMVC(适用范围小)
什么时候用Filter:
简单需求就用Filter
什么时候用HandlerInterceptor:
如果某些功能需要用到其他组件来完成,较难时就用拦截器
HandlerInterceptor接口的三个重写方法:
- preHandle:在目标方法运行之前调用;返回boolean;return true;(chain.doFilter())放行; return false;不放行
- postHandle:在目标方法运行之后调用:目标方法调用之后
- afterCompletion:在请求整个完成之后;来到目标页面之后;chain.doFilter()放行;资源响应之后;
12.2单拦截器流程
正常执行流程
拦截器的preHandle–>目标方法–>拦截器postHandle–>页面–>拦截器的afterCompletion;
异常执行流程
preHandle只要不放行,其他都不执行
12.3多拦截器流程
正常执行流程
异常流程
前提:一号放行,二号有异常
已经放行了的拦截器的afterCompletion总会执行;
13.SpringMVC国际化
13.1说明
在springMVC中大概有三种配置切换国际化的方法:
- 自定义区域信息解析器 (LocaleResolver)
- 使用SessionLocaleResolver实现点击切换:区域信息是从session中获取。
- SessionLocaleResolver配合Locale使用
13.2不同方法前都要的步骤
- 先写不同语言的properties文件
- 依旧在springMVC.xml中配置
<!-- 管理国际化资源文件,同理id必须是messageSource,理由是隐含模型代码中调用错误文件时的对象名就是这个 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<!--value值就是你配置文件的前缀名-->
<property name="basename" value="i18n"></property>
</bean>
13.3自定义区域信息解析器 (LocaleResolver)
- 继承LocaleResolver接口重写两个方法:resolveLocale(解析返回locale)、setLocale(修改locale)
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
Locale l = null;
//根据页面带的参数值来设置区域信息
String locale = httpServletRequest.getParameter("locale");
if(!locale.equals("") && locale!=null){
//发过来的参数一般都是 zh_CN,前面是语言,后面是地区
l =new Locale(locale.split("_")[0], locale.split("_")[1]);
}else {
//如果没带位置区域信息,我们就默认一个,就用浏览器带的请求头中的,即浏览器默认的
l = httpServletRequest.getLocale();
}
return l;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
throw new UnsupportedOperationException(
"Cannot change HTTP accept header - use a different locale resolution strategy");
}
}
- 在springMVC.xml中配置自定义区域信息解析器
<!--配置自定义区域解析器-->
<bean id="localeResolver" class="com.lhjitem.international.MyFirstLocaleResolver"></bean>
13.5显示结果
13.4出现的问题
- 当出现页面国际化信息有??乱码时,就是springMVC搜索不到相对应的properties文件,但前一天还是正常的,经过改名后恢复正常。
13.SpringMVC异常处理
13.1说明
默认情况下异常处理器(HandlerExceptionResolver)有三个
- ExceptionHandlerExceptionResolver
- ResponseStatusExceptionResolver
- DefaultHandlerExceptionResolver
如果三个处理器依次都处理不了的异常直接抛给tomcat显示异常 - SimpleMappingExceptionResolver:这个异常处理器需要自己在springMVC中配置才能使用,指定发生异常时去什么页面
同理如果四个都设置了同一个异常的处理,执行顺序是从上到下的优先级
13.2异常注解
- @ExceptionHandler
在一个类中的某个方法上面加,即为告诉springMVC这个方法专门处理这个类中的‘’XX‘’异常
具体处理什么异常在value属性中配置
可以专门写个错误页面,当发生错误时跳转进错误页面告诉用户什么地方发生错误了 - @ControllerAdvice
当专门写了一个各种异常处理的集合类,用于告诉springMVC这个类专门处理异常 - @ResponseStatus
给自定义某个特定的异常类上标注的
13.3具体实现
/**
* 告诉SpringMVC这个方法专门处理这个类发生的异常 1、给方法上随便写一个Exception,用来接受发生的异常
* 2、要携带异常信息不能给参数位置写Model; 3、返回ModelAndView就行了;
* 4、如果有多个@ExceptionHandler都能处理这个异常,精确优先 5、全局异常处理与本类同时存在,本类优先;
*/
// @ExceptionHandler(value = { Exception.class })
// public ModelAndView handleException01(Exception exception) {
// System.out.println("本类的:handleException01..." + exception);
// //
// ModelAndView view = new ModelAndView("myerror");
// view.addObject("ex", exception);
// // 视图解析器拼串
// return view;
// }
三.SpringMVC下WEB的三大组件的各种配置
1.HiddenHttpMethodFilter解决从页面上只能发起两种请求,GET、POST
1.1说明
由于前面我们可以知道增删改查都是使用一个对应的请求来辨别,但是在jsp中只提供了两种请求方式get和post,所有我们只能将删除和更新操作通过过滤器来让servlet来辨别是什么操作
从页面发起PUT、DELETE形式的请求?Spring提供了对Rest风格的支持
SpringMVC中有一个Filter;他可以把普通的请求转化为规定形式的请求;配置这个filter;
1.2在web.xml中配置HiddenHttpMethodFilter
注意:要配置在标签前面
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.3如何发其他形式请求?
按照以下要求:
- 创建一个post类型的表单
- 表单项中携带一个_method的参数
- 这个_method的值就是DELETE、PUT
<!-- 发送DELETE请求 -->
<form action="book/1" method="post">
<input name="_method" value="delete"/>
<input type="submit" value="删除1号图书"/>
</form><br/>
<!-- 发送PUT请求 -->
<form action="book/1" method="post">
<input name="_method" value="put"/>
<input type="submit" value="更新1号图书"/>
</form><br/>
1.4出现的问题
全部配置好后,如果在delete和put请求上面出现了405的问题,造成原因是Tomcat版本太高(博主用的是9.0.45)
- 第一种解决方案:请在处理页面的Java代码方法上加上@ResponseBody注解,方可解决,
- 第二种解决方案:在跳转后的页面的jsp的头标签中加入isErrorPage="true
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
2.提交数据乱码问题
- 请求乱码:
- GET请求(所有请求的信息都带在url中,服务器一收到就开始解析):改server.xml;在8080端口处URIEncoding=“UTF-8”
- POST请求(所有信息都在请求体中,服务器收到不会了立马解析,直到代码request.getParameter(“xxx”)执行才会解析):SpringMVC提供一个filter(要配置在所有filter之前,不然请求进不去)
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- encoding:指定解决POST请求乱码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<!-- forceEncoding:顺手解决响应乱码;response.setCharacterEncoding(this.encoding); -->
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 响应乱码:
response.setContentType(“text/html;charset=utf-8”)
2.1国际化出现乱码问题
- 在idea中的setting中选择
- 在spring.xml中配置
<!--让SpringMVC管理国际化资源文件;配置一个资源文件管理器;id是必须叫messageSource ,因为在service层spring架构中的方法设置国际化的变量名就是这个messageSource -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<!-- basename指定基础名-->
<property name="basename" value="i18n"></property>
</bean>
- 如果还是乱码请检查此页面是否经过了spring
四.SpringMVC中AJAX与JSON
1.AJAX
说明&步骤
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
步骤:
- 导包
- 配置(具体请回顾视频,太多类与注解的用法了)
在方法上面使用注解@ResponseBody:将返回的数据放到响应体中,导入的jar包自动将对象转化为json
@ResponseBody:返回json数据
其中之一的用法:
@ResponseBody
@RequestMapping("/hello02")
public String test02(){
return "<h1>success</h1>";
}
@RequestBody:接收json数据
五.SpringMVC执行流程
- 所有请求,前端控制器(DispatcherServlet)收到请求,调用doDispatch进行处理
- 根据HandlerMapping中保存的请求映射信息找到,处理当前请求的,处理器执行链(包含拦截器)
- 根据当前处理器找到他的HandlerAdapter(适配器)
- 拦截器的preHandle先执行
- 适配器执行目标方法,并返回ModelAndView
- 拦截器的postHandle执行
- 处理结果;(页面渲染流程)