springMVC

SpringMVC

什么是Springmvc

  1. SpringMVC:是基于spring的一个框架,是spring的一个模块。专门做web开发的,可以理解为servlet的升级
    web开发的底层是servlet,框架是在servlet的基础之上加入一些功能,方便web开发。

  2. springmvc是一个spring。而spring是一个容器,ioc能管理对象,使用,@Component,@Repository,@Service,@Controller。

  3. spring MVC也可以创建对象,放到容器中(springMVC容器),springmvc容器中放的是控制器对象。

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

使用@Controller注解创建的是一个普通类的对象,不是servlet。springmvc赋予了控制器对象一些额外的功能。

springmvc如何处理请求

web开发底层是servlet,而springmvc容器中的对象可以当作servlet来理解,但毕竟不是servlet,而是一个普通类的对象。所以springmvc是如何处理请求的?

springmvc中有一个对象是servlet:DispatcherServlet(中央调度器)

DispatcherServlet:负责接收用户的所有请求。用户把请求给了DispatcherServlet,之后DispatcherServlet把请求转发给我们的Controller对象,最后Controller对象来处理请求。

index.jsp—>DispatcherServlet(Servlet)----->转发,分配给---->Controller对象(@Controller注解创建的对象)

web项目的目录结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-adMAauTl-1666596136635)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220404140711589.png)]

ch01-hello-springmvc

需求:用户在页面发起请求,请求交给springmvc的控制对象,并显示请求的处理结果。

实现步骤:

  1. 新建web maven工程

  2. 加入依赖
    spring-webmvc依赖,间接把spring的依赖都加入到项目
    jsp,servlet依赖

    <dependency>
        <groupId>org.springframework</groupId>
    	<artifactId>spring-webmvc</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>
    <dependecy>
        <groupId>javax.servlet</groupId>
    	<artifactId>javax.servlet-api</artifactId>
    </dependecy>
    
  3. 重点:在web.xml中注册springmvc框架的核心对象是DispatherServlet

    1. DispatherServlet叫做中央调度器,是一个servlet,它的父类是继承HttpServlet
    2. DispatherServlet也叫做前端控制器(front controller)
    3. DispatherServlet负责接收用户提交的请求,调用其他的控制器对象,并把请求的处理结果显示给用户
  4. 创建一个发起请求的页面 index.jsp

  5. 创建按控制器类

    1. 在类的上面加入@Controller注解,创建注解,并放入到springmvc容器中

    2. 在类中的方法上面加入@RequestMapping注解

      @Controller
      public MyController{
          @RequestMapping(value = "/some.do")	//该请求地址的请求,全由下面这个方法来处理
          public ModelAndView doSome(){
              ModelAndView mv = new ModelAndView();
              mv.addObject(key,value);	//key是String,value是Object
              return mv;
          }
      }
      
  6. 创建一个作为结果的jsp,显示请求的处理结果

    ${key}	
    
  7. 创建springmvc的配置文件(spring配置文件一样)

    1. 声明组件扫描器,指定@Controller注解所在的包名

    2. 声明视图解析器,帮助处理试图

      <context:component-scan base-package="com.bjpowernode.controller"/>
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
      

springmvc请求处理流程

  1. 发起some.do
  2. tomcat(web.xml–url–pattern知道*.do的请求给DispatcherServlet)
  3. DispatcherServlet(根据springmvc配置文件知道some.do请求由doSome方法处理)
  4. DispatcherServlet把some.do转发给MyController.doSome()方法
  5. 框架执行doSome()把得到ModelAndView进行处理,转发到show.jsp

springmvc执行过程源代码分析

  1. tomcat启动,创建容器的过程,通过load-on-start标签指定的1,创建DispatcherServlet对象。

    DispatcherServlet它的父类是继承HttpServlet的,他是一个servlet,在被创建时,会执行init()方法。

    在Init()方法中:

    //创建容器,读取配置文件
    WebApplicationContext ctx = new ClassPathApplication("springmvc.xml");
    //把容器都西昂放入到ServletContext中
    getServletContext().setAttribute(key,ctx);
    

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

  2. 请求的处理过程

    1. 执行servlet的service()

      protected void service(HttpServletRequest request,HttpServletResponse response)
      protected void doService(HttpServletRequest request,HttpServletReponse response)
      
      DispatcherServlet.doDispatch(request,response){
          //调用MyController的.doSome()方法
      }
      

