admin管理员组文章数量:1794759
SpringMVC面试题(2020版)
SpringMVC和Struct2的区别
共同点:
- 都是表现层框架,都是基于MVC模型编写的
- 底层都离不开ServletAPI
- 处理请求的机制是一个核心控制器 区别:
- SpringMVC入口是Servlet,Struct2入口是Filter
- SpringMVC是基于方法设计的,它是单例的。Struct2是基于类设计的,是多例的,每次都会重新创建处理对象,所以每次去执行操作时,SpringMV C会比Struct2快一些。
- SpringMVC处理Ajax请求更方便。
- Struct2的OGNL表达式开发效率比SpringMVC更高,但是执行效率并没有比JSTL表达式高。
执行流程: 完整案例: index.jsp:
<h3>入门程序</h3> <a href="hello">入门程序</a>HelloController.java:
// 控制器类 @Controller public class HelloController { @RequestMapping(path="/hello") public String sayHello(){ System.out.println("Hello StringMVC"); return "success"; } }web.xml:
<web-app> <display-name>Archetype Created Web Application</display-name> <!--配置前端控制器--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--加载springmvc.xml配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!--一启动tomcat就创建DispatcherServlet对象,然后创建springmvc.xml文件--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>resources中的springmvc.xml.
<!-- 开启注解扫描 --> <context:component-scan base-package="cn.itcast"/> <!-- 视图解析器对象 --> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 开启SpringMVC框架注解的支持 --> <mvc:annotation-driven/>success.jsp:
<h3>入门成功</h3>运行结果:
SpringMVC的消处理流程有了解吗?(重点)各个组件的功能:
- DispatcherServlet:前端控制器 控制整个流程的执行,调用其它组件处理用户请求
- HandlerMapping:处理器映射器 根据用户请求找到Controller类中的映射方法,如:ControllerHello类中sayHello()
- HandlerAdapter:处理器适配器 处理controller类中映射方法,并返回modelandview给前端控制器
- ViewResolver:视图解析器 对modelandview进行解析,返回view
- View:视图 浏览器将view渲染出来,返回给客户端
作用:建立请求URL和处理请求方法之间的对应关系 属性: path==value指定映射路径的 method指定请求方式。如:GET、POST、PUT、DELETE等 eg:
@RequestMapping(value="/testRequestMapping",method = {RequestMethod.GET}) public String testRequestMapping(){ System.out.println("测试RequestMapping注解..."); return "success"; }params指定请求参数的条件,要求请求参数的key-value和配置的一模一样 eg:
@RequestMapping(value="/testRequestMapping",params = {"username=heihei"}) public String testRequestMapping(){ System.out.println("测试RequestMapping注解..."); return "success"; } <a href="user/testRequestMapping?username=heihei">RequestMapping注解</a>headers:指定请求消头 eg:
@RequestMapping(value="/testRequestMapping",headers = {"Accept"}) public String testRequestMapping(){ System.out.println("测试RequestMapping注解..."); return "success"; }浏览器中按F12进行调试就可以看到消头
绑定请求参数入门级 执行流程: param.jsp:
<a href="param/testParam?username=hehe&password=123">请求参数绑定</a>ParamController.java:
/** * 请求参数绑定 */ @Controller @RequestMapping("/param") public class ParamController { /** * 请求参数绑定入门 * @return */ @RequestMapping("/testParam") public String testParam(String username,String password){ System.out.println("执行了..."); System.out.println("用户名:"+username); System.out.println("密码:"+password); return "success"; }运行结果: 把参数封装到javabean中的数据绑定(带有对象引用) 执行流程: Account.java:
public class Account implements Serializable{ private String username; private String password; private Double money; private User user; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String toString() { return "Account{" + "username='" + username + '\\'' + ", password='" + password + '\\'' + ", money=" + money + ", user=" + user + '}'; } }User.java:
public class User implements Serializable{ private String uname; private Integer age; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "uname='" + uname + '\\'' + ", age=" + age + ", date=" + date + '}'; } }param.jsp:
<form action="param/saveAccount" method="post"> 姓名:<input type="text" name="username" /><br/> 密码:<input type="text" name="password" /><br/> 金额:<input type="text" name="money" /><br/> 用户姓名:<input type="text" name="user.uname" /><br/> 用户年龄:<input type="text" name="user.age" /><br/> <input type="submit" value="提交" /> </form>ParamController.java:
/** * 请求参数绑定 */ @Controller @RequestMapping("/param") public class ParamController { /** * 请求参数绑定把数据封装到JavaBean的类中 * @return */ @RequestMapping("/saveAccount") public String saveAccount(Account account){ System.out.println("执行了..."); System.out.println(account); return "success"; } }运行结果: 带有集合类型的数据绑定 Account.java:
public class Account implements Serializable{ private String username; private String password; private Double money; private List<User> list; private Map<String,User> map; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } public List<User> getList() { return list; } public void setList(List<User> list) { this.list = list; } public Map<String, User> getMap() { return map; } public void setMap(Map<String, User> map) { this.map = map; } @Override public String toString() { return "Account{" + "username='" + username + '\\'' + ", password='" + password + '\\'' + ", money=" + money + ", list=" + list + ", map=" + map + '}'; } }User.java:
public class User implements Serializable{ private String uname; private Integer age; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "uname='" + uname + '\\'' + ", age=" + age + ", date=" + date + '}'; } }param.jsp:
<form action="param/saveAccount" method="post"> 姓名:<input type="text" name="username" /><br/> 密码:<input type="text" name="password" /><br/> 金额:<input type="text" name="money" /><br/> 用户姓名:<input type="text" name="list[0].uname" /><br/> 用户年龄:<input type="text" name="list[0].age" /><br/> 用户姓名:<input type="text" name="map['one'].uname" /><br/> 用户年龄:<input type="text" name="map['one'].age" /><br/> <input type="submit" value="提交" /> </form>ParamController.java:
@RequestMapping("/saveAccount") public String saveAccount(Account account){ System.out.println("执行了..."); System.out.println(account); return "success"; }运行结果:
配置解决中文乱码的过滤器发送请求后,控制台出现乱码: 解决: web.xml:
<!--配置解决中文乱码的过滤器--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>解决后:
自定义类型转换器我们在页面中输入数据时,它都是按照字符串类型进行处理的,但是我么后台中各种数据类型划分明确,它是如何将字符串类型转换成后台中对应的数据类型呢!这就是SpringMVC框架为我们做好的-----类型转换器。 但是有些类型可能框架无法转换,如:日期类型-写法2014-09-03无法转换,但是/写法可以转换2014/09/03。 这需要我们自定义类型转换器
步骤:
User.java:
public class User implements Serializable{ private String uname; private Integer age; private Date date; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } @Override public String toString() { return "User{" + "uname='" + uname + '\\'' + ", age=" + age + ", date=" + date + '}'; } }param.jsp:
<form action="param/saveUser" method="post"> 用户姓名:<input type="text" name="uname" /><br/> 用户年龄:<input type="text" name="age" /><br/> 用户生日:<input type="text" name="date" /><br/> <input type="submit" value="提交" /> </form>ParamController.java:
@Controller @RequestMapping("/param") public class ParamController { /** * 自定义类型转换器 * @param user * @return */ @RequestMapping("/saveUser") public String saveUser(User user){ System.out.println("执行了..."); System.out.println(user); return "success"; } }类型转换代码:
/** * 把字符串转换日期 */ public class StringToDateConverter implements Converter<String,Date>{ /** * String source 传入进来字符串 * @param source * @return */ public Date convert(String source) { // 判断 if(source == null){ throw new RuntimeException("请您传入数据"); } DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); try { // 把字符串转换日期 return df.parse(source); } catch (Exception e) { throw new RuntimeException("数据类型转换出现错误"); } } }springmvc.xml:
<!--配置自定义类型转换器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="cn.itcast.utils.StringToDateConverter"/> </set> </property> </bean> <!-- 让类型转换器生效 --> <mvc:annotation-driven conversion-service="conversionService"/> SpringMVC常用注解(重点)- @RequestParam 作用:把请求中指定名称的参数给控制器中形参赋值 使用地方:方法形参上 属性: value==name指定参数的名称 required指定请求参数中是否必须提供参数,默认值为true。
anno.jsp:
<a href="anno/testRequestParam?dname=哈哈">RequestParam</a>AnnoController.java:
运行结果:
@requestparam案例再重现 @requestparam案例再现
- @RequestBody 作用:获取请求体的内容,得到的是key=value&key=value…结构的数据 使用地方:方法形参上 属性: required指定是否必须有请求体,默认值为true 细节:对GET请求方式没用
运行结果:
restful风格 优点:结构清晰、易于理解、方便扩展
- @PathVariable 作用:指定请求的URL路径里面的变量 使用地方:方法的形参上 属性: name==value指定参数的名称
运行结果:
- @RequestHeader 作用:获取请求头的值 使用地方:方法的形参上 属性: value指定请求头类型,如:Accept等
运行结果:
-
@RequestAttribute 作用:获取request请求域中的值 作用地方:方法的形参上 属性:required 指定是否必须有请求域,默认值是true
-
@CookieValue 作用:用于把指定的cookie名称值给控制器方法形参赋值 使用地方:方法的形参上 属性: value指定参数名,如:JSESSIONID
anno.jsp:
<a href="anno/testCookieValue">CookieValue</a>AnnoController.java:
@Controller @RequestMapping("/anno") public class AnnoController { /** * 获取Cookie的值 * @return */ @RequestMapping(value="/testCookieValue") public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){ System.out.println("执行了..."); System.out.println(cookieValue); return "success"; } }运行结果:
- @ModelAttribute 作用:出现在方法上,表示当前方法会在控制器方法执行之前先执行 出现在参数上,获取指定的数据给参数赋值 出现位置:方法上和参数上都可以
执行流程: @ModelAttribute注解修饰的方法有返回值 anno.jsp:
<form action="anno/testModelAttribute" method="post"> 用户姓名:<input type="text" name="uname" /><br/> 用户年龄:<input type="text" name="age" /><br/> <input type="submit" value="提交" /> </form> @Controller @RequestMapping("/anno") public class AnnoController { /** * ModelAttribute注解 * @return */ @RequestMapping(value="/testModelAttribute") public String testModelAttribute( User user){ System.out.println("testModelAttribute执行了..."); System.out.println(user); return "success"; } // 该方法会先执行 @ModelAttribute public User showUser(String uname){ System.out.println("showUser执行了..."); // 通过用户查询数据库(模拟) User user = new User(); user.setUname(uname); user.setAge(20); user.setDate(new Date()); return user; } }运行结果: @ModelAttribute注解修饰的方法没有返回值(用在参数上)
执行流程: anno.jsp:
<form action="anno/testModelAttribute" method="post"> 用户姓名:<input type="text" name="uname" /><br/> 用户年龄:<input type="text" name="age" /><br/> <input type="submit" value="提交" /> </form>AnnoController.java:
@Controller @RequestMapping("/anno") public class AnnoController { /** * ModelAttribute注解 * @return */ @RequestMapping(value="/testModelAttribute") public String testModelAttribute(@ModelAttribute("abc") User user){ System.out.println("testModelAttribute执行了..."); System.out.println(user); return "success"; } @ModelAttribute public void showUser(String uname, Map<String,User> map){ System.out.println("showUser执行了..."); // 通过用户查询数据库(模拟) User user = new User(); user.setUname(uname); user.setAge(20); user.setDate(new Date()); map.put("abc",user); } }- @SessionAttributes 作用:用于多次执行控制器方法间参数共享 使用地方:类上 属性:value==names指定request域中的key
在页面中获取session域中数据: 执行流程: anno.jsp:
<a href="anno/getSessionAttributes">getSessionAttributes</a> <a href="anno/delSessionAttributes">delSessionAttributes</a> <a href="anno/testSessionAttributes">testSessionAttributes</a>AnnoController.java:
@Controller @RequestMapping("/anno") @SessionAttributes(value={"msg"}) // 把msg=美美存入到session域对中 public class AnnoController { /** * 把数据存储到request域中 * @return */ @RequestMapping(value="/testSessionAttributes") public String testSessionAttributes(Model model){ System.out.println("testSessionAttributes..."); // 把数据存储到request域中 model.addAttribute("msg","美美"); return "success"; } /** * 获取到session域中数据 * @param modelMap * @return */ @RequestMapping(value="/getSessionAttributes") public String getSessionAttributes(ModelMap modelMap){ System.out.println("getSessionAttributes..."); String msg = (String) modelMap.get("msg"); System.out.println(msg); return "success"; } /** * 清除session域中的数据 * @param status * @return */ @RequestMapping(value="/delSessionAttributes") public String delSessionAttributes(SessionStatus status){ System.out.println("getSessionAttributes..."); status.setComplete(); return "success"; } }在页面中取出session域中的数据 success.jsp:
<h3>入门成功</h3> ${sessionScope}运行结果:
响应之返回值是字符串类型执行流程: 浏览器发送请求>>>后台查出数据,存到model对象中,然后存到request域中>>>跳转页面,将request域中数据取出来 response.jsp:
<a href="user/testString" >testString</a>UserController.java:
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testString") public String testString(Model model){ System.out.println("testString方法执行了..."); // 模拟从数据库中查询出User对象 User user = new User(); user.setUsername("美美"); user.setPassword("123"); user.setAge(30); // model对象 model.addAttribute("user",user); return "success"; } }success.jsp:
<h3>执行成功</h3> ${user.username} ${user.password} ${user.age}运行结果:
响应之返回值是ModelAndView类型同返回值是字符串类型
<a href="user/testModelAndView" >testModelAndView</a> @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ // 创建ModelAndView对象 ModelAndView mv = new ModelAndView(); System.out.println("testModelAndView方法执行了..."); // 模拟从数据库中查询出User对象 User user = new User(); user.setUsername("小凤"); user.setPassword("456"); user.setAge(30); // 把user对象存到ModelAndView对象中,然后会存储到request域中 mv.addObject("user",user); // 跳转到哪个页面 mv.setViewName("success"); return mv; } } <h3>执行成功</h3> ${user.username} ${user.password} ${user.age}运行结果:
响应之返回值是void类型项目目录结构:
- 请求转发
运行结果:
- 重定向
运行结果:
- 直接进行相应
执行流程: 设置编码格式>>>设置浏览器解析格式和字符集>>>直接进行响应
<a href="user/testVoid" >testVoid</a> @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testVoid") public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("testVoid方法执行了..."); // 设置中文乱码 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); // 直接会进行响应 response.getWriter().print("你好"); return; } }运行结果:
请求转发和重定向的区别(重点)- 请求转发:
处理流程: 1.客户端发送请求,servlet做出业务逻辑处理 2.servlet调用forward方法,服务器把目标资源返回给客户端
- 重定向
处理流程: 1.客户端发送请求,servlet做出业务逻辑处理 2.servlet调用sendRedirect()方法,把要访问的目标资源作为响应头返回给客户端 3.客户端再次访问服务器的xxx.jsp页面,服务器再次对客户端做出响应 区别: 1.请求转发在服务器内部转发,整个过程处于同一个请求中 2.重定向则是完全的跳转,浏览器会得到跳转后的地址,重新发送请求,整个过程处于两个请求中 3.请求转发中数据的存取可以使用request域:request.setAttribute(),request.getAttribute(),重定向是取不到request域的,只能使用session 4.请求转发在服务器内部进行,不能跨域、重定向可以跨域
Ajax请求之异步请求(补) 响应json数据之发送Ajax请求页面发送ajax请求,后端拿到数据,并打印出来
response.jsp:
<script> // 页面加载,绑定单击事件 $(function(){ $("#btn").click(function(){ // alert("hello btn"); // 发送ajax请求 $.ajax({ // 编写json格式,设置属性和值 url:"user/testAjax", contentType:"application/json;charset=UTF-8", data:'{"username":"hehe","password":"123","age":30}', dataType:"json", type:"post", }); }); }); </script>UserController.java:
@Controller @RequestMapping("/user") public class UserController { /** * 模拟异步请求响应 */ @RequestMapping("/testAjax") public void testAjax(@RequestBody String body){ System.out.println("testAjax方法执行了..."); System.out.println(body);// 做响应,模拟查询数据库 } }运行结果:
响应json数据之响应json格式数据页面发送ajax请求,传的是json字符串数据,后端拿到json字符串数据给封装到user对象中,@ResponseBody把user对象转成json字符串数据再返回给页面。
response.jsp:
// 页面加载,绑定单击事件 $(function(){ $("#btn").click(function(){ // alert("hello btn"); // 发送ajax请求 $.ajax({ // 编写json格式,设置属性和值 url:"user/testAjax", contentType:"application/json;charset=UTF-8", data:'{"username":"hehe","password":"123","age":30}', dataType:"json", type:"post", success:function(data){ // data服务器端响应的json的数据,进行解析 alert(data); alert(data.username); alert(data.password); alert(data.age); } }); }); });UserController.java:
@Controller @RequestMapping("/user") public class UserController { /** * 模拟异步请求响应 * @ResponseBody把user对象转成json字符串数据返回给页面 */ @RequestMapping("/testAjax") public @ResponseBody User testAjax(@RequestBody User user){ System.out.println("testAjax方法执行了..."); // 客户端发送ajax的请求,传的是json字符串,后端把json字符串封装到user对象中 System.out.println(user); // 做响应,模拟查询数据库 user.setUsername("haha"); user.setAge(40); // 做响应 return user; } }运行结果:
文件上传 传统方式上传执行流图: index.jsp:
<form action="user/fileupload1" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="upload" /><br/> <input type="submit" value="上传" /> </form>UserController.java:
@Controller @RequestMapping("/user") public class UserController { /** * 文件上传 * @return */ @RequestMapping("/fileupload1") public String fileuoload1(HttpServletRequest request) throws Exception { System.out.println("文件上传..."); // 使用fileupload组件完成文件上传 // 上传的位置 String path = request.getSession().getServletContext().getRealPath("/uploads/"); // 判断,该路径是否存在 File file = new File(path); if(!file.exists()){ // 创建该文件夹 file.mkdirs(); } // 解析request对象,获取上传文件项 DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); // 解析request List<FileItem> items = upload.parseRequest(request); // 遍历 for(FileItem item:items){ // 进行判断,当前item对象是否是上传文件项 if(item.isFormField()){ // 说明普通表单向 }else{ // 说明上传文件项 // 获取上传文件的名称 String filename = item.getName(); // 把文件的名称设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; // 完成文件上传 item.write(new File(path,filename)); // 删除临时文件 item.delete(); } } return "success"; } }运行结果:
Springmvc框架文件上传原理图: springmvc.xml:
<!--配置文件解析器对象--> <bean id="multipartResolver" class="org.springframework.web.multipartmons.CommonsMultipartResolver"> <!--字节单位--> <property name="maxUploadSize" value="10485760" /> </bean>UserController.java:
@Controller @RequestMapping("/user") public class UserController { /** * SpringMVC文件上传 * @return */ @RequestMapping("/fileupload2") public String fileuoload2(HttpServletRequest request, MultipartFile upload) throws Exception { System.out.println("springmvc文件上传..."); // 使用fileupload组件完成文件上传 // 上传的位置 String path = request.getSession().getServletContext().getRealPath("/uploads/"); // 判断,该路径是否存在 File file = new File(path); if(!file.exists()){ // 创建该文件夹 file.mkdirs(); } // 说明上传文件项 // 获取上传文件的名称 String filename = upload.getOriginalFilename(); // 把文件的名称设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; // 完成文件上传 upload.transferTo(new File(path,filename)); return "success"; } } 跨服务器上传图片经过应用服务器,上传到图片服务器 index.jsp:
<form action="user/fileupload3" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="upload" /><br/> <input type="submit" value="上传" /> </form>UserController.java:
@Controller @RequestMapping("/user") public class UserController { /** * 跨服务器文件上传 * @return */ @RequestMapping("/fileupload3") public String fileuoload3(MultipartFile upload) throws Exception { System.out.println("跨服务器文件上传..."); // 定义上传文件服务器路径 String path = "localhost:9090/uploads/"; // 说明上传文件项 // 获取上传文件的名称 String filename = upload.getOriginalFilename(); // 把文件的名称设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; // 创建客户端的对象 Client client = Client.create(); // 和图片服务器进行连接 WebResource webResource = client.resource(path + filename); // 上传文件 webResource.put(upload.getBytes()); return "success"; } } springmvc异常处理步骤: 1.编写自定义异常类(做提示信的) 2.编写异常处理器代码 3.配置异常处理器(前端控制器能够找到它)
执行流图: 自定义异常类:
public class SysException extends Exception{ // 存储提示信的 private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public SysException(String message) { this.message = message; } }异常处理器:
public class SysExceptionResolver implements HandlerExceptionResolver{ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 获取到异常对象 SysException e = null; if(ex instanceof SysException){ e = (SysException)ex; }else{ e = new SysException("系统正在维护...."); } // 创建ModelAndView对象 ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg",e.getMessage()); mv.setViewName("error"); return mv; } }index.jsp:
<h3>异常处理</h3> <a href="user/testException" >异常处理</a>UserController.java:
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testException") public String testException() throws SysException { System.out.println("testException执行了..."); try { // 模拟异常 int a = 10/0; } catch (Exception e) { // 打印异常信 e.printStackTrace(); // 抛出自定义异常信 throw new SysException("查询所有用户出现错误了..."); } return "success"; } }springmvc.xml:
<!--配置异常处理器--> <bean id="sysExceptionResolver" class="cn.itcast.exception.SysExceptionResolver"/>error.jsp:
${errorMsg}运行结果:
拦截器作用:用于对处理器(Controller类中的方法)进行预处理和后处理
拦截器和过滤器的区别 1.过滤器是servelt规范的一部分,任何javaweb工程都能使用 2.拦截器是springmvc框架自己的,只有使用springmvc框架工程才能使用 3.过滤器在url-pattern中配置/*,可以对所有要访问的资源进行拦截 4.拦截器只会拦截要访问的控制器中的方法(Controller类中的方法),对于jsp、html、js、css、image等无法拦截
步骤: 1.编写拦截器类,实现HandlerInterceptor接口 2.配置拦截器,并在其中注册拦截器对象
执行流图:
index.jsp:
<h3>拦截器</h3> <a href="user/testInterceptor" >拦截器</a>拦截器:
public class MyInterceptor1 implements HandlerInterceptor{ /* * 预处理,controller方法执行前 * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法 * return false不放行 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1执行了...前1111"); return true; }springmvc.xml:
<!--配置拦截器--> <mvc:interceptors> <!--配置拦截器--> <mvc:interceptor> <!--要拦截的具体的方法--> <mvc:mapping path="/user/*"/> <!--不要拦截的方法 <mvc:exclude-mapping path=""/> --> <!--配置拦截器对象--> <bean class="cn.itcast.controller.itcast.interceptor.MyInterceptor1" /> </mvc:interceptor> </mvc:interceptors>UserController.java:
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testInterceptor") public String testInterceptor(){ System.out.println("testInterceptor执行了..."); return "success"; } }success.jsp:
<h3>执行成功</h3>运行结果: 拦截器接口(HandlerInterceptor)中的方法 preHandler()预处理方法,在Controller类方法执行之前执行,可以提前跳转到其他页面 postHandler()后处理方法,在控制类方法执行之后和页面跳转之前执行,同样也可以提前跳转到其他页面 afterCompletion()在整个过程执行完之后执行,不可以跳转页面
index.jsp:
<h3>拦截器</h3> <a href="user/testInterceptor" >拦截器</a>拦截器1:
public class MyInterceptor1 implements HandlerInterceptor{ /** * 预处理,controller方法执行前 * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法 * return false不放行 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1执行了...前1111"); request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); return true; } /** * 后处理方法,controller方法执行后,success.jsp执行之前 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1执行了...后1111"); request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * success.jsp页面执行后,该方法会执行 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1执行了...最后1111"); } }拦截器2:
public class MyInterceptor2 implements HandlerInterceptor{ /** * 预处理,controller方法执行前 * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法 * return false不放行 */ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("MyInterceptor1执行了...前2222"); request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); return true; } /** * 后处理方法,controller方法执行后,success.jsp执行之前 */ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("MyInterceptor1执行了...后2222"); request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response); } /** * success.jsp页面执行后,该方法会执行 */ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("MyInterceptor1执行了...最后2222"); } }处理器:
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/testInterceptor") public String testInterceptor(){ System.out.println("testInterceptor执行了..."); return "success"; } }springmvc.xml:
<!--配置拦截器--> <mvc:interceptors> <!--配置拦截器--> <mvc:interceptor> <!--要拦截的具体的方法--> <mvc:mapping path="/user/*"/> <!--不要拦截的方法 <mvc:exclude-mapping path=""/> --> <!--配置拦截器对象--> <bean class="cn.itcast.controller.itcast.interceptor.MyInterceptor1" /> </mvc:interceptor> <!--配置第二个拦截器--> <mvc:interceptor> <!--要拦截的具体的方法--> <mvc:mapping path="/**"/> <!--不要拦截的方法 <mvc:exclude-mapping path=""/> --> <!--配置拦截器对象--> <bean class="cn.itcast.controller.itcast.interceptor.MyInterceptor2" /> </mvc:interceptor> </mvc:interceptors>success.jsp:
<h3>执行成功</h3>运行结果:
版权声明:本文标题:SpringMVC面试题(2020版) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686813196a106099.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论