SpringMVC学习笔记

SpringMVC就是将servlet的过程封装起来,有自己的一套配置和使用方法,在SpringMVC中,用来处理请求的类叫做控制器类(controller),在servlet中也有相应的类。

关于视图定位

在xml中,配置所有视图的默认位置

在Beans标签中间加入下面代码,表示WEB-INF/page/为页面的默认位置。这个位置,不能从外部直接访问,当内部需要跳转到某个页面时,首先会到该目录下访问。

   <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/" />
        <property name="suffix" value=".jsp" />
    </bean>

在tomcat的server.xml中,也有一个配置过程起到类似的作用,下面配置代码指示了应用所在的位置。如果不配置的话,想要访问这个应用,就需要把整个项目放在tomcat中,这就很麻烦。

<Context path="/" docBase="D:\Workspaces\springmvc\web" debug="0" reloadable="true" />   

TIPS:

如果在地址栏输入:127.0.0.1/index.jsp 那么,就会在tomcat指定的应用目录中去寻找这个文件,注意,不是视图定位的位置,而是在tomcat的server.xml中配置的应用的位置。如果输入的是 1270.0.1/index 那么,应用的 controller 中,会有一个专门用来处理 index 的方法,如果没有这个处理的方法,就报 404 。

视图定位的位置表示的是 我在内部调用页面是使用的默认位置,是一个安全位置,外部是不能直接访问的,想访问这里面的页面,唯一的方法就是通过servlet进行内部跳转。例如:controller中有这么一个语句,表示跳转到showProduct这个文件,SpringMVC就会去视图定位的位置去寻找这个文件,配置中,可以指定文件的后缀之类的,那么跳转时,就不需要加上后缀,showProduct表示的是跳转到 showProduct.jsp这个文件,因为配置时,设置了后缀为 .jsp 。

ModelAndView mav = new ModelAndView("showProduct");

关于控制器类

下面是注解方式来配置SpringMVC中需要用到的控制器类,和Spring一样,也可以在xml中配置。

在控制器的类声明上面,加上注解 @Controller  表示,这个类是一个控制器类,可以用来处理客户端发来的请求

在相应的处理方法上面,加上注解 @RequestMapping("/addProduct")  表明该方法是用来处理前端发来的 addProduct 这个请求的,即html中的form表单的action的值。

在前端的表单中,会填写一些属性,比如name,age,相应的在后端就需要一个 bean 来装这些数据(接收数据的注入),就是下面的例子中的 Product 类,类中的成员变量,就有neme,age这些属性,而且还要有相应的get和set方法,bean的规范。

@Controller   //代表这个是一个控制器类,用来处理请求
public class ProductController {
    
    @RequestMapping("/addProduct") //注解方式  表明该方法是用来处理 addProduct这个请求的
    public ModelAndView add(Product product) throws Exception {
        //mav.addObject("product",product); 参数列表中有一个 Product类的对象,该值会自动赋值给mav,并不需要手动添加
        ModelAndView mav = new ModelAndView("showProduct");
        return mav;
    }
}

跳转方式:

上面的过程进行的是服务端跳转,例如:请求的是 addProduct ,在服务端跳转到了 showProduct ,

下面介绍下客户端跳转,和服务端跳转的区别在于,服务端跳转,浏览器地址栏显示的地址不会发生变化,跳转过程在服务端进行,前端没感觉,客户端跳转,在浏览器地址栏上可以看到访问的地址已经发生了变化,当你访问 /jump 时,地址栏的地址会跳转到 /index ,可以看出,已经进行了客户端跳转。

   @RequestMapping("/jump")
    public ModelAndView jump() {
        ModelAndView mav = new ModelAndView("redirect:/index");//重定向请求
        return mav;
    }   

关于session

Session在用户登录,一些特殊场合在页面间传递数据的时候会经常用到,什么意思?session和servlet中的一样。

servlet 中的session,会话,用来标记同一用户的一系列动作。

 我们使用Httpsession对象来标记不同的会话,也就是说,与一个特定客户的整个会话期间,Httpsession对象会持久存储。Httpsession对象中有许多的属性我们可以直接使用,比如 count 用来记录访问次数。

同一个用户,向同一个 servlet 发送多次请求,如果没有 session ,那么对于容器来说,就是不同的请求,容器并不知道这些请求是来自于同一个用户(因为http是面向无连接的,一次数据发送完毕,连接就会关闭,所以容器不会知道请求来自同一个客户),当加上session之后,当一个用户第一次建立连接时,容器就会给该客户一个ID,后面客户每次发送数据,都会用整个 ID 来标识自己,容器会根据 sessionID,得知,某些请求来自同一个用户,我们可以将每次用户发送的数据存储在Httpsession对象中,这样,servlet 就不仅仅知道用户的本次请求发送了什么数据,还可以获取之前请求的数据。