配置视图解析器

为了防止用户直接输入show.jsp从而访问结果页面,应该对不希望用户直接访问的页面加以控制。

可以将结果页面放入到web-INF目录下,因为web-INF目录下的内容对用户是不开放的。

如果结果页面太多,每次都要设置mv.setViewName(“/WEB-INF/view/xxx.jsp”),为了方便,需要设置视图解析器。

在springmvc配置文件中声明。

<!--声明springmvc框架中的视图解析器,帮助开发人员设置视图文件的路径-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!--前缀:视图文件的路径-->
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" vlaue=".jsp"/>
</bean>

当配置了视图解析器后,可以使用逻辑名称(文件名),指定视图。

框架会使用视图解析器的 前缀+逻辑名称+后缀 组成完整路径,这里就是字符链接操作。

mv.setViewName("show");
//框架会自动将字符串拼接,形成 “/WEB-INF/view/show.jsp”

DispatcherServlet方法接收参数

处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序员可在方法内直接使用

  • HttpServletRequest 代表请求
  • HttpServletResponse 代表应答
  • HttpSession 代表会话
  • 请求中所携带的请求参数 代表用户真正要提交的数据,两种接收方案,逐个接收和对象接收
public ModelAndView doSome(HttpServletRequest request,HttpServletResponse response,HttpSession session){
    //框架会自动给形参赋值
}

逐个接收

框架接收请求参数

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

    String strName = request.getParameter("name");
    String strAge = request.getParameter("age");
    
  2. springmvc框架通过DispatcherServlet调用MyController的doSome()方法

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

    doSome(String name,Integer age);
    //框架会自动赋值
    String name = strName;	//因为name和getParameter中的name一致
    Integer age = Integer.valueOf(StrAge);	//类型转换是框架自动进行的
    //400状态码是客户端错误,表示提交请求参数过程中,发生了问题,如果age不填写,框架类型转换时就会出现异常,于是就会报400错误。
    //但是如果形参age是用Integer修饰的,那么空值也是可以的
    

​ 如果形参和提交的请求参数名不一致,则无法接收到请求的参数值,可以通过注解解决

/*
	@RequestParam:解决请求中参数名形参名不一样的问题
	属性:1.value 请求中的参数名称
		 2.required 是一个boolean,默认是true
					表示请求中必须有该参数,否则报错
	位置:在处理器方法的形参定义到前面
*/
@Controller
public class MyController{
    @RequestMapping(value={"some.do","other.do"})
    //请求中名为“rname”的参数的值,要赋给name,这样就可以解决名称不统一的问题
    public ModelAndView receiveParam(@RequestParam(value="rname") String name,
                                     @RequestParam(value="rage") Integer age )
}

注意:在提交请求参数时,get请求方式中文没有乱码

​ 使用post方式提交请求时,中文有乱码,需要使用过滤器处理乱码的问题。

过滤器:过滤器可以自定义,也可以使用框架中提供的过滤器 characterEncodingFilter

在web.xml文件中
<filter>
	<filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    	<param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
    <init-param>
    	<param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
    	<param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

对象接收

package vo中的类就是springmvc中用对象接收请求参数中所用到的对象。

对象中的属性名和请求的参数名需要一致。

@RequestMapping
//Student类是定义好在vo package中的
public ModelAndView doSome(Student stu){
    stu.getName();
    stu.getAge();
}

返回值类型

