SpringMvc学习文档
- 格式:docx
- 大小:155.46 KB
- 文档页数:28
SpringMvcDispatcherServlet 核心控制器Controller 控制器Handler 处理器1.搭建SpringMvc(了解)1.将相关jar包导入项目2.配置web.xml文件<!--如果你要使用SpringMvc的话1.需要配置核心控制器默认加载/WEB-INF/servlet名字-servlet.xml加载过程:1.tomcat启动,加载web.xml文件2.加载核心控制器2.1.会为核心控制器中的一个变量赋值3.根据所配置的路径加载SpringMvc主配置文件3.1.加载SpringMvc主配置文件--><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--初始化参数--><init-param><!--不要修改!!指定SpringMvc主配置文件存放的路径告诉SpringMvc去哪加载配置文件--><param-name>contextConfigLocation</param-name><!--具体路径classpath 表示src--><param-value>classpath:springMvc.xml</param-value></init-param><!-- 加载顺序 tomcat启动时自动加载数字越小越优先加载 --><load-on-startup>1</load-on-startup></servlet><!-- 为核心控制器配置访问路径 --><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-cl ass><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>3.配置SpringMvc主配置文件<!--自动扫描Ioc容器base-package 写的一个包的路径会去扫描路径下的所有类扫描的作用:会将所有带注解的类,装进ioc容器service,compent,Repository,controller作用:能够让带有controller注解的类被扫描到,并且存入容器,让其生效生效:controller可以进行工作(接收和处理http请求) --><context:component-scanbase-package="com.controller"/>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主配置文件中,配置视图解析器<!-- 视图解析器 --><bean id="jspViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolve r"><!--前缀指定的是JSP页面存放的位置只有存放在这个位置的JSP文件,Handler才能返回--><property name="prefix"value="/WEB-INF/jsp/"/><!-- 后缀指定的是视图的类型 --><property name="suffix"value=".jsp"/></bean>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.@RequestPara m注解(重要)/*** @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* <form>* <input type="text" name="stuName" />* <input type="text" name="address" />* submit* </form>*/@RequestMapping("/testParamBean")public String testParamBean(StuModel stuModel){System.out.println(stuModel);return"";}<a href="/SpringMvc_01/my/testParamBean?age=26&sex=男">a标签传参用实体类接收</a><!-- form表单提交用实体类接收 --><form action="/SpringMvc_01/my/testParamBean"method="post"><input type="text"name="stuName"/><input type="text"name="address"/><input type="submit"value="提交"/></form>8.设置请求时的编码方式(了解)在web.xml文件中增加配置<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-cl ass><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>9.使用Servlet Api(重要)/*** 在Handler中使用Servlet API* 场景:* a标签--查询所有学生* 向Servlet发起请求* 1.到数据库查询所有学生-- List<实体类>* 2.将数据集合传递到JSP request.setAttribute()* 3.使用转发的形式跳转到列表页面的JSP* 4.JSTL 进行循环显示数据 <c:forEach>* 列表页面* 用法:* 1.如果需要使用request对象或者response对象或者其他Servlet对象 * 那么只需要在Handler方法的入参处传递即可* 注意:* 不要使用request进行跳转******/@RequestMapping("/testServlet")public String testServlet(HttpServletRequest request,HttpSession session){request.setAttribute("name", "张三");session.setAttribute("age", 25);return"hello";}<body><h1>Hello Spring Mvc</h1><h1>request中的属性${name}</h1><h1>session中的属性${age}</h1></body>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)(熟悉)/*** /news/detail/24321* /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中配置请求转换过滤器<!-- POST 请求转换过滤器选择性配置如果你需要你就配置不需要就不配置 --><filter><filter-name>httpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-cla ss></filter><filter-mapping><filter-name>httpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>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方法里//${}Map<String,Object> map = new HashMap<String,Object>();map.put("name", "张三");modelAndView.addAllObjects(map);//一个参数,将一个对象存入request ?String address = "北京";modelAndView.addObject(address);String add = "上海";modelAndView.addObject(add);//两个参数,对应key和valuemodelAndView.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<String,Object> map){map.put("data", "这是map中的数据");return"hello";}17.@SessionAttribute s注解(了解)/*** 向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**/@Componentpublic class MyView implements View{/*** 设置视图类型*/@Overridepublic String getContentType() {return"text/html";}/*** 视图内容*/@Overridepublic void render(Map<String, ?> arg0, HttpServletRequest request, HttpServletResponse response) throws Exception {//设置编码格式response.setHeader("Content-type", "text/html;charset=UTF-8");response.setCharacterEncoding("UTF-8");response.getWriter().print("<h1>这是一个自定义视图</h1>");}}<!-- 如果使用了自定义视图,需要配置自定义的视图解析器 --><bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <!--视图解析器的使用顺序,order的值越小越被优先使用默认值为Integer的最大值 Integer.MAX_VALUE--><property name="order"value="1"></property></bean>/*** 返回自定义视图* 如果使用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.properties2.在SpringMvc中配置国际化资源管理器<!-- 配置国际化资源管理器 --><bean id="messageSource"class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename"value="i18n"></property> </bean>3.编写Handler跳转到一个国际化的JSP4.JSP中需要导入标签库<%@taglib prefix="fmt"uri="/jsp/jstl/fmt"%> 这个标签库需要导入JSTL相关jar包在JSP中使用标签获取资源文件中的键值对<fmt:message key="username"></fmt:message><fmt:message key="password"></fmt:message>5.通过切换浏览器语言来实现国际化方式二:通过点击链接实现国际化1.在SpringMvc配置文件中增加配置<!-- 方式2,需要配置国际化资源管理器和拦截器 --><!-- 配置资源解析器 --><bean id="localeResolver"class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> </bean><!-- 配置资源拦截器 --><bean id="localeChangeInterceptor"class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean><!-- 配置拦截器拦截哪些处理器 --><mvc:interceptors><!-- 代表了一个拦截器 --><mvc:interceptor><!-- 拦截的路径 /** 代表拦截所有请求 --><mvc:mapping path="/**"/><ref bean="localeChangeInterceptor"/></mvc:interceptor></mvc:interceptors>2.在webcontent下新建test.jsp,在jsp中放置两个a标签<a href="/SpringMvc_03/testLocale?locale=zh_CN">中文</a><a href="/SpringMvc_03/testLocale?locale=en_US">英文</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<MultipartFile><!-- 文件上传解析器 --><bean id="multipartResolver"class="monsMultipartResolver"> <!-- 文件上传的最大字节数 b --><property name="maxUploadSize"value="10000000"/></bean><!-- 文件上传表单 --><form action="/SpringMvc_03/uploadFile"method="post"enctype="multipart/form-data"><input type="file"name="file"/><input type="submit"value="上传"></form>@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<StuModel> listJson(){List<StuModel> list = new ArrayList<StuModel>();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方法2.如果preHandle返回true那么会执行Handler,然后执行postHandle方法,和afterCompletion方法3. 如果返回false,请求结束,不会执行拦截器的后续两个方法多个拦截器的执行顺序1.执行Handler之前,按照配置文件的顺序执行每个拦截器的preHandle方法,如果所有的preHandle方法返回都是true,那么将执行Handler,然后倒序执行postHanle和afterCompletion方法2.按顺序执行所有拦截器的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{@Overridepublic void afterCompletion(HttpServletRequest arg0,HttpServletResponse arg1, Object arg2, Exception arg3)throws Exception {System.out.println("执行了afterCompletion");}@Overridepublic void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {// TODO Auto-generated method stubSystem.out.println("执行了postHandle");}@Overridepublic 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;}}}<!-- 配置拦截器 --><mvc:interceptors><mvc:interceptor><!--mvc:mapping配置需要让拦截器拦截哪些请求/** 代表拦截所有请求必须要写这个标签--><mvc:mapping path="/**"/><!--mvc:exclude-mapping配置不拦截哪些请求优先级要高于拦截的请求--><mvc:exclude-mapping path="/tologin"/><mvc:exclude-mapping path="/dologin"/><mvc:exclude-mapping path="/js/**"/><!--配置拦截器是哪一个具体的类--><bean class="com.interceptors.FirstInterceptor"/></mvc:interceptor></mvc:interceptors>23.异常处理(熟悉)在SpringMvc中处理异常方式有3种注意:处理的异常是java中的异常,是在处理器运行过程中发生的异常,比如,空指针,数组越界或者已定义的异常,不能处理类似404这样的东西。