sessionID是存放在cookie中的,容器和客户的每次交互,都需要将cookie交给对方,而且整个过程,会由容器自动完成,我们只需要直接使用Httpsession对象就行了,原理还是要知道的。

想使用session这个对象,需要导入相关的包,session中的count属性记录的是同一个用户访问该页面的次数?  

   import javax.servlet.http.HttpSession; 

   @RequestMapping("/check") public ModelAndView check(HttpSession session) { Integer i = (Integer) session.getAttribute("count"); if (i == null) i = 0; i++; session.setAttribute("count", i); ModelAndView mav = new ModelAndView("check"); return mav; }

关于中文问题

通过过滤器来实现这个配置过程,配置之后,页面显示中文不会乱码。

在项目的web.xml中配置过滤器来设置字符集,就可以解决。过滤器的作用和servlet中的一样,所以说先学servlet,再学框架真的是容易些

servlet 中的过滤器:

过滤器就是在夹在客户和servlet中间的部件,所有的请求必从过滤器经过才能到达servlet,同样的所有的响应必须经过过滤器才能回送给客户。把关的。

 在servlet中,过滤器在DD中配置,某些请求运行特定组合的过滤器,过滤器的顺序等。过滤器的运行顺序,由FilterChain来定义,FilterChain请求到来时,沿着FilterChain来运行,目标servlet给出响应时,响应沿着FilterChanin的反方向出来。

 配置文件web.xml:head first servlet&JSP的P678

   <filter>  
        <filter-name>CharacterEncodingFilter</filter-name>  
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
        <init-param>  
            <param-name>encoding</param-name>  
            <param-value>utf-8</param-value>  
        </init-param>  
    </filter>  
    <filter-mapping>  
        <filter-name>CharacterEncodingFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping> 

关于如何上传文件

关于拦截器

对于业务类Controller来说,并不知道由拦截器的存在,

首先在SpringMVC的xml文件的beans标签中配置拦截器,可以配置多个,拦截器运行的顺序就是配置的顺序,例如下面的配置文件,在访问/index时,会先执行

IndexInterceptor和Interceptor2这两个拦截器。这两个拦截器都是针对/index这个请求的。

   <!-- 配置拦截器 -->
    <mvc:interceptors>    
        <mvc:interceptor>    
            <mvc:mapping path="/index"/>  
            <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --> 
            <bean class="interceptor.IndexInterceptor"/>      
        </mvc:interceptor>  
        <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
        <mvc:interceptor>    
            <mvc:mapping path="/index"/>  
            <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 --> 
            <bean class="interceptor.Interceptor2"/>      
        </mvc:interceptor> 

    </mvc:interceptors> 

拦截器类如下:拦截器相当于把业务处理类包裹起来了,Controller处理前运行一部分,处理之后,再运行一部分

public class IndexInterceptor extends HandlerInterceptorAdapter { 
     /**  
     * 在业务处理器处理请求之前被调用  
     * 如果返回false  
     *     从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 
     * 如果返回true  
     *    执行下一个拦截器,直到所有的拦截器都执行完毕  
     *    再执行被拦截的Controller  
     *    然后进入拦截器链,  
     *    从最后一个拦截器往回执行所有的postHandle()  
     *    接着再从最后一个拦截器往回执行所有的afterCompletion()  
     */   
    public boolean preHandle(HttpServletRequest request,    
            HttpServletResponse response, Object handler) throws Exception {
         
        System.out.println("preHandle(), 在访问Controller之前被调用");  
        return true;
    } 
    /** 
     * 在业务处理器处理请求执行完成后,生成视图之前执行的动作    
     * 可在modelAndView中加入数据,比如当前时间,只有当这个处理函数运行结束之后,真正的响应才会返回给客户
     */ 
    public void postHandle(HttpServletRequest request,    
            HttpServletResponse response, Object handler,    
            ModelAndView modelAndView) throws Exception {  
        System.out.println("postHandle(), 在访问Controller之后,访问视图之前被调用,这里可以注入一个时间到modelAndView中,用于后续视图显示");
        modelAndView.addObject("date","由拦截器生成的时间:" + new Date());
    }  
    /**  
     * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等   
     *   
     * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()  
     */
     
    public void afterCompletion(HttpServletRequest request,    
            HttpServletResponse response, Object handler, Exception ex)  
    throws Exception {
        System.out.println("afterCompletion(), 在访问视图之后被调用");  
    }  
       
原文地址:https://www.cnblogs.com/mxck/p/7147680.html