四大类返回值

  1. 返回ModelAndView

    如果处理器方法处理完后,需要跳转到其他资源,且又要在跳转的资源间传递数据,此时使用ModelAndView。

  2. 返回String

    如果处理器方法处理完后,只需要跳转到其他页面而不需要传递数据,则返回String是最方便的

    @RequestMapping(value = "/returnstring.do",method = RequestMethod.POST)
        public String doReturnString(String name,Integer age){
           //返回的show与视图解析器一起组成完整路名
            //框架对视图进行forward转发操作
            return "show";
        }
    
  3. 返回void

    在处理ajax的时候,可以使用void返回值,通过HttpServletResponse输出数据,响应ajax请求.

    <!--复习一下ajax和jquery-->
    <!--前端-->
    <!--ajax入口函数-->
    $(function(){
    	$.get({
    	url:"url",
    	data:{data},
    	dataType:"json",
    	success:function(resp){
    	<!--处理resp-->
    }
    })
    })
    
    //后端
    @RequestMapping("returnVoid-ajax.do")
    public void doReturnVoid(HttpServletResponse resp,Student stu){
        String json = null;
        PrintWriter pw = null;
        //转换为json各式
        ObjectMapper om = new ObjectMapper();
        try{
        	json = om.writerValueAsString(stu);
            resp.contextType("application/json;charset=utf-8");
            pw = resp.getWriter();
        }catch(JsonProcessingException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        }
        pw.println(json);
        pw.flush();
        pw.close();
        
    }
    
  4. 返回Object

​ 处理器方法可以直接返回Object对象,返回的Object表示数据,是model,和视图无关。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。

​ 返回对象,需要使用@ResponseBody注解,将转换后的Json数据放入到响应体中,可以适用对象表示的数据,响应Ajax请求。

​ 实现步骤:

  1. 加入处理json的工具库依赖,springmvc默认使用的jackson

  2. 在springmvc配置文件中加入< mvc:annotation-driven >注解驱动,这一步是做了 om.writeValueAsString(Object) 的工作

    <mvc:annotation-driven>注解驱动完成了Java对象到json,xml,text,二进制等数据格式的转换。利用了下面的接口完成转换
        HttpMessageConverter接口:消息转换器
        
    public interface HttpMessageConverter<T> {
        
    	boolean canRead(Class<?> var1, @Nullable MediaType var2);
        //canWrite用于检查处理器方法的返回值是否能转为var2表示的数据格式,MediaType表示数据格式的
        boolean canWrite(Class<?> var1, @Nullable MediaType var2);
    	//无需在意
        List<MediaType> getSupportedMediaTypes();
    
        T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, 							        														HttpMessageNotReadableException;
    	//write吧处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串
        void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, 	  																		HttpMessageNotWritableException;
    }
    
    <mvc:annotation-driven>注解驱动在加入到springmvc配置文件后,会自动创建HttpMessageConverter接口的7个实现类对象,包括MappingJackson2HttpMessageConverter(使用jackson工具库中的ObjectMapper实现java对象转为json)
    
  3. 在处理器方法上面加入@ResponseBody注解

    这一部分的工作就是
    resp.contextType("application/json;charset=utf-8");
    pw = resp.getWriter();
    pw.println(json);
    

url-pattern

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

tomcat之所以能处理是因为tomcat中的conf中的web.xml中有default的servlet,

这个servlet属于org.apache.catalina.servlets.DefaultServlet。

这个servlet会处理所有未映射到其他servlet的请求,和静态资源。

而之所以这个default的servlet能处理上述两个作用,是因为他的url-pattern被设置成/了

所以我的项目中url-pattern设置成/,那么就取代了tomcat的default servlet,但是dispatcherServlet默认情况下没有处理静态资源的能力。没有控制器对象能处理静态资源的访问,所以这些静态资源都是404。

如果希望设置url-pattern为/且可以访问静态资源,则:

  • 第一种处理静态资源的方式

    需要在springmvc配置文件中加入< mvc:default-servlet-handler >标签即可。

    原理是:加入这个标签后,框架会创建控制器对象DefaultServletHttpRequestHandler(类似我们自己创建的MyController)。

    ​ DefaultServletHttpRequestHandler这个对象可以把接受的请求转发给tomcat的default这个servlet。

    注意:< mvc:default-servlet-handler > 和@RequestMapping注解有冲突,因为前者会把所有请求都转给tomcat处理,所以需要用<mvc:annotation-driven >来讲动态资源交给我们自定义的controller来处理。

  • 第二种处理静态资源的方式

    在spring3.0之后,spring定义了一个专门处理静态资源访问请求的处理器ResourceHttpRequestHandler.bingtianjiale < mvc:resources/>标签,用于解决静态资源无法访问的问题。

    需要在springmvc配置为年间中添加如下形式的配置:

    <mvx:resources location="/images/" mapping="/images/**"/>
    location 表示静态资源所在目录,目录不要使用WEB-INF及其子目录。
    mapping 表示对该资源的请求 
        
    

