DispatcherServlet 核心控制器
Controller 控制器
Handler 处理器
1.搭建SpringMvc(了解)
1.将相关jar包导入项目
配置web.xml文件
3.配置SpringMvc主配置文件
4.创建一个包 com.controller,在包下创建一个类 类定义处要增加@Controller注解 5.类中新增一个方法作为处理器 6.为处理器映射访问路径,使用@RequestMapping() 2.@Controller注解(重要) /** * controller注解 * 1.注解需要写在类定义处 * 2.让一个类变成控制器 * @author muty * */ @Controller @RequestMapping("/my") public class MyController { } 3.@RequestMapping注解(重要) /** * 创建一个Handler * 控制器是一个java类 * 处理器是一个java方法 * 一个类中有多个java方法 * 一个控制器中有多个处理器 * 处理请求的是Handler * 和Servlet一样,需要设置一个访问路径,不然无法接受请求 * 在方法定义处增加@RequestMapping可为处理器设置访问路径 * 注意:1.访问路径的设置一般是与方法名一致 * 2. 斜杠/ 如果你的方法路径没有以斜杠开头,他会自动加上一个斜杠 * 如何访问:localhost:端口号/项目名/Handler访问路径 */ @RequestMapping("/helloSpringMvc") public void helloSpringMvc(){ System.out.println("这是第一个处理器"); } 4.Handler返回JSP(重要) 1.在SpringMvc主配置文件中,配置视图解析器 2.让Handler方法的返回值为String /** * 如果要让一个Handler返回到JSP的话,那么方法的返回值为String * 要返回某一个JSP,方法的返回值直接写JSP的文件名字,不需要写后缀名 * 前缀+方法返回值+后缀=页面路径 * /WEB-INF/jsp/ + hello + .jsp * 默认是以转发方法进行跳转(request) * @return */ @RequestMapping("/testPage") public String testPage(){ return "hello"; } 5.设置请求方式(了解) /** * 为Handler设置请求方式 * 如果为Handler设置了请求方式以后,那么只支持这一种请求方式 * 其他任何请求方式都访问不到 * @return */ @RequestMapping(value="/testMethod" ,method=RequestMethod.POST) public String testMethod(){ return "hello"; } 6.@RequestParam注解(重要) /** * @RequestParam 可以接收请求参数 * 传递参数方式: * 1.a标签 访问路径?id=123 request.getParameter(参数名) * 2.form表单提交 在form表单中有name属性的元素 会被提交 * 场景: * 假设有一个a标签将要请求到这个Handler并且携带两个参数 * 一个参数名字为id 一个参数名字为name * http://localhost:8080/SpringMvc_01/my/testParam * ?id=123&name=张三 * 用法: * 1.注解要写在方法的入参处 * String id = request.getParameter("id") --> String * value属性的 就是指定参数的名字 * 可以省略 * 2.如果不写required属性,默认为true,请求时参数必须传递,否则报400错误 * 3.defaultValue 如果参数值为空的话(空字符串情况除外),那么默认值将生效 */ @RequestMapping("/testParam") public String testParam (@RequestParam(value="id") Integer id, @RequestParam(value="name", required=false,defaultValue="无名") String name){ System.out.println(id); System.out.println(name); return "hello"; } 7.用实体类接收请求参数(重要) /** * 用实体类接收请求参数 * 场景: * 新增学生 输入 学生名字,年龄,性别,地址 * form表单提交 * request.getParameter() * .... * 使用实体类进行写入数据 * Stu stu = new Stu(); * stu.setXXX(); * .... * 用法: * 1.在Handler方法的入参处 传入实体类 * 2.需要将参数名与实体类中的属性名字对应(一模一样,区分大小写) * 会将参数值自动绑定到实体类的属性上 * XXX?stuName=张三&age=25 * */ @RequestMapping("/testParamBean") public String testParamBean(StuModel stuModel){ System.out.println(stuModel); return ""; } 8.设置请求时的编码方式(了解) 在web.xml文件中增加配置 9.使用Servlet Api(重要) /** * 在Handler中使用Servlet API * 场景: * a标签 -- 查询所有学生 * 向Servlet发起请求 * 1.到数据库查询所有学生 -- List<实体类> * 2.将数据集合 传递到JSP request.setAttribute() * 3.使用转发的形式跳转到列表页面的JSP * 4.JSTL 进行循环显示数据 * 列表页面 * 用法: * 1.如果需要使用request对象或者response对象或者其他Servlet对象 * 那么只需要在Handler方法的入参处 传递即可 * 注意: * 不要使用request进行跳转***** */ @RequestMapping("/testServlet") public String testServlet(HttpServletRequest request, HttpSession session){ request.setAttribute("name", "张三"); session.setAttribute("age", 25); return "hello"; } 10.Ant风格访问路径的映射(了解) /** * Ant风格的访问路径映射 * 通配符方式 * 用法: * 1.一个星号 * 星号代表可以匹配任意长度的任意字符 * /test/1123123123 /test/7656215371 * 只能向下匹配一级的路径 * /test/ */ @RequestMapping("/test/*") public String testAnt(){ return "hello"; } /** * 2.两个星号 两个星号在一起 * 可以匹配任意路径 * 无限级 * /test/asd/s/dd/asd/asd/2/eas/da/sda/ds/asd/sa * * /test/123 */ @RequestMapping("/test/**") public String testAnt1(){ System.out.println("testAnt1"); return "hello"; } /** * 3.问号 (占位符)? * 一个问号只能替换成一个字符 * /test/a1b2 * */ @RequestMapping("/test/a?b?") public String testAnt2(){ System.out.println("testAnt2"); return "hello"; } 11.@ModelAttribute注解(熟悉) /** * ModelAttribute注解 * 用法: * 1.写在参数上,要求 参数必须是实体类类型 * Handler会将实体类类型的参数自动存入request * key是参数的类名 首字母小写 * request.setAttribute(key,value) * ${stuModel.stuName} * 不写注解 request.setAttribute("stuModel",stuModel); * 写了注解 request.setAttribute("stu",stuModel); * 注意: * 1.如果手动对某个属性进行了set,那么将覆盖传递进来的值 * 2.如果使用request.setAttribute()向JSP传递数据的时候 * 如果key值和Handler中 实体类参数 类名首字母小写 一样 * 如果与@ModelAttribute注解中显式指定的值一样 * 会被覆盖 */ @RequestMapping("/testModel") public String testModel (@ModelAttribute("stu") StuModel stuModel, HttpServletRequest request){ System.out.println(stuModel.getAddress()); // JSP传递了一个id Handler 我用实体类来接收id 修改 Stu /** * handler(Stu stu,request){ * 根据id查询 * 将查到的数据传递到jsp * request.set...(stu,"stu"); * } */ // StuModel stu1 = new StuModel(); // stu1.setStuName("李四"); // stu1.setAge(99); // request.setAttribute("stu", stu1); // stuModel.setAge(null); return "hello"; } /** * 用法2: * 将注解写在方法定义处 * 会将方法的返回值存入request * 如果访问了一个Controller中的某一个Handler的时候 * 检测该Controller中是否有注解了@ModelAttribute的方法 * 如果有,先执行注解了@ModelAttribute的方法,然后在执行Handler * @return */ @ModelAttribute(value="stu") public StuModel setStuModel(){ StuModel stuModel = new StuModel(); stuModel.setStuName("王五"); stuModel.setAddress("北京市"); return stuModel; } 12.转发和重定向(重要) /** * 转发和重定向 * forward * redirect * 1.在跳转时指定方式 * 2.可以跳转到另外一个Handler上 * 如果需要从一个处理器跳转到另外一个处理器,那么需要执行跳转方式 * 如果处理器直接返回JSP,那么不需要指定方式, */ @RequestMapping("/forward") public String forward(){ return "forward:toPage"; } @RequestMapping("/toPage") public String toPage(){ return "hello"; } 13.PathVariable注解(模板类型URL)(熟悉) /** * http://geek.csdn.net/news/detail/24321 * http://geek.csdn.net/news/detail/243976 * 模板类型的URL * 参数占位符 * @PathVariable注解 * 场景: * 将请求参数隐藏到访问路径中,不使用问号进行传递参数 * 用法: * 接收请求参数,接收的是访问路径中的请求参数 * 接收时 value属性的值 要和大括号中的值对应 * 注意: * 不能接受form表单提交过来的参数和问号传递的参数 * {} 大括号代表了 这是一个参数 * 访问时要将参数占位符替换为一个具体的参数值 * /testPathVariable/123 * */ @RequestMapping("/testPathVariable/{id}/{name}") public String testPathVariable (@PathVariable(value="id") Integer id, @PathVariable(value="name") String name){ System.out.println(id); System.out.println(name); return "hello"; } 14.POST请求转换(了解) 1.在web.xml中配置请求转换过滤器 2.JSP中编写FORM表单 3.编写Handler /** * RestFul 风格 * 通过访问路径能够表达出 要做的事情是什么 * 将请求参数 放在访问路径 * GET 获取资源 * POST 新增资源 * PUT 更新资源 * DELETE 删除资源 * 两个Handler访问路径一样,但是请求方式不一样,是允许的 * 场景: * 学生 增删改查 * 将POST请求 转换为除GET类型以外的请求 * 用法: * 需要在web.xml中配置 转换过滤器 --SpringMvc提供 * 注意: * 1.要转换的请求必须是POST,GET请求不能转换 * 2.在form表中需要增加一个参数,name属性必须为_method * value 是 你要转换为的目标请求方式 */ @RequestMapping(value="/stuCRUD",method=RequestMethod.GET) public String selectStu(){ System.out.println("查询学生"); return ""; } //新增 @RequestMapping(value="/stuCRUD",method=RequestMethod.POST) public String insertStu(){ System.out.println("新增学生"); return ""; } //更新 @RequestMapping(value="/stuCRUD",method=RequestMethod.PUT) public String updateStu(){ System.out.println("更新学生"); return ""; } //删除 @RequestMapping(value="/stuCRUD",method=RequestMethod.DELETE) public String deleteStu(){ System.out.println("删除学生"); return ""; } 15.ModelAndView(重要) /** * ModelAndView * 功能: * 1.返回视图 * 2.传递数据 存入到request * 用法: * 返回的返回值为ModelAndView */ @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ ModelAndView modelAndView = new ModelAndView(); //setView(View view) View是个接口 modelAndView.setViewName("hello"); //传递一个Map集合 把要传递的数据全部存入map集合 //将map集合传递到addAllObjects方法里 //${requestScope.name} Map map.put("name", "张三"); modelAndView.addAllObjects(map); //一个参数,将一个对象存入request ? String address = "北京"; modelAndView.addObject(address); String add = "上海"; modelAndView.addObject(add); //两个参数,对应key和value modelAndView.addObject("age", 25); return modelAndView; } 16.ModelMap和Map集合(重要) 在SpringMvc中一共4种方式可以向request作用域保存数据 ModenAndView,ModelAttribute,ModelMap,Map集合 /** * ModelMap -- Map集合 * 作用: * 处理器执行完后,会将ModelMap中的所有键值对 存入request * 用法: * 在处理器入参处声明ModelMap */ @RequestMapping("/testModelMap") public String testModelMap(ModelMap modelMap){ modelMap.addAttribute("name", "张三"); return "hello"; } /** * Map参数 --java中的Map * 作用: * 将map集合中的键值对存入request * 用法: * 在处理器入参处声明Map集合 */ @RequestMapping("/testMap") public String testMap(Map map.put("data", "这是map中的数据"); return "hello"; } 17.@SessionAttributes注解(了解) /** * 向session中保存数据 * @SessionAttribute * 作用: * 将ModelMap中的数据 复制到session中一份 * ModelAndView,ModelAttirbute,Map集合 都是将数据先放入ModelMap * 用法: * 只能在写类定义处 * 过程: * 写在类定义处,作用于整个控制器 * 在执行控制器中的任意一个处理器的时候,该注解都会进行工作 * 1.用value属性中值,去跟处理器的ModelMap中的key进行匹配 * 如果发现匹配成功(一模一样),那么会将ModelMap中的该键值对复制到session * 2.用types属性值的值,去跟处理器的ModelMap中的value的类型进行匹配 * 如果发现类型一致,那么会将该键值对复制到session */ 用法: 在类定义处增加注解,会将匹配到的键值对复制到session @SessionAttributes(value={"name","data"},types={String.class,Integer.class}) public class MyController { 18.自定义视图(熟悉) /** * 自定义视图使用过程 * 1.创建一个类 实现View接口 * 2.实现接口中的方法 * 3.将自定义视图的类存入ioc容器 * 3.1 在类定义处增加注解,要保证这个类能被扫描到 * 3.2手动在配置文件中,使用bean标签,将类存入容器 * 4.在配置文件中 配置自定义视图解析器 * @author muty * */ @Component public class MyView implements View{ /** * 设置视图类型 */ @Override public String getContentType() { return "text/html"; } /** * 视图内容 */ @Override public void render(Map HttpServletResponse response) throws Exception { //设置编码格式 response.setHeader("Content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.getWriter().print(" } } /** * 返回自定义视图 * 如果使用String来返回自定义视图,那么返回值写的自定义视图在ioc容器中的id */ @RequestMapping("/returnView") public String returnView(){ return "myView"; } @RequestMapping("/returnModelAndView") public ModelAndView returnModelAndView(){ ModelAndView modelAndView = new ModelAndView(new MyView()); // modelAndView.setView(new MyView()); return modelAndView; } 19.国际化配置(了解) 方式一:通过识别浏览器语言来实现国际化 1.在src下编写资源文件,中文和英文 i18n_zh_CN.properties i18n_en_US.properties 2.在SpringMvc中配置国际化资源管理器 3.编写Handler跳转到一个国际化的JSP 4.JSP中需要导入标签库 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 这个标签库需要导入JSTL相关jar包 在JSP中使用标签获取资源文件中的键值对 5.通过切换浏览器语言来实现 国际化 方式二:通过点击链接实现国际化 1.在SpringMvc配置文件中增加配置 2.在webcontent下新建test.jsp,在jsp中放置两个a标签 3.通过点击链接可实现国际化切换 20.文件上传(重要) * 文件上传 * 1.导入两个jar包 commons-fileupload,commons-io * 2.配置文件上传解析器 * 3.在JSP编写一个form表单,表单的method要为post * 要为表单指定enctype="multipart/form-data" * 要为file控件 指定name属性 * 4.在Handler中接收文件,使用@RequestParam注解, * value的值 和 file控件name的值 对应 即可 * 使用MultipartFile来接收文件 * 注意: * MultipartFile对象,不论是否选择了文件,值都不为null * 如果想判断用户是否选择了文件,那么需要判断文件名是否为空 * 多个文件List @RequestMapping("/uploadFile") public String uploadFile( @RequestParam(value="file") MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException{ //获取文件名 String fileName = file.getOriginalFilename(); //获取upload文件夹的绝对路径 String realPath = request.getServletContext() .getRealPath("/upload"); //写入文件 //拼接完整路径 String filePath = realPath + File.separator + fileName; //根据完整路径 创建File实例 File uploadFile = new File(filePath); //上传 调用MultipartFile对象的transferTo方法 file.transferTo(uploadFile); //获取相对路径 /SpringMvc_03/upload/图片名字 String showPath = request.getContextPath()+"/upload/"+fileName; request.setAttribute("showPath", showPath); return "hello"; } 21.@ResponseBody注解(重要) /** * ResponseBody注解 * 场景: * 1.为手机接口提供json数据 * 2.为前端提供json数据 * 3.一般情况会配合ajax来使用,如果要用ajax的方式来请求一个处理器,那么 * 处理器一定要注解ResponseBody,如果没有该注解,那么ajax将拿不到返回值 * 用法: * 导入jackson的3个jar包 * 要写在方法定义处 * 会将Handler方法的返回值 格式化为JSON,通过response响应 * 注意: * 如果Handler被注解了 ResponseBody 那么将不能在返回视图 * 而且,注解ResponseBody的Handler request.setAttribute无意义 */ @ResponseBody @RequestMapping("/jsonBean") public StuModel jsonBean() throws InterruptedException{ StuModel stuModel = new StuModel(); stuModel.setStuName("张三"); stuModel.setAge(25); return stuModel; } @ResponseBody @RequestMapping("/listJson") public List List StuModel stuModel = new StuModel(); stuModel.setStuName("张三"); stuModel.setAge(25); StuModel stuModel1 = new StuModel(); stuModel1.setStuName("李四"); stuModel1.setAge(25); list.add(stuModel); list.add(stuModel1); return list; } ajax请求时如何传递参数 1.问号传参 2.获取form表单中所有参数 给form表单设置一个id 然后使用serialize方法获取 22.(重要) 一个的执行顺序 1.在Handler执行之前会先执行的preHandle方法 如果preHandle返回true那么会执行Handler,然后执行postHandle方法,和 方法 如果返回false,请求结束,不会执行的后续两个方法 多个的执行顺序 执行Handler之前,按照配置文件的顺序 执行每个的preHandle方法,如果所有的preHandle方法返回都是true,那么将执行Handler,然后倒序执行postHanle和 afterCompletion方法 按顺序执行所有的preHanle,如果第一个preHandle返回true,那么将执行后续的preHandle 如果其中一个的preHandle返回了false 那么将倒序执行除自己()以外的其他的afterCompletion 怎么实现一个自定义的 1.实现HandlerInterceptor接口 2.实现接口的三个方法 3.在SpringMvc配置文件中 进行配置 /** * 如果要自定义一个 * 1.需要实现HandlerInterceport接口 * 是在Handler之前执行 * 过程: * 1.preHandle方法会在Handler之前执行 * 1.1如果preHandle方法返回true,那么程序将继续向下执行,正常执行Handler * 1.2如果返回false,那么将不执行Handler * 2.postHandle方法会在Handler执行完之后执行 * 3.afterCompletion渲染视图之前执行 * @author muty * */ public class FirstInterceptor implements HandlerInterceptor{ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("执行了afterCompletion"); } @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub System.out.println("执行了postHandle"); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { //检测登录 //从session获取登录信息,如果为空,则证明没有登录,需要到登录页面 StuModel stuModel = (StuModel)request.getSession().getAttribute("user"); if(stuModel == null){ //跳转到登录页面 // response.sendRedirect("/WEB-INF/login.jsp"); response.sendRedirect("/SpringMvc_04/tologin"); return false; }else{ //如果不为空 ,则正常进入到处理器 return true; } } } 23.异常处理(熟悉) 在SpringMvc中处理异常方式有3种 注意:处理的异常是java中的异常,是在处理器运行过程中发生的异常,比如,空指针,数组越界或者已定义的异常,不能处理类似404这样的东西。 方式1:配置的方式 1.定义一个自定义异常的类,创建一个class继承Excpetion 2.在SpringMvc配置文件中配置 异常解析器 3.创建一个处理器,让他发生异常,测试结果 @RequestMapping("/exceptionTest") public String exceptionTest() throws Exception{ String abc = "abc"; if(abc.equals("abc")){ // throw new MyException("这是我的异常"); throw new NullPointerException(); } return ""; } 4.在错误页面将异常信息显示出来 这是自定义异常页面 ${ex.message} 方式2: 1.创建一个类,实现HandlerExceptionResolver接口 2.然后实现接口的方法 public class ExceptionHandler implements HandlerExceptionResolver{ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse reponse, Object arg2, Exception ex) { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("ex", ex); if(ex instanceof MyException){ System.out.println("使用的是代码方式"); modelAndView.setViewName("my_error"); }else{ System.out.println("使用的是代码方式"); modelAndView.setViewName("error"); } return modelAndView; } } 3.将该类存入容器中,存入方式两种 1.注解,2.通过bean标签配置 方式3: 1.创建了一个基础类 2.在基础类中创建了一个处理异常的方法 public class BaseController { /** * @ExceptionHandler注解 * 把他当做一个Handler * 但是不要主要去访问 * 发生异常时会自动进行调用 * 注意: * 不能使用ModelMap * 要使用原生的request * @return */ @ExceptionHandler public String expHandler(Exception ex, HttpServletRequest request){ request.setAttribute("ex", ex); if(ex instanceof MyException){ System.out.println("基类处理异常"); return "my_error"; }else{ System.out.println("基类处理异常"); return "error"; } } } 3.需要进行异常处理的Controller只需要继承该基础类 这几种方式的优先级: 优先使用的是 跟Controller相关的,基础类的方式 其次量种方式,哪一种配置在前,哪一种优先被使用 24.@RequestBody注解(熟悉) /** * RequestBody注解 * 如果要使用RequestBody注解来接收json类型的请求参数 * 那么在请求时必须注意如下几点 * 1.请求要使用ajax * 2.请求方式要为post * 3.请求参数 要是一个json格式的字符串 * 要么使用单引号 将 json对象 引起来 * 要么调用JS中的方法,将json对象转换为字符串 * 4.要设置contentType属性为 application/json * 5.使用实体类接收参数,实体类前面要加上@RequestBody注解 * 6.要导入jackson的3个jar包 */ @RequestMapping("/requestBody") public String requestBody(@RequestBody StuModel stuModel){ System.out.println(stuModel); return ""; } @RequestMapping("/requestBodyList") public String requestBodyList (@RequestBody List System.out.println(models); return ""; } function requestBody(){ $.ajax({ url:"/SpringMvc_05/requestBody", //1.请求方式必须是post type:"post", //2. 方式1.创建出的json对象要使用单引号括起来 // 方式2.调用JS中一个方法JSON.stringify data:'{"stuName":"张三北京"}', // data:JSON.stringify( // {"stuName":"张三北京"}), //3.如果要发送json类型的参数,要设置contentType contentType:"application/json", success:function(data){ } }) } function requestBodyList(){ var array = new Array(); var stu1 = {"stuName":"张三","age":25,"address":"北京"}; var stu2 = {"stuName":"李四","age":99,"address":"上海"}; array.push(stu1); array.push(stu2); $.ajax({ url:"/SpringMvc_05/requestBodyList", type:"post", data:JSON.stringify(array), contentType:"application/json", success:function(data){ } }) } 25.FlashMap(重定向时传递数据)(熟悉) /** * flashMap * 以重定向的方式定位到另外一个处理器 * 并且携带一些 参数(attribute) * 场景: * 使用重定向的方式,向另外一个处理器传递 实体类,或数据集合 或者其他类型的attribute * 用法: * 在Handler方法的入参处 声明RedirectAttributes对象 * addAttribute 在执行时会将传递的参数 拼接到返回路径后(以问号的形式) * addFlashAttribute 会将参数隐藏(推荐) */ @RequestMapping("/testRedirect") public String testRedirect(RedirectAttributes redirectAttributes){ StuModel stuModel = new StuModel(); stuModel.setAddress("北京"); stuModel.setStuName("张三"); redirectAttributes.addFlashAttribute("stu",stuModel); return "redirect:/doRedirect"; } /** * 获取重定向传递过来的实体类 * 注意: * 接收重定向过来的参数,不能使用普通方式 @RequestParam注解,实体类接收参数等 * 要通过flashMap来获取参数 */ @RequestMapping("/doRedirect") public String doRedirect(HttpServletRequest request){ Map RequestContextUtils.getInputFlashMap(request); StuModel stuModel = (StuModel)flashMap.get("stu"); System.out.println(stuModel); return ""; }下载本文
Hello Spring Mvc
request中的属性${name}
session中的属性${age}
这是一个自定义视图
");