小插曲:
小插曲1、出现xml配置文件xsd标红,项目右击->Maven单击->Reimport单击,重新导入meven
小插曲2、出现引入本地jQuery,仍是无效Unresolved function or method $(),先是利用原生javascript发现能执行,后面查看博文,先是打算重启一下IDEA再说,发现意外解决问题,但仍是提示上述无效,以后万事不决先重启IDEA
记得刚开始入门时候,提到spring开启注解mvc的支持,开不开无所谓,但是现在发现,不开容易出现一系列不可预知问题404,所以后面都加上
<mvc:annotation-driven>mvc:annotation-driven>
1. 返回字符串
1. Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
2. 返回值是void
1. 如果控制器的方法返回值编写成void,没有返回响应数据,执行程序报404的异常,默认查找JSP页面没有找到。
原因,会调用视图解析器,至于字符串则是一二级目录拼凑的。
2. 可以使用请求转发或者重定向跳转到指定的页面,后面SpringMVC框架也提供了转发和重定向
3. 直接返回响应数据
3. 返回值是ModelAndView对象
1. ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图
response.jsp里触发下列方法
<body>
<a href="user/testString">testStringa><br/>
<a href="user/testVoid">testVoida><br/>
<a href="user/testForwardOrRedirect">testForwardOrRedirecta><br/>
<a href="user/testModelAndView">testModelAndViewa><br/>
body>
success.jsp页面,至于index就是普通页面,没啥内容,就不附了
<body>
<h3>执行成功h3>
${user.uname}
${user.age}
body>
控制器处理结果
package com.valerius.controller;
import com.valerius.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 返回字符串
* @param model
* @return
*/
@RequestMapping("/testString")
public String testString(Model model){
// 模拟从数据库查找对象
User user = new User();
user.setUname("张三");
user.setAge(18);
model.addAttribute("user", user);
return "success";
}
/**
* 返回空
*/
@RequestMapping("/testVoid")
public void testVoid(){
// 模拟从数据库查找对象
System.out.println("testVoid方法执行...");
}
/**
* 返回空,但使用了 转发 或重定向 或直接返回响应数据
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/testForwardOrRedirect")
public void testForwardOrRedirect(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 模拟从数据库查找对象
System.out.println("testForwardOrRedirect方法执行...");
// 执行转发
//request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
// 执行重定向
//System.out.println(request.getContextPath());
//response.sendRedirect(request.getContextPath() + "/index.jsp");
// 设置中文编码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
// 直接返回响应数据
response.getWriter().println("nihao");
response.getWriter().println("你好");
return;
}
/**
* 返回 ModelAndView
* 注意:返回字符串底层使用的仍是下面的代码
* @return
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
// 创建ModelAndVies对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView执行了");
// 模拟从数据库取对象,后存入session
User user = new User();
user.setUname("张三");
user.setAge(18);
// 把user对象存入mv对象中
mv.addObject("user", user);
// 跳转页面
mv.setViewName("success");
return mv;
}
}
DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
1. mvc:resources标签配置不过滤
1. location元素表示webapp目录下的包下的所有文件
2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
参考博文:设置静态资源不被拦截的方法汇总
@RequestBody将json转化为JavaBean
@ResponseBody将JavaBean对象转化为json
// 页面加载
$(function(){
// 绑定点击事件
$("#btn").click(function(){
$.ajax({
url:"user/testJson",
contentType:"application/json;charset=UTF-8",
data:'{"addressName":"aa","addressNum":100}',
dataType:"json",
type:"post",
success:function(data){
alert(data);
alert(data.addressName);
}
});
});
});
* 获取请求体的数据
* @param body
*/
@RequestMapping("/testJson")
public void testJson(@RequestBody String body) {
System.out.println(body);
}
2、使用@RequestBody注解把json的字符串转换成JavaBean的对象
// 页面加载
$(function(){
// 绑定点击事件
$("#btn").click(function(){
$.ajax({
url:"user/testJson",
contentType:"application/json;charset=UTF-8",
data:'{"addressName":"aa","addressNum":100}',
dataType:"json",
type:"post",
success:function(data){
alert(data);
alert(data.addressName);
}
});
});
});
/**
* 获取请求体的数据
* @param body
*/
@RequestMapping("/testJson")
public void testJson(@RequestBody Address address) {
System.out.println(address);
}
3、使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应,但要求方法需要返回JavaBean的对象
// 页面加载
$(function(){
// 绑定点击事件
$("#btn").click(function(){
$.ajax({
url:"user/testJson",
contentType:"application/json;charset=UTF-8",
data:'{"addressName":"哈哈","addressNum":100}',
dataType:"json",
type:"post",
success:function(data){
alert(data);
alert(data.addressName);
}
});
});
});
@RequestMapping("/testJson")
public @ResponseBody Address testJson(@RequestBody Address address) {
System.out.println(address);
address.setAddressName("上海");
return address;
}
json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.9.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.9.0version>
dependency>
. forward请求转发
/**
* 使用forward关键字进行请求转发
* "forward:转发的JSP路径",不走视图解析器了,所以需要编写完整的路径
* @return
* @throws Exception
*/
@RequestMapping("/delete")
public String delete() throws Exception {
System.out.println("delete方法执行了...");
// return "forward:/WEB-INF/pages/success.jsp";
return "forward:/user/findAll";
}
redirect重定向
/**
* 重定向
* @return
* @throws Exception
*/
@RequestMapping("/count")
public String count() throws Exception {
System.out.println("count方法执行了...");
return "redirect:/add.jsp";
// return "redirect:/user/findAll";
}
异常最后都返回到前端控制器,前端控制器分配给异常处理器组件处理,处理好或不能处理返回到一个错误页面等
package com.valerius.exception;
public class SysException extends Exception{
private static final long serialVersionUID = 4055945147128016300L;
// 异常提示信息
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
package com.valerius.exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 异常处理器
* @author rt
*/
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 跳转到具体的错误页面的方法
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
ex.printStackTrace();
SysException e = null;
// 获取到异常对象
if(ex instanceof SysException) {
e = (SysException) ex;
}else {
e = new SysException("请联系管理员");
}
ModelAndView mv = new ModelAndView();
// 存入错误的提示信息
mv.addObject("message", e.getMessage());
// 跳转的Jsp页面
mv.setViewName("error");
return mv;
}
}
<bean id="sysExceptionResolver" class="com.valerius.exception.SysExceptionResolver"/>
异常处理后转向页面error.jsp就不附了,只附上一个触发异常的方法
@RequestMapping("/testException")
public String testException() throws SysException {
System.out.println("异常执行...");
try{
int a = 10/0;
}
catch(Exception e){
e.printStackTrace();
throw new SysException("查询所有");
}
return "success";
}
2. SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
3. 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链
中的拦截器会按着定义的顺序执行。
4. 拦截器和过滤器的功能比较类似,有区别
1. 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
2. 拦截器是SpringMVC框架独有的。
3. 过滤器配置了/*,可以拦截任何资源。
4. 拦截器只会对控制器中的方法进行拦截。
5. 拦截器也是AOP思想的一种实现方式
6. 想要自定义拦截器,需要实现HandlerInterceptor接口。
注意过滤器和拦截器两者的区别:
1、过滤器是 servlet 规范中的一部分, 任何 java web 工程都可以使用。
2、拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
3、过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。所以过滤器经常需要放行静态资源
4、拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp, html,css,image 或者 js 是不会进行拦截的。
创建类,实现HandlerInterceptor接口,重写需要的方法
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* 自定义拦截器1
* @author rt
*/
public class MyInterceptor1 implements HandlerInterceptor{
/**
* controller方法执行前,进行拦截的方法
* return true放行
* return false拦截
* 可以使用转发或者重定向直接跳转到指定的页面。
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("拦截器执行了...");
return true;
}
}
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 哪些方法进行拦截 -->
<mvc:mapping path="/user/*"/>
<!-- 哪些方法不进行拦截
<mvc:exclude-mapping path=""/>
-->
<!-- 注册拦截器对象 -->
<bean class="cn.valerius.demo1.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
1. preHandle方法是controller方法执行前拦截的方法
1. 可以使用request或者response跳转到指定的页面
2. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
3. return false不放行,不会执行controller中的方法。
2. postHandle是controller方法执行后执行的方法,在JSP视图执行前。
1. 可以使用request或者response跳转到指定的页面
2. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
3.afterCompletion 只有 preHandle 返回 true 才调用,而且此方法返回为空。可以做一些资源清理