地址

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

地址分类

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

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

在页面的请求地址中加斜杠的方式

<a href="some">some</a>	
<!--
这是相对当前页面的地址,比如我在localhost8080/ch05发起请求,那么完整请求地址就是
localhost8080/ch05/some	
-->

<a href="/some">some</a>
<!--
这是基于服务器的地址,比如我在localhost8080/ch05发起请求,那么其中localhost8080就是我的服务器地址,发起请求的地址是
localhost8080/some

如果非要在页面使用第二种加斜杠的方式,那么需要EL表达式来指出你的请求地址指向哪一个项目
${pageContext.request.contextPath}	这个代表了ch05的意思,如果之后你的项目换成了ch06,他也会自动知道。
<a href="${pageContext.request.contextPath}/user/some.do"></a>	此时EL表达式之前就没有斜杠了。
-->

在页面的请求地址中不加斜杠的方式

假设我现在有一个页面跳转到自己
我从localhost8080/ch06发起请求,跳回自己

@RequestMapping("/user/some")
public ModelAndView doSome(Student stu){
	ModelAndView mv = new ModelAndView();
	mv.setViewName("index.jsp")
	return index.jsp
}

请求页面:

<a href="user/some">发起user/some请求</a>

此时当前页面的网址变成了localhost8080/ch06/user/some,
其中localhost8080/ch06/user/是路径,
some是资源,

那么当我再次从该页面发起user/some请求时,地址就会变成localhost8080/ch06/user/user/some
而这个地址没有任何资源,所以就会找不到。
所以为了解决地址变动导致找不到资源的问题,有两种解决办法

  1. 加入${pageContext.request.contextPath},也就是第一种加斜杠的方式
  2. 加入一个base标签,这个是html标签,表示当前页面中所有没有斜杠开头的访问地址的基地址。
<%
  String basePath = request.getScheme()+"://"+      //获取协议名
                    request.getServerName()+":"+    //获取服务器名
                    request.getServerPort()+"/"+    //获取端口号
                    request.getContextPath()+"/";   //http://localhost:8080/ch06/中的ch06部分
  

%>
<head>
	<base href="<%=basePath%>"/>
</head>

整合SSM

关于springmvc的依赖:
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>

关于spring的依赖:
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>      处理事务的依赖
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>    jdbc
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId> 使用aspectj实现事务

关于mybatis的依赖:
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
	<groupId>org.mybatis</groupId>整合用到的
    <artifactId>mybatis-spring</artifactId>

jackson依赖   用于json的
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>

mysql依赖:
    <groupId>mysql</groupdId>
    <artifactId>mysql-connector-java</artifactId>

druid连接池    数据库的
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
jsp
servlet依赖:
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>

实现步骤
1.新建maven web项目

2.加入依赖

3.写web.xml

1) 注册DispatcherServlet,目的:1.创建sprignmvc容器对象,才能创建Controller类对象
                             													2.创建的是servlet,才能接收用户的请求
   2) 注册spring的监听器:ContextLoaderListener,目的:创建spring容器,才能创建service,dao等对象
   3) 注册字符集过滤器characterEncodingFilter,目的:解决post请求乱码问题

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

5.写配置文件
1)spring配置文件
2)springmvc配置文件
3)mybatis配置文件
4)数据库的属性配置文件

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

7.写jsp页面

在pom.xml中
<!--name和url是生成网站时用到的,暂时用不到
  <name>ch01-hello-springmvc Maven Webapp</name>
  FIXME change it to the project's website &ndash;&gt;
  <url>http://www.example.com</url>
  -->
<!--spring配置文件:声明service,dao,工具类等对象-->

    <!--声明数据源,连接数据库-->
        <!--配置文件加载-->
    <context:property-placeholder location="classpath:conf/jdbc.properties"/>
        <!--声明数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
        <!--声明sqlSessionFactoryBean,目的是创建SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:conf/mybatis.xml"/>
    </bean>
    
    <!--声明mybatis扫描器,创建dao对象-->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.bjpowernode.dao"/>
    </bean>
    
    <!--声明service的注解@service所在的包名位置-->
    <context:component-scan base-package="com.bjpowernode.service"/>
    
    <!--事务配置:注解配置,aspectj的配置-->
