• SpringMVC基础


    讲义链接

    [csdn比较好的博客

    [spring官网](https://blog.csdn.net/Augenstern_QXL/article/details/119205766)

    ssm框架中,从这里开始就要创建webapp的模板啦

    1. 什么是SpringMVC

    • 它是基于MVC开发模式的框架,用来优化控制器controller。
    • 它是Spring的一个模块,专门做web开发的
    • 它也具备IOC和AOP.

    SpringMVC:是基于spring的一个框架, 实际上就是spring的一个模块, 专门是做web开发的。可理解为是servlet的一个升级

    web开发底层是servlet,springmvc框架是在servlet基础上面加入一些功能,让你做web开发方便。

    • Spring是容器,能够通过ioc技术管理对象,使用, 或注解@Component, @Repository, @Service, @Controller。

    • SpringMVC创建对象, 放入到容器中(SpringMVC容器), springmvc容器中放的是控制器对象

      sping创建 Service, Dao,工具类对象(SM整合中 spring替mybtis创建对象)

    我们要做的是 使用@Contorller创建控制器对象, 把对象放入到springmvc容器中, 把创建的对象作为控制器使用。这个控制器对象能接收用户的请求, 显示处理结果,将其当做是一个servlet使用。

    使用@Controller注解创建的是一个普通类的对象, 不是Servlet(servlet类需要继承Servlet,控制器对象并没有继承Servlet,故其不是servlet)。 springmvc赋予了控制器对象一些额外的功能。

    web开发底层是servlet, springmvc中有一个对象是Servlet : DispatcherServlet(中央调度器)
    DispatcherServlet: 负责接收用户的所有请求, 用户把请求给了DispatcherServlet, 之后DispatcherServlet把请求转发给我们的Controller对象, 最后是Controller对象处理请求。如下:

    index.jsp-----DispatcherServlet(Servlet)----转发,分派给—Controller对象(@Controller注解创建的对象)
    main.jsp MainController
    addUser.jsp UserController

    什么是MVC?

    它是一种开发模式,它是模型视图控制器的简称。所有的web应用都是基于MVC开发.

    M:模型层。包含实体类,业务逻辑层(Service),数据访问层(Dao)【ModelAndView】

    V:视图层。html,javaScript,vue等都是视图层,用来显现数据【View】

    C:控制器Controller),它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件(Aciton)【controller】

    image-20240129071127437

    springMVC是管理用户请求的工具

    image-20230704201014907

    SpringMVC框架的优点

    1. 轻量级,基于MVC的框架

    2. 易于上手,容易理解,功能强大

    3. 它具备IOC和AOP。作为Spring框架一部分,能够使用Spring的IOC和AOP

    4. 完全基于注解开发。在Controller, Service, Dao 都可以使用注解。方便灵活。

      使用@Controller 创建处理器对象,

      ​ @Service 创建业务对象,

      ​ @Autowired 或者@Resource 在控制器类中注入 Service,在Service 类中注入 Dao。

    SSM框架

    • mybatis处理数据访问层
    • springMVC优化控制器
    • spring负责整合mybatis和springMVC

    image-20231119174719933

    springMVC优化的方向

    image-20231119180346575

    2. 基于注解的web项目

    大体步骤:

    image-20240127144620413
    项目1

    项目1

    项目结构:

    image-20230704131518666
    1. 新建项目(配项目的jdk,配本地maven)然后通过Maven创建webapp模板。【具体步骤看Maven笔记第四节:通过Maven创建Web项目:maven

    2. 修改目录,添加缺失的src\test, main\java, main\resources test\java, test\resources(两套)。并修改目录属性【改颜色,maven笔记中有记载,新版本idea目录属性无需手动修改】

    3. 修改pom.xml文件。

      1. 删除pom.xml文件中 两行

      2. 中的中的jdk版本号改为1.8(高版本idea没有这一项)

      3. 添加依赖:在<\dependencies>中添加SpringMVC的依赖,添加Servlet的依赖。上依赖

        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.2.5.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.1.0version>
        dependency>
        
        <dependency>
            <groupId>javax.servlet.jspgroupId>
            <artifactId>javax.servlet.jsp-apiartifactId>
            <version>2.3.3version>
        dependency>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
      4. 标签(资源文件指定)按照自己的需求进行改写(MyBatis里面有讲)

        <build>
            <resources>
                <resource>
                    <directory>/src/main/javadirectory>
                    <includes>
                        <include>**/*.xmlinclude>
                        <include>**/*.propertiesinclude> 
                    includes>	
                resource>
                <resource>
                    <directory>/src/main/resourcesdirectory>
                    <includes>
                        <include>**/*.xmlinclude>
                        <include>**/*.propertiesinclude> 
                    includes>	
                resource>        
            resources>
        build>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
    4. 点击maven工程目录,点击刷新按钮进行刷新

    5. 删除web.xml文件,新建web.xml(WEB-INF目录下)

    6. 在web.xml文件中注册springMVC框架(所有的web请求都是基于servlet的) 【重点】

      
      
      
      <servlet>
          <servlet-name>springmvcservlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
          
          
          
          <init-param>
              
              <param-name>contextConfigLocationparam-name>
              
              <param-value>classpath:springmvc.xmlparam-value>
          init-param>
          
          
          <load-on-startup>1load-on-startup>
          
      servlet>
      <servlet-mapping>
          <servlet-name>springmvcservlet-name>
          
          <url-pattern>*.actionurl-pattern>   //拦截所有以.action结尾的请求  / :拦截所有请求
      servlet-mapping>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76

      在web.xml文件中注册SpringMVC框架的核心对象DispatcherSerlvet。

      1. DispatcherSerlvet叫做中央调度器,是一个servlet,它的父类继承自HttpServlet
      2. DispatcherSerlvet也叫做前端控制器(front controller)
      3. DispatcherSerlvet作用
        1. 负责接收用户提交的请求,并根据请求的路径分派给对应的控制器对象进行处理,并把请求的处理结果显示给用户
        2. 创建容器对象WebApplicationContext;读取配置文件,进而创建控制器对象

      中央调度器的全限定性类名在导入的 Jar 文件 spring-webmvc-5.2.5.RELEASE.jar 的第一个包org.springframework.web.servlet下可找到。

      classpath:springmvc.xml表示从类路径下加载SpringMVC的配置文件。

      指定拦截以.action结尾的请求,交给核心处理器DispatcherServlet处理。

    7. 添加springmvc.xml配置文件(在main\resources目录下新建springmvc.xml文件),指定包扫描,添加视图解析器(下图中的ViewResolver) 上配置

      
      <context:component-scan base-package="com.bjpowernode.controller"> 
      context:component-scan>
       		
      
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
           
           <property name="prefix" value="/admin/">property> //将来会在 webapp下创建admin目录
           
           <property name="suffix" value=".jsp">property> //将来会创建的 webapp下的admin目录下的.jsp文件
      bean>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25

      SpringMVC框架为了避免对于请求资源路径与扩展名上的冗余,在视图解析器InternalResouceViewResolver 中引入了请求的前辍与后辍。而action中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接。

      context:component-scan:用来进行包扫描,这里用于指定@Controller注解所在的包路径。

    8. 在webapp目录下新建admin目录,在admin目录下新建main.jsp页面,删除webapp/index.jsp页面,并新建index.jsp。发送请求给服务器

      //main.jsp
      

      main....

      • 1
      • 2
      // index.jsp带.action是为了让第七步中配置的拦截器拦截到
      访问服务器
      
      • 1
      • 2
    9. 开发 控制器(能处理请求的都是控制器),它是一个普通的类,不用继承和实现接口。类中的每个方法就是一个具体的action控制器(没有像老杜Servlet教程中那样继承HttpServlet,实现doGet,doPost方法,但现在的类比之前学的更加牛逼,牛逼的点在下面注释中已给出)

      // 能处理请求的都是控制器,DemoAction称为 后端控制器(back controller)
      
      //交给Spring去创建对象,并将创建好的对象放入到springMVC容器中,所以要在springmvc.xml中配置组件扫描器
      @Controller  
      public class DemoAction {
          /**
      	     * 以前的Servlet的规范:
      	     * protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
      	     *	
      	     * action中所有的功能实现都是由方法来完成的
      	     * action方法的规范:
      	     * 			1)访问权限是public
      	     * 			2)方法的返回值任意
      	     * 			3)方法名称任意
      	     * 			4)方法可以没有参数,如果有可是任意类型
      	     * 			5)要使用@RequestMapping注解来声明一个访问的路径(名称)
      	     *
      	     */
          // 该注解更多内容见第4节
          @RequestMapping("/demo") //这个注解中的"/demo"由index.jsp中超链接中的"/demo.action"确定了。即这里也可写 /demo.action,但没有必要
          public String demo(){
              System.out.println("服务器被访问到了.......");
              return "main";  //可以直接跳到/admin/main.jsp页面上(请求转发,见第7节),底层用的是request对象的请求转发。request.getRequestDispatcher("/show.jsp")。forward(request, response);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
    10. 添加tomcat进行测试功能【见老杜Servlet笔记中:在集成开发环境中开发servlet 一节】

    springmvc执行过程源代码分析
    1. tomcat启动,创建容器的过程

      • 通过load-on-start标签指定的1,创建DispatcherServlet对象,

      • DisaptcherServlet它的父类是继承HttpServlet的, 它是一个serlvet, 在被创建时,会执行init()方法。在init()方法中:

        //创建springmvc容器对象;读取配置文件,通过包扫描创建controller对象
        WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
        //把容器对象放入到ServletContext中
        getServletContext().setAttribute(key, ctx);
        
        • 1
        • 2
        • 3
        • 4

        上面创建容器作用: 创建@controller注解所在的类的对象, 即创建MyController对象,这个对象放入到 springmvc的容器中, 容器是map,类似 map.put(“DemoAction”, DemoAction对象)

    2. 请求的处理过程

      1. 执行servlet的service()方法

        protected void service(HttpServletRequest request, HttpServletResponse response)
            
        protected void doService(HttpServletRequest request, HttpServletResponse response)
        
        DispatcherServlet.doDispatch(request, response){
        	调用 DemoAction 的 demo方法
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7

        doDispatch:springmvc中DispatcherServlet的核心方法, 所有的请求都在这个方法中完成的。

    添加tomcat时遇到的坑:

    添加tomcat的步骤:

    • IDEA工具右上角,绿色小锤子右边有一个:Edit Configuration

    • 左上角加号,点击Tomcat Server --> local

    • 在弹出的界面中设置服务器Server的参数(基本上不用动)

      • 点击appliction server 一栏中的configuretion选项,

        1.将tomcat home ,tomcat base directory配置为要使用的tomcat版本(填入其安装路径即可)

        2.将libraries中的Class中的jar包替换成要使用版本的jar包(sevlet-api.jar jsp-api.jar)

        image-20230703213829455

    • 在当前窗口中有一个Deployment(点击这个用来部署webapp),继续点击加号,部署即可(选名字中带有exploded的那个进行部署)。

    • 修改 Application context为:/

    • 启动tomcat,如果启动失败,出现下列报错

      • java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet

      • 问题就是在于Maven Dependencies果然没有配置到WEB-INF/lib下,包没有导进去,缺少lib依赖所引起的报错!( 输出时,target WEB-INF目录下缺少lib)

      • 解决方法:

        image-20230703214229364

        image-20230703214317989

    设置完成之后重启Tomcat即可

    解决办法2:

    1. 在IDEA中点击File > Project Structure > Artifacts >选中项目(例如seckill:war exploded), 在右侧Output Layout右击项目名,选择Put into Output Root

    2. 执行后,查看WEB-INF,此时在WEB-INF下新增了lib目录,里面是项目引用的jar包,点击OK

    3. 重启tomcat测试

      image-20230704080226941

    3. 分析web请求

    web请求执行的流程(所有的请求都要通过servlet进行处理),但SpringMVC的处理器(controller类)是一个普通的类,故要通过DispatcherServlet处理数据
    核心处理器:DispatcherServlet
    index.jsp<--------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法(不是servlet)
    one.jsp <--------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法

    DispatcherServlet要在web.xml文件中注册才可用.(这就解释了第二节中第七步的操作)

    springMVC执行流程

    image-20240127140323619

    DispatcherServlet中的核心方法doDispatch(),所有的请求都在这个方法中完成的。

    ApplicationContext ac = new ClassPathXmlApplication("bean.xml");
    StudentService service = (StudentService)ac.getBean("service")
    
    • 1
    • 2

    springMVC内部请求的处理流程:也就是springMVC接收请求,到请求处理完成的过程

    1. 用户发起请求 some.do

    2. DispatcherServlet接收请求 some.do,把请求转交给处理器映射器(HandlerMapping)【DispatcherServlet的核心方法doDispatch()中进行处理】

      • 处理器映射器:springmvc框架中的一种对象
        • 框架把实现了 HandlerMapping接口 的类都叫做映射器(有多个)
          • 映射器返回处理器执行链对象:
            • HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
      • 处理器映射器作用
        • 根据请求,从springMVC容器对象中获取处理器对象(MyController controller = ac.getBean(“some.do”); )。【处理器对象:处理请求的控制器对象action】
        • 把找到的处理器对象放到一个叫做 处理器执行链的类(HandlerExecutionChain) 中保存
          • HandlerExecutionChain
            • 保存着处理器对象(MyController,保存在变量Object handler中)
            • 保存着项目中所有的拦截器(保存在 List interceptorList)
          • doDispatch()方法中调用,获取 处理器执行链类对象
            • HandlerExecutionChain mappedHandler = getHandler(processedRequest);
      1. DispatcherServlet 把 2中的 HandlerExecutionChain 中的处理器对象交给了处理器适配器对象(多个)

        • 处理器适配器:springMVC框架中的对象,需要实现HandlerAdapter接口
        • 处理器适配器作用
          • 执行处理器方法(调用 MyController类中的方法,得到返回值ModelAndView)
            • ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
        • 中央调度器中的doDispatch()方法
          • 调用适配器
            • HandlerAdapter ha = getHandlerAdapter(mapperHandler.getHandler()));
          • 执行处理器方法,返回ModelAndView对象
            • mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
      2. DispatcherServlet 把 3中获取到的 ModelAndView交给视图解析器对象

        • 视图解析器:springMVC中的对象,需要实现ViewResoler接口(可以有多个)

        • 视图解析器作用

          • 组成视图的完整路径,使用 前缀,后缀。
          • 创建View对象
        • View是一个接口,表示视图的。

          • 在框架中,jsp,html表示string表示,而是使用 View 和 它的实现类表示视图。不同的文件用不同的实现类来表示

          • InternalResourceView:视图类,表示jsp文件。视图解析器会创建 InternalResourceView类对象。这个对象里面有一个属性:url=/WEB-INF/view/show.jsp。展示了视图所在的路径

            • builderView()方法

              • 这个属性url是在其父类UrlBasedViewResolver的builderView()方法中赋值的

                view.setUrl(getPrefix() + viewName + getSuffix());
                
                • 1

                其利用了 AbstractUrlBasedView类的 url属性

      3. DispatcherServlet 把 4步骤中创建的View对象获取到,调用View类自己的方法,把Model放入到request作用域。执行对象视图的 forward。请求结束

    4. @RequestMapping注解详解

    • 此注解就是来映射服务器访问的路径,给浏览器html使用的。请求映射,作用是把一个请求地址和一个方法绑定在一起,一个请求指定一个方法处理。

    • 使用@RequestMapping修饰的方法叫做处理器方法或控制器方法。使用@RequestMapping修饰的方法是可以处理请求的,类似于servlet中的doGet,doPost

    • 个人理解:类似于servlet学的,在web.xml文件中使用,标签映射服务器访问servlet的路径。此注解就是简化了这一功能

    • @RequestMapping的属性和返回值

      • 属性

        • value:表示请求的uri地址的(demo.action)value可以省略,是一个数组类型
          • String类型,表示请求的uri地址(demo.action)
          • 值是唯一的,不能重复
          • 使用时,建议以 "/"开始
      • 位置

        • 方法上面
        • 类上面
      • 返回值

        • ModelAndView:表示本次请求的处理结果

          • Model:数据,请求处理完成后,要显示给用户的数据
          • View:视图,比如jsp等等
        • 代码演示:

          index.jsp: <a href="${pageContext.request.contextPath}/demo.action">发起demo.action请求</a>
          show.jsp:通过el表达式从request作用域中获取数据:${msg}
          
          
          @Controller  // 使用注解,一定要在springmvc.xml中添加包扫描
          public class MyController {
              @RequestMapping("/demo.action") // 等价于@RequestMapping("/demo")
              public ModelAndView demo(){  //相当于servlet中的doGet()方法 --》调service()请求处理
                  //处理demo.action请求了。此处看作service()方法调用处理完成了
                  // mv:保存数据 和视图信息,供底层框架使用
                  ModelAndView mv = new ModelAndView();
          
                  // 添加数据,框架在请求的最后把数据放入到request域中
                  // request.setAttribute("msg", "欢迎光临");
                  mv.addObject("msg", "欢迎光临");
          
                  //1. 指定视图,指定视图的完整路径:此时show.jsp在webapp目录下,用户能直接访问show.jsp。未指定视图解析器
                  // 框架对视图执行的forward操作,request.getRequestDispatcher("/show.jsp")。forward(request, response);
                  mv.setViewName("/show.jsp"); 
          
                  //2. 将 show.jsp移到 /WEB-INF/admin目录下,在/WEB-INF目录下的文件用户不能直接访问。未指定视图解析器。
                  mv.setViewName("/WEB-INF/admin/show.jsp");   
                  /*
                  	如果有多个视图:mv.setViewName("/WEB-INF/admin/other.jsp")
                  	可以发现:参数中的前半截 /WEB-INF/admin/ 和 后半截 .jsp都是相同的,
                  为了简化开发,便可以使用视图解析器,在视图解析器中配置前后缀,简化此处的开发,如3
                  
                  */
          
                  //3. 当在springmvc.xml中配置了视图解析器后,可以使用逻辑名称(文件名),指定视图
                  // 框架会使用视图解析器的前置 + 逻辑名称 + 后缀 组成完整路径,这里就是字符连接操作
                  // /WEB-INF/admin/ + show + .jsp 视图解析器为我们拼接前后缀,我们提供页面的文件名即可
                  mv.setViewName("show");
          
                  // 返回mv,这个mv中保存了数据和视图信息,框架会使用这个mv中的信息
                  return mv;
              }
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
        • ModelAndView 这个对象,不仅能存放数据,而且能存放请求转发到的页面的信息。

          这样就代替了servlet中使用 HttpServletRequest对象 来存放数据,请求转发到页面。

          但是它的底层也是用request对象存放数据,进行请求转发,只不过框架给我们封装好了罢了。

    springmvc请求的处理流程
    1. 用户发起: demo.action

    2. tomcat接收请求(tomcat读取web.xml,通过url-pattern标签知道 *.action的请求是给DispatcherServlet进行处理的)

    3. DispatcherServlet(根据springmvc.xml配置,知道 demo.action请求对应着控制器对象的demo()方法)

    4. DispatcherServlet把demo.action转发给MyController.demo()方法

    5. 框架执行demo(),把得到ModelAndView进行处理, 转发到show.jsp

    上面的过程简化的方式
    demo.action—》DispatcherServlet—》DemoAction

    image-20240127220810630

    将.do后缀换成.action,保持内容的连贯性

    项目1

    1)此注解可加在方法上,是为此方法注册一个可以访问的名称(路径)

    @RequestMapping("/demo") // 等同于@RequestMapping("/demo.action")  该方法处理demo.action请求
    public String demo(){
        System.out.println("服务器被访问到了.......");
        return "main";  //可以直接跳到/admin/main.jsp页面上
    }
    
    前端请求:
    <a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2)此注解可以加在类上,相当于是包名(提供虚拟路径), 区分不同类中相同的action的名称

    @Controller  
    @RequestMapping("/user")  // 放在类上,所有请求地址的公共部分,叫做模块名称。前端路径得带该名称
    public class DemoAction1 {
        @RequestMapping("/demo")
        public String demo(){
            System.out.println("user服务器被访问到了.......");
            return "main";  //可以直接跳到/admin/main.jsp页面上
        }
    }
    
    前端请求:
    <a href="${pageContext.request.contextPath}/user/demo.action">访问服务器</a>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    项目2

    项目2(搭建项目的流程请参看项目1,此处不在赘述)

    3)此注解可区分get请求和post请求:利用 该注解的method属性指定请求的方式,它的值是RequestMethod类枚举值。若不指定请求方式,前端发送任何请求,控制器都能够接收

    @Controller
    public class ReqAction {
        //value填写访问资源的名称,method填写 请求方式
        @RequestMapping(value = "/req",method = RequestMethod.GET)
        public String reqGet(){
            System.out.println("我是处理get请求的........");
            return "main";
        }
        @RequestMapping(value = "/req" ,method = RequestMethod.POST)
        public String reqPost(){
            System.out.println("我是处理post请求的........");
            return "main";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    //index.jsp
    
    //post==> get
    • 1
    • 2
    • 3
    • 4

    SpirngMVC优化的四项内容

    1. 提交数据到action:5种方式(第5节)
    2. action方法的返回值(第7节)
    3. 页面跳转的四种方式(第九节)
    4. 携带数据跳转

    image-20231119222855754

    5. 五种数据提交方式的优化(1,2,4)

    从前端传递的值,springmvc通过函数形参获取

    项目2

    1. 单个提交数据

    第4种方式 其实是对 这种方式的一个优化

    页面:

    form标签是专门用来请求后端的标签。

    action:写的就是springmvc提供的映射名称,即@RequestMapping(“/one”)中的名称。至于为什么要加.action

    后缀,这是因为在第二节注册springmvc框架的时候, *.action中指定了只拦截了

    以.action结尾的请求

    //index.jsp
    
    
    姓名:
    年龄:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    action(定义一个controller类,写如下方法):

    @Controller
    public class DataSubmitAction{
        //通过 “http://localhost:8080/项目名称/one  便可以执行one方法
        @RequestMapping("/one")
        //此处形参myname即表单中的myname,形参age对应表单中的age值
        //这里的形参必须和表单中的 name属性的值相同,否则的话不会进行自动注入(利用函数形参获取前端传递的值)
        // 处理器返回String--main表示逻辑视图名称,需要配置视图解析器
        public String one(String myname,int age){  // ===>自动注入,并且自动类型转换
            System.out.println("myname="+myname+",age="+age);
            return "main"; //main这个字符串 表达的是页面名称,回到main.jsp页面,底层是 请求转发request.getRequestDispatcher("/main.jsp")。forward(request, response);
        }
    }
    
    // 返回值是 String时,只进行了视图的转发,如何传递数据到 show.jsp ?  ==> 使用 HttpServletRequest对象 做函数形参,框架会自动赋值
        public String one(HttpServletRequest request, String myname,int age){ 
            request.setAttribute("name", myname);
            request.setAttribute("age", age);
          
            return "main";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    逐个接收请求参数:

    • 要求:
      • 控制器(处理器)方法的形参名 和 请求中参数名 必须一致。
      • 同名的请求参数赋值给同名的形参

    框架进行以下处理:

    1. 使用request对象接收请求参数

      String name = request.getParameter("myname");
      String age = request.getParameter("age");
      
      • 1
      • 2
    2. 框架通过 DispatcherServlet 调用 DataSubmitAction(控制器对象)的 one()方法

      调用方法时,按名称对应,把1中接收的参数赋给形参

      one(name, Integer.valueOf(age)); // myname=name, age=Integer.valueOf(age)

      框架会提供类型转换的功能,能把String转为 int,long,float,double等类型

    上面的代码在 类型转换 时会有一点问题

    1. 当不传入年龄时,框架用 request对象接收age,得到的值是 null,在进行第2步的类型转换时会失败(null ===> int), 报400错误

      所以DataSubmitAction的one方法中的 age形参的类型最好是包装类型:例如 Integer。

      这样就不会出现 null值无法转换 的情况

    2. 当你的年龄传入的是无法进行类型转换的字符串时,后台会发出警告,记录到日志中。如:

      Failed to convent value of type 'java.lang.String' to required type 'int'
      
      • 1
    3. 即当你传入的参数不合法时,one方法不会被执行

    4. 400状态码是客户端错误,表示提交请求参数过程中,发送了问题

    5. post请求中文乱码:使用过滤器 CharacterEncodingFilter

    2. 对象封装提交数据

    在提交请求中,保证请求参数的名称与实体类中成员变量的名称一致,则可以自动创建对象,则可以自动提交数据,自动类型转换,自动封装数据到对象中.

    实体类:(还要提供无参构造器,有参构造器,get,set方法 以及重写toString方法。快捷键:alt + Insert,在com.bjpowernode包下创建,不要在com.bjpowernode.controller包下创建,要见名知意)

    // 保存 请求 中参数值 的一个普通的类
    public class Users {
        //实体类中定义的 成员变量的名称 必须跟下面 页面(即表单)中的 name属性的值相同,才能在action中注入
        private String uname;
        private int uage;
        //无参构造器,有参构造器,get,set方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    页面:(post请求乱码问题第6节解决)

    //index.jsp
    // get请求输入中文不会乱码,但post请求输入中文姓名会产生乱码(第6节有解决方案:使用过滤器)。表单默认是get请求,超链接和url中用?携带数据也是get请求	
    
    姓名:
    年龄:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    action(定义一个controller类,可用第一步中的,写如下方法):

    /*
    	处理器方法形参是java对象,这个对象的属性名和请求中的参数名一样
    	框架会创建 形参的对象实例,并给该实例的属性赋值,赋值是用类中提供的setXXX()方法
    */
    @RequestMapping("/two")
    public String two(Users u){
        System.out.println(u);
        System.out.println(u.getName())
        return "main";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    3. 动态占位符提交

    ​ 仅限于超链接或地址拦提交数据。它是一杠一值,一杠一大括号,使用注解@PathVariable来解析.

    页面:

    王鹤在springboot中所讲的 RESTful风格 表示的url地址

    动态提交 
    
    • 1

    以前传输数据,通过 ?

    <a href="${pageContext.request.contextPath}/three.action?name=”张三"&age=22>动态提交a> 
    
    • 1

    现在:

    ​ 在/three.action中通过“一杠一值”的方式传值

    action(定义一个controller类,可用第一步中的 写如下方法):

    //通过“一杠一大括号” 的方式,接收  “一杠一值”的方式传过来的值。
    //@RequestMapping注解里面的形参可以任意命名,但@PathVariable中的参数必须和其保持一致。当@RequestMapping注解里面的形参与函数形参名相同时,@PathVariable中可不要参数
    @RequestMapping("/three/{uname}/{uage}")
        public String three(
                @PathVariable("uname")  // ===> 用来解析路径@RequestMapping 中的请求参数
                String name,
                @PathVariable("uage")
                int age){
            System.out.println("name="+name+",age="+(age+100));
            return "main";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    4. 映射名称不一致@RequestParam

    提交请求参数名称(比如form表单中name属性的值)与控制器action中方法的形参的名称不一致,使用注解@RequestParam来解析【是第1种方法的拓展】

    页面:

    //index.jsp
    
    姓名:
    年龄:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    action(定义一个controller类,可用第一步中的,写如下方法):

    @RequestMapping("/four")
    public String four(
        /*
        	@RequestParam:逐个接收请求参数中,解决请求中参数名 和形参名 不一样的问题
        				属性:
        					1. value:请求 中参数的名称
        					2. required:是一个boolean,默认是true,表示 请求 中必须包含此参数,没有就						    		  会报错
                        位置:在处理器方法的形参定义的前面
          个人理解:该注解通过vale的值 接收 前端 请求发送来的同名参数,并将该值赋值给 控制器方法的形参       
        */
    	@RequestParam("name") // 专门用来解决名称不一致的问题(参数为form表单中 name属性的值)
    	String uname,
    	@RequestParam("age")
    	int uage){
    		System.out.println("uname="+uname+",uage="+(uage+100));
    		return "main";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    5. 手工提取数据(最早学的)

    页面:

    //index.jsp
    
    姓名:
    年龄:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    action(定义一个controller类,写如下方法):

    @RequestMapping("/five")
    public String five(HttpServletRequest request){
        String name = request.getParameter("name");
        int age = Integer.parseInt(request.getParameter("age")); //必须自己转换,上面的都是自动转换好的
        System.out.println("name="+name+",age="+(age+100));
        return "main";
    }   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    其他形参

    第10节有所提及

    控制器对象 的处理器方法 还可以包含以下4类形参,这些参数会在系统调用时由系统自动赋值,即程序员可以在方法内直接使用(回调函数)

    • HttpServletRequest

    • HttpServletResponse

      • 见此节第5小节
    • HttpSession

    • 请求中所携带的请求参数

      • 见此节1 和 2 小节

      这个如何理解?比如前端发出请求 http://localhost:8080/myweb/test.action?name=zhangsan

      其中 name=zhangsan就是请求中所携带的请求参数

      可以通过:request.getParameter(“name”); // zhangsan 获取到值

    6. 中文乱码解决方案------配置过滤器.

    在servelt中学习到的解决乱码问题的方法:使用request or response

    public void test(HttpServletRequest request
                     HttpServletResponse response){
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在web.xml文件中配置过滤器CharacterEncodingFilter,解决post请求乱码的问题(中文编码过滤器配置 建议放在web.xml文件首位)

    接下来就可以用第5节第2小节来测试一下

    个人小结:过滤器和监听器都是 从 spring-web 这个框架中导入的,这个框架在我们导入spring-webmvc的 时候就自动导入了。而且这两个都配置在web.xml文件中

    <filter>
        <filter-name>encodefilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        
        
        <init-param>
            <param-name>encodingparam-name>
            <param-value>UTF-8param-value>
        init-param>
        
        <init-param>
            <param-name>forceRequestEncodingparam-name>
            <param-value>trueparam-value>
        init-param>
         
        <init-param>
            <param-name>forceResponseEncodingparam-name>
            <param-value>trueparam-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>encodefilter-name>
         
        <url-pattern>/*url-pattern> 
    filter-mapping> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    tomcat10就没有上述中文乱码问题,值得注意的是,tomcat10后,servlet的包名改了,这个在老杜的servlet笔记中有讲

    7. action方法的返回值

    action方法即 controller类中所定义的方法

    1. String:

      • 处理器返回String–表示逻辑视图名称,一般搭配 视图解析器 使用

      • 客户端资源的地址。自动拼接 视图解析器 中配置的前缀和后缀,还可以屏蔽自动拼接字符串,可以指定返回的路径.

      • 在本笔记 第5节 所使用的方式

    1. Object:

      • 这个 Object对象可以是 Integer,String,自定义对象,Map,List等。但返回的对象不是作为视图,而是作为直接在页面显示的数据出现的

      • 返回 json 格式的对象,自动将对象或集合转为json。

        1. 使用的jackson工具进行转换,必须要在 pom.xml 中添加jackson依赖

        2. 需要在springmvc.xml中 配置注解驱动(在第3种方式中,我们需要手动把java对象转换成json,如今这个动作交由容器处理)

          <mvc:annotation-driven>mvc:annotation-driven>
          
          • 1
        3. 在处理器方法上使用@ResponseBody注解(在第3种方式中,需要通过形参 HttpServletResponse 获取PrintWriter对象 输出数据,而今只需要配置注解,让容器响应ajax请求)

      • springmvc处理器方法返回Object, 可以转为json输出到浏览器,响应ajax的内部原理

        1. 注解驱动。

          注解驱动 实现的功能是 完成java对象到json,xml, text,二进制等数据格式的转换。

          • 在加入到springmvc配置文件后, 会自动创建HttpMessageConverter接口的7个实现类对象,

            • 包括MappingJackson2HttpMessageConverter (该类使用jackson工具库中的ObjectMapper 实现java对象转为json字符串。只有配置了 注解驱动 才会创建该类的对象实例)
          • HttpMessageConverter接口:消息转换器。

            • 功能:定义了java转为json,xml等数据格式的方法。 这个接口有很多的实现类。这些实现类完成 java对象到json, java对象到xml,java对象到二进制数据的转换

            • 下面的两个方法是控制器类把结果输出给浏览器时使用的:

              • boolean canWrite(Class var1, @Nullable MediaType var2);

              • void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3)

                例如处理器方法
                    @RequestMapping(value = "/returnString.do")
                    public Student doReturnView2(HttpServletRequest request,String name, Integer age){
                    Student student = new Student();
                    student.setName("lisi");
                    student.setAge(20);
                    return student;
                }
                
                1)canWrite作用检查处理器方法的返回值,能不能转为var2所表示的数据格式。
                    检查student(lisi,20)能不能转为var2所表示的数据格式。比如此例中如果检查能转为json,canWrite返回true
                    MediaType:表示数据格式的, 例如json, xml等等
                
                2)write:把处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串
                
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6
                • 7
                • 8
                • 9
                • 10
                • 11
                • 12
                • 13
                • 14
      1. @ResponseBody注解

        放在处理器方法的上面, 通过HttpServletResponse获取PrintWriter对象输出数据,响应ajax请求的。

          - 一般用于ajax请求.
        
        
          - 在本笔记 第8节项目3中使用的方式
        
        • 1
        • 2
        • 3
        • 4
    2. void:

      • 无返回值,不能表示数据,也不能表示视图

      • 一般用于ajax请求。通过形参 HttpServletResponse 获取PrintWriter对象 输出数据,响应 ajax请求。但是这种方式还能简化,于是就有了 本节第2种方式处理ajax请求

      • ajax请求 服务器端返回的就是数据,和视图无关。这也解释了 第8节 中 为什么不用配置 视图解析器

    3. 基本数据类型

      • 用于ajax请求.
    1. ModelAndView

      • 返回数据和视图对象,现在用的很少。底层是将数据保存到request域中,利用request请求转发到视图

      • 在本笔记 第4节有所提及

    8. 完成ajax请求访问服务器,返回学生集合.

    理论部分见 第7节

    项目3

    项目3

    项目结构:

    image-20230704131709150

    前面的流程见第二节项目1

    1. 在pom.xml中<\dependencies>中继续添加jackson依赖(springmvc的依赖和servlet的依赖是必不可少的),并进行刷新。

      
      <dependency>
          <groupId>com.fasterxml.jackson.coregroupId>
          <artifactId>jackson-databindartifactId>
          <version>2.9.8version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    1. 删除web.xml文件,新建web.xml(WEB-INF目录下)

    2. 在web.xml文件中 注册springMVC框架(第二节 DispatcherServlet),添加中文编码过滤器(第六节 Filter)

    3. 在webapp目录下新建js目录, 添加jQuery函数库(资料下有一个jquery-3.3.1,将其复制到 js目录下)jquery

    4. 添加springmvc.xml配置文件(在main\resources目录下新建springmvc.xml文件),指定包扫描。

      • 不用添加视图解析器,因为处理的是ajax请求

      • 必须要添加注解驱动(专门处理ajax请求的),注意注解驱动所要导的包是以mvc结尾的,不要加载错了注解驱动

        
        <context:component-scan base-package="com.bjpowernode.controller"> 
        context:component-scan>
        
        
        <mvc:annotation-driven>mvc:annotation-driven>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
    5. 删除index.jsp页面,并新建index.jsp。在index.jsp页面上导入函数库

    6. 添加tomcat进行测试功能(见第二节)

    index.jsp内容如图:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Title
    <%--    导入jQuery的函数库 --%>
        
    
    
    


    访问服务器,返回学生集合
    等待服务器返回数据
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    创建学生类(新建一个包:com.bjpowernode.pojo,在其中创建学生类,未给出无参,有参构造器,get,set方法,toString方法)

    public class Student{ 
     	//因为index.jsp中用到了 stu.name,stu.age。所以创建的学生类必须和其保持一致
        //stu.name,stu.age调用了Student类的getName() 和 getAge()方法
    	private String name; 
    	private int age;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 在action上(controller包下的类com.bjpowernode.controller)添加注解@ResponseBody,用来处理ajax请求
    @Controller
    public class StudentListAction {
        @RequestMapping("/list")   //与index.jsp中 url中所写的请求保持一致	
        //解析ajax请求,一定要加@ResponseBody注解,并且要在springmvc中添加注解驱动(第5步)
        // 作用:把处理器方法返回的对象 转为 json后,通过 HttpServletResponse输出给浏览器
        /*
        	框架返回对象的处理流程:
        		1.框架会调用 ArrayList中每个类的 canWrite()方法,检测哪个				  HttpMessageConverter接口的实现类能处理 返回对象所属类型 的数据
    			  实现类:MappingJackson2HttpMessageConverter
        	    2.框架会调用实现类的 writer()方法,将 返回对象 转换为 json数组,调用 jackson的 					  ObjectMapper实现转为json数z。
        	    	contentType:application/json;charset=utf-8
        	    3.框架会调用@ResponseBody把2中的结果数据输出到浏览器,ajax请求处理完成
        */
        @ResponseBody	// 可以将方法的返回值转化成 json字符串
        public List<Student> list(){    
            List<Student> list = new ArrayList<>();
            Student	stu1 = new Student("张三",23);
            Student	stu2 = new Student("李白",24);
            Student	stu3 = new Student("王五",25);
            list.add(stu1);
            list.add(stu2);
            list.add(stu3);
    
            return list; //Springmvc框架负责将 list集合 转为 json数组
        }
        
        /*
        实现类:StringHttpMessageConverter	
        	与第一种方式不同,第一种方式是返回视图的名称,这里的 String 返回的是数据。
        区分返回值String是数据还是视图:看有没有 @ResponseBody 注解
        	有 @ResponseBody注解,返回的是数据,否则是视图
        	
        	默认使用 “text/plain;charset=ISO-8859-1”作为contentType,导致中文乱码,
        	解决方案:给RequestMapping增加一个属性 produces,使用这个属性指定新的 contentType
        */
    	@RequestMapping("/listData", produces="text/plain;charset=utf-8")
        @ResponseBody
        public String listData(){
            return "helloworld,你好";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    9. 四种跳转方式

    请求转发是基于服务器端的跳转(地址栏不会发生变化),重定向是基于客户端的跳转(地址栏会发生变化)(红色代表服务器端,蓝色代表客户端)

    image-20230704124435461

    项目4:请求转发和重定向

    项目4

    项目结构图:

    image-20230704130853552

    项目创建前的配置工作见第2节和第6节内容(无需参看第八节内容)

    页面:

    webapp\admin\main.jsp

    main....

    • 1

    webapp\index.jsp

    1.请求转发到页面(默认)

    2.请求转发到action

    3.重定向到页面

    4.重定向到action

    >5.随便跳页面
    • 1
    • 2
    • 3
    • 4
    • 5

    webapp\fore\login.jsp(测试five())

    login........

    • 1

    action(actioncom.bjpowernode.OtherAction,写如下方法): 对应第二种跳转方式

    @Controller
    public class OtherAction{
      @RequestMapping("/other")
      public String other(){
      		System.out.println("这是other的action访问。。。。");
      		return "main"; // 默认是请求转发的方式:使用视图解析器拼接前缀后缀(在springmvc.xml中配置的)。视图解析器见项目1
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    action(com.bjpowernode.JumpAction,写如下方法):

    @Controller
    public class JumpAction{
      @RequestMapping("/one")
        public String one(){ 
            System.out.println("这是请求转发页面跳转.........");
            return "main";  //默认是请求转发这种方式使用视图解析器拼接前缀后缀(前缀 main 后缀)进行页面跳转
        }
    
        @RequestMapping("/two")
        public String two(){
            System.out.println("这是请求转发action跳转.........");
            // return "/other.action" 会被视图解析器进行如下转换
            //  /admin/  /other.action  .jsp (这种像one()一样直接拼接是行不通的,所以使用了forward)
            //forward: 这组字符串可以屏蔽前缀和后缀的拼接.实现请求转发跳转
            return "forward:/other.action"; 
        }
    
        @RequestMapping("/three")
        public String three(){
            System.out.println("这是重定向页面.......");
            //redirect:  这组字符串可以屏蔽前缀和后缀的拼接.实现重定向跳转
            return "redirect:/admin/main.jsp";
        }
    
        @RequestMapping("/four")
        public String four(){
            System.out.println("这是重定向action.......");
            //redirect:  这组字符串可以屏蔽前缀和后缀的拼接.实现重定向跳转
            return "redirect:/other.action";
        }
    
        @RequestMapping("/five")
        public String five(){
            System.out.println("这是随便跳.......");
    
            return "forward:/fore/login.jsp"; // return "redirect:/fore/login.jsp";
        }    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    SpringMVC框架把原来servlet中的请求转发,重定向操作进行了封装。

    • forward和redirect都是关键字,有一个共同的特点 不和视图解析器一同工作,就当项目中没有视图解析器。

      不能够拼接视图解析器中的前后缀,所以这两个关键字后面要跟 视图文件的完整路径

    • forward:

      • 表示转发,实现 request.getRequestDispatcher(“xx.jsp”).forward();
      • 可以转发到 WEB-INF目录下的页面,是服务器端的行为
    • redirect:

      • 表示重定向,实现 response.redirect(“xxx.jsp”);
      • 不可以重定向到 WEB-INF目录下的页面,是浏览器端的行为
    image-20240202033712461

    异常处理

    以前我们处理异常,要在 会出现异常的地方 用 try catch finally 代码块进行捕获,大量编写重复代码,业务逻辑代码与异常处理代码相互耦合

    pringmvc框架采用的是统一,全局的异常处理。

    • 把controller中的所有异常处理都集中到一个地方。 采用的是aop的思想。把业务逻辑和异常处理代码分开。解耦合。

    • 使用两个注解

      • 方法上注解:@ExceptionHandler
      • 类上注解:@ControllerAdvice
    处理步骤

    项目路径

    代码参见讲义

    1.新建maven web项目

    2.加入依赖

    3.新建一个自定义异常类 MyUserException , 再定义它的子类NameException,AgeException

    4.在controller中抛出NameException , AgeException

    5.创建一个普通类,作用全局异常处理类

    1. 在类的上面加入@ControllerAdvice(控制器增强,需要声明组件扫描器)

    2. 在类中定义方法,方法的上面加入@ExceptionHandler(表示异常的类型,当发生此类型异常时,由当前方法进行处理)

    • 例如:@ExceptionHandler(value=NameException.class),处理NameException

      @ExceptionHandler 没有value表示处理 注解中除指定value外的 其他的所有异常,只能有一个

    • 该方法有一个形参 Exception,用来表示Controller中抛出的异常对象,通过该形参可以获取发生的异常信息)

    • 异常发生的处理逻辑

      • 将异常记录到数据库,日志文件
        • 记录异常发生的时间,哪个方法发生的,异常错误内容
      • 发送通知,把异常的信息通过邮件,短信,微信发送给相关人员
      • 给用户友好的提示

    6.创建处理异常的视图页面

    7.创建springmvc的配置文件

    1. 组件扫描器 ,扫描@Controller注解

    2. 组件扫描器,扫描@ControllerAdvice所在的包名

    3. 声明注解驱动(同处理ajax一样的注解驱动)

    10. SpringMVC默认的参数类型

    也就是在Action类中能够直接用作方法的形参的数据类型(形参:即服务端向客户端传递的参数)

    不需要去创建,直接拿来使用即可。

    1. HttpServletRequest

    2. HttpServletResponse

    3. HttpSession

    4. Model

    5. Map

    6. ModelMap

    注意:Map,Model,ModelMap和request一样,都使用请求作用域进行数据传递。所以服务器端的跳转必须是请求转发【forward】

    redirect方式不是同一请求作用域,不能共享数据,但使用session对象进行数据传递

    //做一个数据,传到main.jsp页面上
    Users u = new Users("张三",22);
    
    //传递数据
    request.setAttribute("requestUsers",u);
    session.setAttribute("sessionUsers",u);
    model.addAttribute("modelUsers",u);
    map.put("mapUsers",u);
    modelMap.addAttribute("modelMapUsers",u)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    项目结构(资料代码在项目4):

    image-20230704135817584

    页面:

    webapp\admin\main.jsp

    <h2>main.............显示数据,从action中携带的数据h2>
    requestUsers:${requestUsers} <br>  //el表达式,这里能取数据是因为下面的controller类中往里放了数据
    sessionUsers:${sessionUsers} <br>
    modelUsers:${modelUsers} <br>
    mapUsers:${mapUsers} <br>
    modelMapUers:${modelMapUsers}
    
    从index.jsp页来的数据${param.name}  //测试webapp\index.jsp中第二个超链接
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    webapp\index.jsp

    访问服务器,进行数据携带跳转
    
    访问服务器,进行数据携带跳转
    
    • 1
    • 2
    • 3

    代码:

    User:(com.bjpowernode.pojo.User 无参有参构造器,setget方法,toString方法未给出)

    public class Users {
        private String name;
        private int age;
    }
    
    • 1
    • 2
    • 3
    • 4

    DataAction(com.bjpowernode.controller.DataAction)

    @Controller
    public class DataAction {
        @RequestMapping("/data")
        public String data(HttpServletRequest request,
                           HttpServletResponse response,
                           HttpSession session,
                           Model model,
                           Map map,
                           ModelMap modelMap){
            //做一个数据,传到 main.jsp页面上
            Users u = new Users("张三", 22);
    
            //传递数据
            request.setAttribute("requestUsers", u);
            session.setAttribute("sessionUsers", u);
            model.addAttribute("modelUsers", u);
            map.put("mapUsers", u);
            modelMap.addAttribute("modelMapUsers", u);
    
            return "main";  //只能通过 请求转发方式跳转
            // return "redirect:/admin/main.jsp"; //观察有哪些数据可以被传递
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    11. 日期处理

    1. 日期的提交处理

    提交到服务器,进行业务逻辑层的处理

    项目结构(资料是用的项目4):

    image-20230704143253041

    页面:

    webapp\admin\main.jsp

    main.......

    • 1

    webapp\index.jsp

    日期:
    • 1
    • 2
    • 3
    • 4
    单个日期处理(MyDateAction)

    要使用注解@DateTimeFormat(没有注解会报500错误)

    此注解必须搭配 springmvc.xml文件中的标签

    (处理ajax请求也要这个标签,事务处理是一个tx开头的标签,在spring笔记中可以得到。在第8章可以找到该语句:这里和第八章不同的是,这里不能删除视图解析器的配置)

    //com.bjpowernode.MyDateAction
    @Controller
    public class MyDateAction{
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); //让日期格式变得好看
    
        //单个日期处理
        @RequestMapping("/mydate")
        public String mydate1(
            @DateTimeFormat(pattern = "yyyy-MM-dd") //将String注入到mydate,形参名与表单中name属性相同
            Date mydate){
            System.out.println(mydate);
            System.out.println(sf.format(mydate)); //在服务器端显示mydate,实际是用SimpleDateFormat将日期转换成字符串
            return "main";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    类中全局日期处理(MyDateAction)

    注册一个注解用来解析本类中的所有的日期类型,自动转换。不需要@DateTimeFormat标签和标签

    //com.bjpowernode.MyDateAction
    @Controller
    public class MyDateAction{
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
    
        //注册一个全局的日期处理注解
        @InitBinder
        public void initBinder(WebDataBinder dataBinder){
            dataBinder.registerCustomEditor(Date.class,
                                            new CustomDateEditor(sf, true));
        }
        @RequestMapping("/mydate")
        public String mydate2(Date mydate){
            System.out.println(mydate);
            System.out.println(sf.format(mydate));
            return "main";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    2.日期的显示处理

    将日期显示到页面(以好看的格式)

    单个日期对象
    1. 如果是单个日期对象,直接转为好看的格式化的字符串进行显示.

    上本节第一点中的MyDateAction类中修改成如下代码,便可在main.jsp中 输出日期(String类型)

    // main.jsp
    单个日期显示:${mydate}
    
    • 1
    • 2
    //com.bjpowernode.MyDateAction
    
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
    
    //注册一个全局的日期处理注解
    @InitBinder
    public void initBinder(WebDataBinder dataBinder){
        dataBinder.registerCustomEditor(Date.class,
                                        new CustomDateEditor(sf, true));
    }
    @RequestMapping("/mydate")
    public String mydate2(Date mydate, HttpServletRequest request){
        System.out.println(mydate);
        System.out.println(sf.format(mydate));
        request.setAttribute("mydate", sf.format(mydate)); //转换成字符串
    
        return "main";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    list中实体类对象成员为日期类型
    1. 如果是list中的实体类对象的成员变量是日期类型,则必须使用jstl进行显示.

      项目结构(资料中是项目4):

      image-20230704153500816

      页面:

      webapp\admin\main.jsp(实现第三步)

      学生集合

      姓名 生日
      ${stu.name} ${stu.birthday}------
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      webapp\index.jsp

      显示集合中对象的日期成员
      
      • 1

      步骤:

      1. 在pom.xml中添加依赖jstl,并在maven工程中进行刷新

        
        <dependency>
            <groupId>jstlgroupId>
            <artifactId>jstlartifactId>
            <version>1.2version>
        dependency>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
      2. 在页面上导入标签库 (因为要在main.jsp上显示数据,所以要在其页面上导入jstl标签核心库,jstl格式化标签库)

        // main.jsp
        <%--导入jstl核心标签库--%>
        <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
        <%--导入jstl格式化标签库--%>
        <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      3. 使用标签显示数据

        Student类(com.bjpowernode.pojo.Student无参有参构造器,getset方法,toString方法未给出)

        public class Student{
            private String name;
            private Date birthday;
        }
        
        • 1
        • 2
        • 3
        • 4

        action:

        //com.bjpowernode.MyDateAction
        
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        
        //注册一个全局的日期处理注解
        @InitBinder
        public void initBinder(WebDataBinder dataBinder){
            dataBinder.registerCustomEditor(Date.class,
                                            new CustomDateEditor(sf, true));
        }
        
        //单个日期处理
        @RequestMapping("/list")
        public String list(HttpServletRequest request) throws ParseException {
            Student stu1 = new Student("张三", sf.parse("2001-03-21"));
            Student stu2 = new Student("张2", sf.parse("2004-06-21"));
            Student stu3 = new Student("张8", sf.parse("2009-03-21"));
            List<Student> list = new ArrayList<>();
            list.add(stu1);
            list.add(stu2);
            list.add(stu3);
            request.setAttribute("list", list);
        
            return "main";
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25

    见配套的资源讲义

    会自动注册两个bean,分别为DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。 是springmvc为@controller分发请求所必须的。除了注册了这两个bean,还提供了很多支持。

    1)支持使用ConversionService 实例对表单参数进行类型转换;

    2)支持使用 @NumberFormat 、@DateTimeFormat;

    3)注解完成数据类型的格式化;

    4)支持使用 @RequestBody 和 @ResponseBody 注解;

    5)静态资源的分流也使用这个标签;

    springmvc的执行流程:40-SpringMVC执行流程分析_哔哩哔哩_bilibili

    12. 资源在WEB-INF目录下

    WEB-INF目录下的动态资源,不可直接访问,只能通过请求转发的方式进行访问。第 9节有明确的案例。

    在第4节的代码中也有详细解释

    静态资源放行

    发起的请求是由哪些服务器程序处理的。

    http://localhost:8080/ch05_url_pattern/index.jsp :tomcat(jsp会转为servlet)
    http://localhost:8080/ch05_url_pattern/js/jquery-3.4.1.js : tomcat
    http://localhost:8080/ch05_url_pattern/images/p1.jpg : tomcat
    http://localhost:8080/ch05_url_pattern/html/test.html: tomcat
    http://localhost:8080/ch05_url_pattern/some.do : DispatcherServlet(springmvc框架处理的)

    tomcat本身能处理静态资源的访问, 像html, 图片, js文件都是静态资源

    tomcat的web.xml文件有一个servlet 名称是 default , 在服务器启动时创建的。

    <servlet>
        <servlet-name>defaultservlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServletservlet-class>
        <init-param>
            <param-name>debugparam-name>
            <param-value>0param-value>
        init-param>
        <init-param>
            <param-name>listingsparam-name>
            <param-value>falseparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>defaultservlet-name>
        
        <url-pattern>/url-pattern>  表示静态资源和未映射的请求都这个default处理
    servlet-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    default这个servlet作用:
    The default servlet for all web applications, that serves static resources. It processes all requests that are not mapped to other servlets with servlet mappings (defined either here or in your own web.xml file).

    1.处理静态资源

    2.处理未映射到其它servlet的 请求。(前端发出的请求 没有对应的 servlet 处理)

    将静态资源和未映射到其它servlet的 请求 交给 default servlet 进行处理,而不是让 DispatcherServlet进行处理

    项目5

    项目5

    项目结构:

    image-20230704171044102

    页面:

    webapp下的index.jsp随便写点内容,删除的话会报404错误,不美观

    在WEB-INF目录下新建jsp目录,添加index.jsp,main.jsp。

    因为是测试访问这两个文件,所以里面的内容分别为

    index.jsp

    main.jsp

    【此目录下的动态资源,不可直接访问】

    action:(com.bjpowernode.controller.WebInfAction)

    @Controller  // 交给spring创建对象
    public class WebInfAction {
        @RequestMapping("/showIndex")
        public String showIndex(){
            System.out.println("访问index.jsp");
            return "index";  //后面配置的视图解析器为我们拼好了前缀和后缀
        }
    
        @RequestMapping("/showMain")
        public String showMain(){
            System.out.println("访问main.jsp");
            return "main";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    修改springmvc.xml中视图解析器的路径

    
     
    
     		
    
    
         
          //将来会在 webapp下创建jsp目录
         
          //将来会创建的 webapp下的jsp目录下的.jsp文件
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样的话,在地址栏输入 http://localhost:8080/showIndex.action 就可以跳转到 index.jsp

    ​ http://localhost:8080/showMain.action 就可以跳转到 main.jsp

    使用

    这个项目中并没有静态资源和动态资源的混合使用,只是访问了动态资源。(王鹤的教程中讲了)

    当遇到静态资源 和动态资源混合使用导致冲突时,在下述web.xml配置文件的注释中查找解决方案

    修改web.xml文件中的 注册springmvc框架 中的内容

    <servlet>
        <servlet-name>springmvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:springmvc.xmlparam-value>
        init-param>
    servlet>
    <servlet-mapping>
        <servlet-name>springmvcservlet-name>
        
    		<mvc:annotation-driven />
    		
        	<mvc:resources mapping="/static/**" location="/static/" />
    	-->
        <url-pattern>/url-pattern>  
    servlet-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    这样的话,在地址栏输入 http://localhost:8080/showIndex就可以跳转到 index.jsp

    ​ http://localhost:8080/showMain 就可以跳转到 main.jsp

    添加登录操作

    在jsp目录下新建 login.jsp(内容如下)

    登录

    姓名:
    密码:


    ${msg}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在action类 WebInfAction 中添加如下方法进行登录功能 (com.bjpowernode.controller.WebInfAction)

    @RequestMapping("/showLogin")
    public String showLogin(){
        System.out.println("访问login.jsp");
        return "login";
    }
    
    //登录的业务判断
    @RequestMapping("/login")
    public String login(String name, String pwd, HttpServletRequest request){
        if("zar".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){
            return "main";
        }else{
            request.setAttribute("msg", "用户名或密码不正确");
            return "login";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这个登录功能并不完善,后续会用到拦截器

    地址

    在jsp , html中使用的地址, 都是在前端页面中的地址,都是相对地址

    地址分类:
    1.绝对地址 , 带有协议名称的是绝对地址, http://www.baidu.com , ftp://202.122.23.1

    2.相对地址, 没有协议开头的, 例如 user/some.do , /user/some.do

    • 相对地址不能独立使用,必须有一个参考地址。 通过参考地址+相对地址本身才能指定资源。

    3.参考地址

    1. 在你的页面中的,访问地址不加 “/”

      访问的是: http://localhost:8080/ch06_path/index.jsp
      路径: http://localhost:8080/ch06_path/
      资源: index.jsp

      在index.jsp通过超链接发起 user/some.do请求,访问地址变为 http://localhost:8080/ch06_path/user/some.do。

      当你的地址 没有以斜杠开头,例如 user/some.do , 当你点击链接时, 访问地址是当前页面的地址(路径),加上超链接中的地址,即 http://localhost:8080/ch06_path/ + user/some.do。 http://localhost:8080/ch06_path/被称为参考地址

      index.jsp 访问 user/some.do , 再通过mv.setViewName(“/index.jsp”) 返回到index.jsp后现在的地 址: http://localhost:8080/ch06_path/user/some.do

      http://localhost:8080/ch06_path/user/some.do
      路径: http://localhost:8080/ch06_path/user/
      资源: some.do

      在index.jsp在 user/some.do ,就变为 http://localhost:8080/ch06_path/user/user/some.do(当前页面的地址(路径),加上超链接中的地址)

      解决方案:

      1. 加入${pageContext.request.contextPath}

      2. 加入一个base标签, 是html语言中的标签。 表示当前页面中访问地址的基地址。

        你的页面中所有 没有“/”开头的地址,都是以base标签中的地址为参考地址
        使用base中的地址 + user/some.do 组成访问地址

        <%
        	String basePath = request.getScheme() + "://" + 
            request.getServerName() + ":" + request.getServerPort() + 
            request.getContextPath() + "/";
        %>
        
            
            title
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
    2. 在你的页面中的,访问地址加 “/”

      访问的是: http://localhost:8080/ch06_path/index.jsp
      路径: http://localhost:8080/ch06_path/
      资源: index.jsp

      点击 /user/some.do, 访问地址变为 http://localhost:8080/user/some.do
      参考地址是 你的服务器地址, 也就是 http://localhost:8080

      如果你的资源不能访问: 加入 p a g e C o n t e x t . r e q u e s t . c o n t e x t P a t h < a h r e f = " {pageContext.request.contextPath} pageContext.request.contextPath<ahref="{pageContext.request.contextPath}/user/some.do">发起user/some.do的get请求

      index.jsp–addStudent.jsp—student/addStudent.do( service的方法,调用dao的方法)–result.jsp

    13. SpringMVC的拦截器

    针对请求和响应进行的额外的处理,在请求和响应的过程中添加预处理,后处理和最终处理.

    • 拦截器:

      1. 拦截器是springmvc中的一种,需要实现HandlerInterceptor接口。

      2. 拦截器和过滤器类似,功能方向侧重点不同

        • 过滤器是用来过滤请求参数,设置编码字符集等工作。
        • 拦截器是拦截用户的请求,对请求做判断处理的。
      3. 拦截器是全局的,可以对多个Controller做拦截。

        • 一个项目中可以有0个或多个拦截器, 他们在一起拦截用户的请求

        • 拦截器常用在:用户登录处理,权限检查, 记录日志。

    • 拦截器的使用步骤:

      1. 定义类实现HandlerInterceptor接口

      2. 在springmvc配置文件中,声明拦截器, 让框架知道拦截器的存在。

    • 拦截器的执行时间:

      • 在请求处理之前, 也就是controller类中的方法执行之前先被拦截。
      • 在控制器方法执行之后也会执行拦截器。
      • 在请求处理完成后也会执行拦截器。

    拦截器:看做是多个Controller中公用的功能,集中到拦截器统一处理。使用的是aop的思想

    拦截器执行的时机
    • preHandle():在请求被处理之前(调用处理器的方法前)进行操作。预处理

    • postHandle():在请求被处理之后(调用了处理器方法后),但结果还没有渲染前进行操作,可以改变响应结果(对原来的结果进行二次修正)。后处理

    • afterCompletion:所有的请求响应正常结束后(视图处理完成后,例如forward)执行善后工作。清理对象,关闭资源 。最终处理

      • preHandle方法返回 true 时,该方法一定执行
    image-20231128214129235
    拦截器实现的两种方式
    1. 继承HandlerInterceptorAdapter的父类

    2. 实现HandlerInterceptor接口。推荐使用实现接口的方式

    拦截器实现的步骤(改造项目5)

    单个拦截器:实现一次会话中免登录的功能

    1. 改造登录方法,在session中存储用户信息,用于进行权限验证

      在 WebInfAction类中改造登录的方法 (com.bjpowernode.controller.WebInfAction)

      //登录的业务判断
      @RequestMapping("/login")
      public String login(String name, String pwd, HttpServletRequest request){
          if("zar".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){
              //在 ssessionn中存储用户信息,用于权限验证(最终这里连数据库查信息)
              request.getSession().setAttribute("users", name);
              return "main";
          }else{
              request.setAttribute("msg", "用户名或密码不正确");
              return "login";
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    2. 开发拦截器的功能:实现HandlerInterceptor接口, 重写 preHandle()方法

      写com.bjpowernode.interceptor.LoginInterceptor类,实现HandlerInterceptor接口, 重写 preHandle()方法

      public class LoginInterceptor implements HandlerInterceptor {
          /* 预处理方法 preHandle
          	 特点:在控制器方法之前执行
          	 	  在此方法中可以获取请求的信息,验证请求是否符合要求
          	参数:
          		Object handler:被拦截的控制器对象,即上述的 WebInfAction
          */
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              //是否登录过的判断,
              if(request.getSession().getAttribute("users") == null){
                  //此时没有登录,打回到登录页,并给出提示
                  request.setAttribute("msg","请先登录");
                  //跳转到login.jsp(请求转发:servlet中学的,因为要携带数据)
                  request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
                  return false; // 截断请求,请求不会被控制器处理。后续所有方法都不执行
              }
      
              return true; //登录成功 放行请求,此时控制器方法才能执行
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
    3. 在springmvc.xml文件中注册拦截器

      <mvc:interceptors>
          
          <mvc:interceptor>
              
              <mvc:mapping path="/**"/>
              
              <mvc:exclude-mapping path="/showLogin">mvc:exclude-mapping>
              <mvc:exclude-mapping path="/login">mvc:exclude-mapping>
              
              <bean class="com.it.interceptor.LoginInterceptor">bean>
          mvc:interceptor>
          
      mvc:interceptors>
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20

    ​ 配置完成后,便可以在登录之后访问 index.jsp 和 main.jsp。直接访问这两个资源是拒绝的(他们都在WEB- INF目录下)

    ​ 多个拦截器实现的拦截器链====》采用的是拦截器设计模式

    多个拦截器

    讲义4.2源码

    讲义4.3 源码(类似于上述的 改造的项目5)

    拦截器链,责任链设计模式

    拦截器1先声明,拦截器2后在springmvc中声明

    第一个拦截器preHandle=true , 第二个拦截器preHandle=true

    111111-拦截器的MyInterceptor的preHandle()
    22222-拦截器的MyInterceptor的preHandle()
    =执行MyController中的doSome方法=
    22222-拦截器的MyInterceptor的postHandle()
    111111-拦截器的MyInterceptor的postHandle()
    22222-拦截器的MyInterceptor的afterCompletion()
    111111-拦截器的MyInterceptor的afterCompletion()

    类似于这种感觉:拦截器1将拦截器2 包裹在里面


    第一个拦截器preHandle=true , 第二个拦截器preHandle=false

    111111-拦截器的MyInterceptor的preHandle()
    22222-拦截器的MyInterceptor的preHandle()
    111111-拦截器的MyInterceptor的afterCompletion()


    第一个拦截器preHandle=false , 第二个拦截器preHandle=true|false

    111111-拦截器的MyInterceptor的preHandle()

    拦截器和过滤器的区别
    1. 过滤器是servlet规范中的对象, 拦截器是框架中的对象

    2. 过滤器实现Filter接口的对象, 拦截器是实现HandlerInterceptor接口的对象

    3. 过滤器是用来设置request,response的参数,属性的,侧重对数据过滤的。

      拦截器是用来验证请求的,能截断请求。

    4. 过滤器是在拦截器之前先执行的。

    5. 过滤器是tomcat服务器创建的对象

      拦截器是springmvc容器中创建的对象

    6. 过滤器是一个执行时间点。拦截器有三个执行时间点

    7. 过滤器可以处理jsp,js,html等等

      拦截器是侧重拦截对Controller的请求。 如果你的请求不能被DispatcherServlet接收, 这个请求不会执行拦截器内容

    8. 拦截器拦截普通类方法执行,过滤器过滤servlet请求响应

    监听器:Servlet规范。spring容器有一个 ContextLoadListener,用于 创建 spring容器

    14.SSM整合的步骤

    • SSM是标准的MVC模式,将整个系统分为 视图层,控制器层,业务逻辑层,数据访问层
      • springMVC负责请求的转发和视图管理 Controller
      • spring 实现业务对象管理 Service
      • Mybatis作为数据对象的持久化引擎完成数据持久化 Dao
    项目6

    项目6代码

    项目6代码实现具体步骤见讲义

    这个项目是 ssm + vue的,目前并没有学完。只注重前面的 SSM整合即可

    1. 建库,建表 ssmuser.sql

    2. 新建Maven项目,选择webapp模板

    3. 修改目录(maven规范的目录,以及com.bjpowernode.pojo包,mapper包,service包,controller包。测试类包名会影响pom.xml文件中junit的配置,要注意)

    4. 修改pom.xml文件(使用老师提供 pom.xml 记得修改为mysql8的版本)

      上依赖。

      这里有mybatis分页插件的依赖

    5. 添加jdbc.properties属性文件 jdbc记得改mysql8的,改driver和密码,数据库(复制粘贴即可)

    6. 添加SqlMapConfig.xml文件(使用模板,在sm整合时已经提供。)

      mybatis的配置

      <settings>
       <setting name="logImpl" value="STDOUT_LOGGING"/>
      settings>
      
      • 1
      • 2
      • 3
    7. 添加applicationContext_mapper.xml文件(数据访问层的核心配置文件。通过xml configuration file创建)

      
      <context:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
      
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
          <property name="driverClassName" value="${jdbc.driverClassName}">property>
          <property name="url" value="${jdbc.url}">property> 
          <property name="username" value="${jdbc.username}">property>
          <property name="password" value="${jdbc.password}">property>
      bean>
      
      <bean class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource">property>
          
          <property name="configLocation" value="classpath:SqlMapConfig.xml">property>
          
          <property name="typeAliasesPackage" value="com.bjpowernode.pojo">property>
      bean>
      
      
      <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
          <property name="basePackage" value="com.bjpowernode.mapper">property>
      bean>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
    8. 添加applicationContext_service.xml文件(业务逻辑层的核心配置文件。通过xml configuration file创建)

      
      <context:component-scan base-package="com.bjpowernode.service.impl">context:component-scan>
      
      
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource">property>
      bean>
      
      <tx:advice id="myadvice" transaction-manager="transactionManager">
          <tx:attributes>
              <tx:method name="*select*" read-only="true"/>  
              <tx:method name="*find*" read-only="true"/>
              <tx:method name="*search*" read-only="true"/>
              <tx:method name="*get*" read-only="true"/>
              <tx:method name="*insert*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
              <tx:method name="*add*" propagation="REQUIRED"/>
              <tx:method name="*save*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
              <tx:method name="*set*" propagation="REQUIRED"/>
              <tx:method name="*update*" propagation="REQUIRED"/>
              <tx:method name="*change*" propagation="REQUIRED"/>
              <tx:method name="*modify*" propagation="REQUIRED"/>
              <tx:method name="*delete*" propagation="REQUIRED"/>
              <tx:method name="*remove*" propagation="REQUIRED"/>
              <tx:method name="*drop*" propagation="REQUIRED"/>
              <tx:method name="*clear*" propagation="REQUIRED"/>
              <tx:method name="*" propagation="SUPPORTS"/>
          tx:attributes>
      tx:advice>
      
      <aop:config>
          <aop:pointcut id="mycut" expression="execution(* com.bjpowernode.service.impl.*.*(..))">aop:pointcut>
          <aop:advisor  advice-ref="myadvice" pointcut-ref="mycut">aop:advisor>
      aop:config>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33

      spring的配置

      4-8所需 jdbc需要改

      4-7可参见spring笔记中sm整合一节 spring笔记 。第7步有点不同:此处不需要导入applicationContext_mapper.xml(会在第8步实现),但是包扫描(service.impl)和事务处理的配置一定要加(spring笔记31节)

    9. 删除web.xml文件,新建,改名,设置中文编码(第6节),并注册springmvc框架(第12节项目5),并注册Spring框架

      web.xml注册框架

      sm整合的时候,容器启动是本地控制的,所以不用配置web.xml。

      到了ssm整合的时候,要配置web.xml:

      1. 注册springMVC的框架:DispathcherServlet (创建springmvc容器对象)
      2. 添加中文编码过滤器:CharacterEncodingFilter
      3. 添加监听器:ContextLoaderListener (创建spring容器对象)
      
      
      
      <servlet>
          <servlet-name>springmvcservlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
          <init-param>
              <param-name>contextConfigLocationparam-name>
              <param-value>classpath:springmvc.xmlparam-value>  // resources/springmvc.xml
          init-param>
          <load-on-startup>1load-on-startup>
      servlet>
      <servlet-mapping>
          <servlet-name>springmvcservlet-name>   
          <url-pattern>/url-pattern>
      servlet-mapping>
      
      
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
      listener>
      
      <context-param>
           
          <param-name>contextConfigLocationparam-name>
          
          <param-value>classpath:applicationContext_*.xmlparam-value>  *处可能要 **
      context-param>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
    10. 添加spirngmvc.xml文件(使用模板)

      
      <context:component-scan base-package="com.bjpowernode.controller">context:component-scan>
      
      
      <mvc:annotation-driven>mvc:annotation-driven>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      上配置。配置文件由下到上添加(mybatis的配置,spring的配置(分层),springmvc的配置)

      第8步:由于本项目是ajax请求,不需要配置视图解析器,只需要配置包扫描(controller)和ajax所需注解(第8节)

      springMVC的配置:从第8步开始是之前SM整合没有涉及到的了

    11. 新建实体类 User(user_id ===> userId 无参,含参构造,get,set,toString)

    12. 新建UserMapper.java接口(面向接口文档开发,代码实现如下 接口文档

    13. 新建UserMapper.xml(使用模板XXXmapper)实现增删查所有功能,没有更新(自己实现)

      为了使用动态代理所必须实现的规范

    14. 新建service接口和实现类

      实现类一定要 implements service接口,否则会报错:bean创建不成功

    15. 新建测试类,完成所有功能的测试

      @RunWith(SpringJUnit4ClassRunner.class) //启动spring的容器
      @ContextConfiguration(locations = {"classpath:applicationContext_mapper.xml","classpath:applicationContext_service.xml"})
      public class MyTest {
          @Autowired
          StudentService studentService;
      
          @Test
          public void testInsert() {
      
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    16. 新建控制器,完成所有功能

    17. 浏览器测试功能

    分页查询的sql语句

    select * from user limit (当前页码 - 1) * 当前页码, 每页条数;
    
    • 1
    分层
    • springMVC:视图层,界面层,负责接收请求,显示处理结果的
    • spring:业务层,管理 service,dao,工具类对象的
    • mybatis:持久层,访问数据库的

    用户发起请求 ----- springMVC接收 ----- spring中的service 对象 — mybatis处理数据

    SSM整合也叫做SSI (IBatis也就是mybatis的前身), 整合中有容器。

    1. 第一个容器SpringMVC容器, 管理Controller控制器对象的。

    2. 第二个容器Spring容器,管理Service,Dao,工具类对象的

    我们要做的把使用的对象交给合适的容器创建,管理。

    • 把Controller还有web开发的相关对象交给springmvc容器, 这些web用的对象写在springmvc配置文件中。

    • service,dao对象定义在spring的配置文件中,让spring管理这些对象。

    springmvc容器和spring容器是有关系的,关系已经确定好了。

    springmvc容器是spring容器的子容器, 类似java中的继承。 子可以访问父的内容

    在子容器中的Controller可以访问父容器中的Service对象, 就可以实现controller使用service对象

    实现步骤(由下到上)

    项目路径见文档

    1. 建库,建表

    2. 新建maven webapp项目

    3. 加入依赖(已提供)
      springmvc,spring,mybatis三个框架的依赖,jackson依赖,mysql驱动,druid连接池
      jsp,servlet依赖

    4. 写web.xml

      1. 注册DispatcherServlet

        ​ 目的:1.创建springmvc容器对象,才能创建Controller类对象。
        ​ 2.创建的是Servlet,才能接受用户的请求。

      2. 注册spring的监听器:ContextLoaderListener

        ​ 目的: 创建spring的容器对象,才能创建service,dao等对象。

      3. 注册字符集过滤器:CharacterEncodingFilter

        ​ 目的:解决post请求乱码的问题

    5. 创建包, Controller包, service ,dao,实体类pojo 包名创建好

    6. 写springmvc,spring,mybatis的配置文件

      1. springmvc配置文件

      2. spring配置文件

        1. applicationContext_mapper 负责 接管 mybtis中需要创建的对象
        2. applicationContext_service 负责 接管 service 层对象的创建
      3. mybatis主配置文件

        1. 只需要配置很少的东西,大部分都在 第二步 被 spring接管了
      4. 数据库的属性配置文件

    7. 写代码, dao接口和mapper文件, service和实现类,controller, 实体类。

    8. 写jsp页面

    :component-scan base-package=“com.bjpowernode.controller”>

    mvc:annotation-driven

    
    > 上配置。配置文件由下到上添加(mybatis的配置,spring的配置(分层),springmvc的配置)
    >
    > 第8步:由于本项目是ajax请求,不需要配置视图解析器,只需要配置包扫描(controller)和ajax所需注解(第8节)
    
    > springMVC的配置:从第8步开始是之前SM整合没有涉及到的了
    
    10. 新建实体类 User(user_id ===> userId 无参,含参构造,get,set,toString)
    
    11. 新建UserMapper.java接口(面向接口文档开发,代码实现如下 [接口文档](F:\学习资料\笔记资料\javaWeb\动力节点荣姐SSM\springMVC\03_资源))
    
    12. 新建UserMapper.xml(使用模板XXXmapper)实现增删查所有功能,没有更新(自己实现)
    
     > 为了使用动态代理所必须实现的规范
    
    13. 新建service接口和实现类
    
     > 实现类一定要 implements service接口,否则会报错:bean创建不成功
    
    14. 新建测试类,完成所有功能的测试
    
     ```java
     @RunWith(SpringJUnit4ClassRunner.class) //启动spring的容器
     @ContextConfiguration(locations = {"classpath:applicationContext_mapper.xml","classpath:applicationContext_service.xml"})
     public class MyTest {
         @Autowired
         StudentService studentService;
     
         @Test
         public void testInsert() {
     
         }
     }
     ```
    
    15. 新建控制器,完成所有功能
    
    16. 浏览器测试功能
    
    
    
    分页查询的sql语句
    
    ```sql
    select * from user limit (当前页码 - 1) * 当前页码, 每页条数;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    分层
    • springMVC:视图层,界面层,负责接收请求,显示处理结果的
    • spring:业务层,管理 service,dao,工具类对象的
    • mybatis:持久层,访问数据库的

    用户发起请求 ----- springMVC接收 ----- spring中的service 对象 — mybatis处理数据

    SSM整合也叫做SSI (IBatis也就是mybatis的前身), 整合中有容器。

    1. 第一个容器SpringMVC容器, 管理Controller控制器对象的。

    2. 第二个容器Spring容器,管理Service,Dao,工具类对象的

    我们要做的把使用的对象交给合适的容器创建,管理。

    • 把Controller还有web开发的相关对象交给springmvc容器, 这些web用的对象写在springmvc配置文件中。

    • service,dao对象定义在spring的配置文件中,让spring管理这些对象。

    springmvc容器和spring容器是有关系的,关系已经确定好了。

    springmvc容器是spring容器的子容器, 类似java中的继承。 子可以访问父的内容

    在子容器中的Controller可以访问父容器中的Service对象, 就可以实现controller使用service对象

    实现步骤(由下到上)

    项目路径见文档

    1. 建库,建表

    2. 新建maven webapp项目

    3. 加入依赖(已提供)
      springmvc,spring,mybatis三个框架的依赖,jackson依赖,mysql驱动,druid连接池
      jsp,servlet依赖

    4. 写web.xml

      1. 注册DispatcherServlet

        ​ 目的:1.创建springmvc容器对象,才能创建Controller类对象。
        ​ 2.创建的是Servlet,才能接受用户的请求。

      2. 注册spring的监听器:ContextLoaderListener

        ​ 目的: 创建spring的容器对象,才能创建service,dao等对象。

      3. 注册字符集过滤器:CharacterEncodingFilter

        ​ 目的:解决post请求乱码的问题

    5. 创建包, Controller包, service ,dao,实体类pojo 包名创建好

    6. 写springmvc,spring,mybatis的配置文件

      1. springmvc配置文件

      2. spring配置文件

        1. applicationContext_mapper 负责 接管 mybtis中需要创建的对象
        2. applicationContext_service 负责 接管 service 层对象的创建
      3. mybatis主配置文件

        1. 只需要配置很少的东西,大部分都在 第二步 被 spring接管了
      4. 数据库的属性配置文件

    7. 写代码, dao接口和mapper文件, service和实现类,controller, 实体类。

    8. 写jsp页面

  • 相关阅读:
    Win11如何更改默认下载路径?Win11更改默认下载路径的方法
    day83 AJAX
    基于 CentOS7 制作 Apache HTTPD 2.4.58 的RPM安装包
    Android入门第27天-GrdidView控制件和可复用的Adapter
    学Python的漫画漫步进阶 -- 第十一步.常用的内置模块
    【C语言初阶(NEW)】五、操作符详解(二)|隐式类型转换|算术转换|操作符的属性
    链表经典面试题(四)
    【数据结构初阶】一. 复杂度讲解
    FPGA USB device原型验证流程及调试手段
    SQL 专项笔记
  • 原文地址:https://blog.csdn.net/m0_60842098/article/details/136572451