<!--mybatis.xml-->
<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--设置别名-->
    <typeAliases>
        <!--实体类所在包名-->
        <package name="com.bjpowernode.entity"/>
    </typeAliases>
    <!--mapper的文件-->
    <mappers>
        <package name="com.bjpowernode.dao"/>
    </mappers>
<!--springmvc.xml-->
<context:component-scan base-package="com.bjpowernode.controller"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="suffix" value=".jsp"/>
        <property name="prefix" value="/WEB-INF/view/"/>
    </bean>
    
    <!--
        1.响应ajax请求,返回json
        2.解决静态资源访问问题
    -->
    <mvc:annotation-driven/>
    <!--静态资源-->
    <mvc:resources mapping="static/**" location="/static/"/>
<!--web.xml-->
<!--注册中央调度器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:conf/dispathcerServlet.xml</param-value>	<!--dispatcherServlet就是springmvc配置文件-->
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--注册监听器-->
        <!--指定自定义的spring配置文件路径,否则listener会去默认位置找-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:conf/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

    <!--解决post请求中文乱码问题-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

idea service窗口中文乱码

tomcat conf 中的logging.properties中catalina.org.apache 和localhost.org.apache 和java.util.logging这三行改成gbk即可;

在这里插入图片描述

SpringMVC核心技术

请求 转发和重定向 forward and redirect

forward:表示转发,实现reqeust.getRequestDispatcher(“.jsp”).forward()

redirect:表示重定向,实现response.sendRedirect(“xxx.jsp”)

注意:对于请求转发的页面,可以是WEB-INF中页面;而重定向的页面,是不能维WEB-INF中的页面的。因为重定向相当于用户在此发出一次请求,而用户是不能直接访问WEB-INF中的资源的。

 /*
    * 处理器方法返回ModelAndView,实现转发forward
    * 语法:setViewName("forward:完整页面的路径名");
    * forward:不和视图解析器一同使用。
    * */
    @RequestMapping(value = "/doForward.do")
    public ModelAndView doForward(Student stu){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",stu.getName());
        mv.addObject("age",stu.getAge());
        //forward:显式转发
        mv.setViewName("forward:/WEB-INF/view/show.jsp");
        return mv;
    }


    /*
     * 处理器方法返回ModelAndView,实现重定向redirect
     * 语法:setViewName("redirect:完整页面的路径名");
     * redirect:不和视图解析器一同使用。
     * */
    @RequestMapping(value = "/doRedirect.do")
    public ModelAndView doRedirect(Student stu){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",stu.getName());
        mv.addObject("age",stu.getAge());
        //重定向,重定向的页面不能是WEB-INF中的页面
        mv.setViewName("redirect:/hello.jsp");
        return mv;
    }
<h3>name数据:${param.name}</h3><br/>
    <h3>age数据:${param.age}</h3>
    <h3>name数据:<%=request.getParameter("name")%></h3><br/>

集中统一处理异常

异常处理:

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

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

使用两个注解:

1.@ExceptionHandler

2.@ControllerAdvice

/*
* 特点:必须让框架知道这个注解所在的包名,需要在springmvc配置文件声明组件扫描器
* 指定@ControllerAdvice所在的包名
* */
@ControllerAdvice
public class GlobalExceptionHandler {
    /*
    * 定义方法,处理发生的异常
    * 处理异常的方法和控制器方法的定义一样,返回值,形参之类的,控制方法能用的,处理异常方法页能用。
    *
    * 形参Exception表示Controller中抛出的异常对象
    *
    * @ExceptionHandler(异常的class):表示异常的类型,当发生此类型异常时,由当前方法处理
    * */
    @ExceptionHandler(value = NameException.class)
    public ModelAndView doNameException(Exception exception){
        /*
        * 处理NameException异常
        *
        * 异常发生时的处理逻辑:
        * 1.需要把异常记录下来,记录到数据库,日志文件
        *   记录异常发生的时间,哪个方法发生的,异常错误内容
        * 2.发送通知,把异常信息通过邮件,短信,微信发送给相关人员
        * 3.给用户友好的提示。
        * */
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "姓名必须是张三,其他用户不能访问");
        mv.addObject("ex",exception);
        mv.setViewName("nameError");
        return mv;
    }

拦截器Interception

  1. 拦截器是拦截请求,做预处理的。过滤器则是过滤请求参数的,设置编码字符集等工作的。

    拦截器是拦截用户的请求,做请求做判断处理的。

  2. 拦截器是全局的,可以对多个Controller做拦截。

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

    拦截器常用在:用户登录请求,权限检查,记录日志

拦截器是基于java的反射机制的,过滤器则是基于函数回调。

自定义拦截器需要实现HandlerInterception接口,

public class MyInterception implements HandlerInterception

实现步骤

  1. 定义类实现HandlerInterception接口
  2. 在springmvc配置文件中声明拦截器,让框架知道拦截器的存在。

拦截器的执行时间

  1. 在请求处理之前,也就是controller类中的方法执行之前先被拦截

    1. 在控制器方法自行之后也会执行拦截器
    2. 在请求处理完成后也会执行拦截器

多个拦截器的执行

​ 拦截器1的prehandler为true–拦截器2的prehandler为true–处理器方法执行–拦截器2的posthandler执行–拦截器1的posthandler执行–拦截器2的afterHandler执行–拦截器1的afterhandler执行

​ 如果第一个拦截器的prehandler为true,第二个拦截器的preHandler为False,那么第一个拦截器的afterhandler一定执行。

拦截器与过滤器的区别

  1. 过滤器是servlet中的对象,拦截器是框架中的对象

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

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

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

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

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

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

  6. 过滤器是一个执行时间点

    拦截器由三个执行时间点

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

    拦截器侧重拦截对Controller的对象,如果请求不能被dispatcherServlet接收,这个请求也不会被拦截器拦截

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

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

  1. 用户发起请求some.do

  2. DispatcherServlet接收请求some.do,把请求转交给处理器映射器(HandlerMapping)

    处理器映射器:springmvc框架中的一种对象,框架把实现了HandlerMapping接口的类都叫做映射器(多个)

    处理器映射器的作用:根据请求,从springmvc容器对象中获取处理器对象(MyController controller = ctx.getBean(“some.do”))

    ​ 框架把找到的处理器对放到一个叫做**处理器执行链(**HandlerExecutionChain)的类中保存。

    HandlerExecutionChain:类中保存着 1. 处理器对象(MyController) 2.项目中的所有的拦截器List< HandlerInterceptor >

  3. DispatcherServlet把2中的HandlerExecutionChain中的处理器对象交给了处理器适配器对象(多个)

    处理器适配器:springmvc框架中的对象,需要实现HandlerAdaptor接口

    处理器适配器作用:执行处理器方法(调用MyController.doSome()得到返回值ModelAndView)

  4. DispatcherServlet把3中获取的ModelAndView交给了视图解析器对象。

    视图解析器:springmvc中的对象,需要实现ViewResolver(可以有多个)

    视图解析器作用:组成视图完整路径。

    View是一个接口,表示视图的

    InternalResolverView:视图类,表示jsp文件,视图解析器会创建InternalResolverView类对象。

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

56790ffaad776522d3707c09d4cbe63 w

er controller = ctx.getBean(“some.do”))

​ 框架把找到的处理器对放到一个叫做**处理器执行链(**HandlerExecutionChain)的类中保存。

HandlerExecutionChain:类中保存着 1. 处理器对象(MyController) 2.项目中的所有的拦截器List< HandlerInterceptor >

  1. DispatcherServlet把2中的HandlerExecutionChain中的处理器对象交给了处理器适配器对象(多个)

    处理器适配器:springmvc框架中的对象,需要实现HandlerAdaptor接口

    处理器适配器作用:执行处理器方法(调用MyController.doSome()得到返回值ModelAndView)

  2. DispatcherServlet把3中获取的ModelAndView交给了视图解析器对象。

    视图解析器:springmvc中的对象,需要实现ViewResolver(可以有多个)

    视图解析器作用:组成视图完整路径。

    View是一个接口,表示视图的

    InternalResolverView:视图类,表示jsp文件,视图解析器会创建InternalResolverView类对象。

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

56790ffaad776522d3707c09d4cbe63 w
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值