2022-05-26  2022-05-26    16296 字   33 分钟

SpringMVC第一天

一、SpringMVC的基本概念(了解)

(一)三层架构和MVC

1、三层架构概述

我们的开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就是浏览器服务器。在 JavaEE 开发中,几乎全都是基于 Browser/S 架构的开发。那么在 B/S 架构中,系统标准的三层架构
包括:表现层(web)、业务层(service)、持久层(dao)。三层架构在我们的实际开发中使用的非常多,所以我们课程中的案例也都是基于三层架构设计的。
三层架构中,每一层各司其职,接下来我们就说说每层都负责哪些方面:
(1)表现层(表示层,web):也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层,web 需要接收 http 请求,完成 http 响应。
表现层包括展示层和控制层:控制层负责接收请求,展示层负责结果的展示。	
(2)业务层:也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。	
(3)持久层(Dao data access  object):也就是我们是常说的 dao 层。负责数据持久化,和数据库做交互。

(二)SpringMVC 概述

1、springMVC是什么?

SpringMVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
model: 模型 bean pojo
controller: servlet 充当了控制器
view: 试图~ 


百科介绍:
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts 2(一般老项目使用)等等。

总结: 
springmvc 是应用web层的 基于MVC设计模式的轻量级的web框架。 对Servlet封装,支持restful风格。
官网: 
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web

2、SpringMVC在三层架构中的位置?

springMVC位于三层架构中的表现层,作用是接收请求响应数据,响应的数据通过视图、模板展示给用: 
数据访问层:  Mybatis DButils JdbcTemplate Jdbc | Mybatis-plus | mapper Hibernate JPA  
业务层:    spring框架: IOC提供对象, 声明式事务~ 
表现层:    springMVC Servlet | Struts2(很少)  Struts1 

3、SpringMVC的优势?

(1)清晰的角色划分:
(2)分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。 
(3)POJO 就可以充当控制器,屏蔽了繁琐的servlet的API
(4)和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。 
(5)可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。 
(6)可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。 
(7)功能强大的数据验证、格式化、绑定机制。 
………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配
置支持等等。

约定优于配置, 配置优于编码~ 

二、SpringMVC入门(实战)

(一)SpringMVC 的入门案例

1、入门案例需求分析

构建页面index.jsp发起请求,在服务器端处理请求,控制台打印处理请求成功,跳转success.jsp成功页面;

2、构建maven项目并添加依赖

注意:  maven war   工程打包方式war。 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

总结: springmvc: webmvc web

3、web.xml中配置核心控制器DispatcherServlet

<servlet>
    <servlet-name>springmvc01</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc01</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

4、配置springMVC的配置文件springmvc.xml

 	<!--扫描注解包-->
    <context:component-scan base-package="com.offcn.controller"></context:component-scan>
    
	<!--处理器映射器:根据请求路径匹配映射路径找到对应的执行器-->
   <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>

    <!--处理器适配器:根据处理器映射器返回的执行器对象,去执行执行器对象-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>

    <!--视图解析器:解析视图-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

5、构建页面发起请求

<a href="/hello/test1">hello</a>

6、编写控制器并使用注解配置

@Controller //必须开启注解扫描
@RequestMapping("hello")
public class HelloController {
    @RequestMapping("test1")
    public String test1(){
        System.out.println("正在处理请求");
        return "main";
    }
}

7、启动服务器测试

pom.xml文件中服务器插件配置:
 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <!--指定编码格式-->
                    <uriEncoding>utf-8</uriEncoding>
                    <!--指定项目启动后的访问路径-->
                    <path>/</path>
                    <!--指定访问端口号-->
                    <port>8888</port>
                </configuration>
            </plugin>
        </plugins>
    </build>

(二)SpringMVC执行过程及原理分析

1、SpringMVC的请求响应流程

浏览器发送请求,被DispatcherServlet捕获,DispatcherServlet没有直接处理请求,而是将请求交给HandlerMapping处理器映射器,处理器映射器根据请求路径去controller控制层中匹配对应的执行器,并将匹配结果返回给DispatcherServlet,由DispacherServlet调用HandlerAdapter处理器适配器来执行控制层执行器方法;
执行器方法执行后的返回结果,由DispatcherServlet交给视图解析器ViewResolver来处理,找到对应的结果视图,渲染视图,并将结果响应给浏览器。

http://localhost:8080/xxx/servlet
(1)客户端浏览器发出请求, 到达DispatcherServlet前端控制器。 springmvc 框架提供的。  
(2)DispatcherServlet 将请求交给了 处理器映射器,进行路径映射。映射结果交给前端控制器。 
(3)请求到达处理器适配器,可以进行数据类型的转换等操作,最后达到Handler。【后端处理器,自定义的 Servlet】 
(4)后端处理器处理完毕之后, 将结果经过处理器适配器最终交给 前端控制器。 
(5)经过视图解析器: 数据解析到 view 对象当中。  交给了前端控制器
(6)前端控制器将view对象 交给模板引擎,进行试图渲染。 最终生成静态页面,响应给用户。 

以下组件: 
一个中心是三个基本点: 不需要自己开发,springmvc提供的
一个中心: DispatcherServlet 
三个基本点: 处理器映射器  处理器适配器  试图解析器
Handler后端处理器:程序员自己开发~ 

https://www.pianshen.com/article/72582080569/

(三)SpringMVC常用组件介绍

1、DispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于 mvc 模式中的 controller,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。 
DispatcherServlet本质上就是servlet web.xml当中。 该组件是springMVC 提供的, 无所编写,只需配制。

2、HandlerMapping:处理器映射器

HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC提供了不同的映射器实现不同的映射方式: 
该组件: springMVC提供的。 无需编写

3、Handler:后端处理器【自定义的,类似于servlet】

它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。 
等价于之前编写的Servlet。后端逻辑处理 【程序员编写】

4、HandlAdapter:处理器适配器

通过 HandlerAdapter 对处理器进行执行, 适配器主要进行数据类型类转换等操作~  
该组件: 无需编写, 只需配置~ 

5、View Resolver:视图解析器

View Resolver 负责将处理结果(ModelAndView)生成 View 对象,将view对象返回给前端控制器。 
注意: 组件springmvc提供的, 如果不使用,可以不用配置。  
      如果要使用,自行配置试图解析器~ 

6、View:视图渲染

SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jsp、freemarkerView、pdfView,FreeMark ,thymeleaf 等。我们最常用的视图就是 jsp。之后的学习, 我们会学习静态模板技术~  
view对象的数据渲染到页面上。 

总结: 
springmvc 基于组件开发: 
DispatcherServlet: 一个中心
三个基本点:
    处理器映射器: 
    处理器适配器: 
    试图解析器: 
    
后端处理器: 类似与servlet, 程序员自定义。 

7、mvc:annotation-driven标签说明:

在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。使用 <mvc:annotation-driven> 自动加载 RequestMappingHandlerMapping(处理映射器)和RequestMappingHandlerAdapter ( 处 理 适 配 器 ),可 用 在 SpringMVC.xml 配 置 文 件 中 使 用<mvc:annotation-driven>替代处理映射器和适配器的配置(一般开发中都需要该标签)。注意:我们只需要编写处理具体业务的控制器以及视图。
    
<mvc:annotation-driven> 标签相当于以下配置:
<!-- HandlerMapping处理器映射器 --> 
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerM
apping"></bean> 
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
    
<!-- HandlerAdapter处理器适配器 --> 
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerA
dapter"></bean> 
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
    
<!-- HadnlerExceptionResolvers异常处理器 --> 
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExcept
ionResolver"></bean> 
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolv
er"></bean> 
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"
></bean>

三、SpringMVC中的请求参数绑定【重点】

(一)绑定说明

1、绑定的机制

我们都知道,表单中请求参数都是基于 key=value 的。SpringMVC绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。

获得前端页面提交的参数:
request.getParameter("username");
String [] values = request.getParameterValues("hobby");
request.getParameterMap(); => Map集合

2、支持的数据类型

简单类型参数:包括基本类型和 String 类型
POJO 类型参数:包括实体类,以及关联的实体类
数组和集合类型参数:包括 List 结构和 Map 结构的集合(包括数组)

3、使用要求:

如果是基本类型或者 String 类型:要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)
如果是 POJO 类型,或者它的关联对象:要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。
如果是集合类型,有两种方式:
(1)第一种:要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。给 List 集合中的元素赋值,使用下标。给 Map 集合中的元素赋值,使用键值对。
(2)第二种:接收的请求参数是 json 格式数据。需要借助一个注解实现。 @RequestBody注解

(二)参数绑定示例

1、基本类型和 String 类型作为参数

1页面定义请求
<form action="/hello/test2" method="post">
    用户名<input name="userName" type="text">
    年龄<input name="age" type="text">
    <input type="submit" value="提交">
</form>
2执行器方法绑定参数
 @RequestMapping("test2")
    public String test2(String userName,int age){
        System.out.println("用户名:"+userName);
        System.out.println("年龄:"+age);
        return "main";
    }
注意 参数提交的名称和方法形式参数的名称保持一致 否则封装失败~  并且能够进行数据类型的转换 

2、POJO 类型作为参数

1页面定义请求
<form action="/hello/test3" >
    用户名<input name="pname" type="text">
    年龄<input name="age" type="text">
    车名称<input name="car.cname" type="text">
    车价格<input name="car.cprice" type="text">
    <input type="submit" value="提交">
</form>
2执行器方法绑定参数
 @RequestMapping("test3")
    public String test3(Person person){
        System.out.println(person);
        return "main";
    }

3、POJO 类中包含集合类型参数(了解)

集合类型不能直接绑定在方法的形式参数上 
1页面定义请求
<form action="/hello/test4" >
    用户名<input name="pname" type="text">
    年龄<input name="age" type="text">
    车名称<input name="car.cname" type="text">
    车价格<input name="car.cprice" type="text">
    list集合车1车名称<input name="carList[0].cname" type="text">
    list集合车1车价格<input name="carList[0].cprice" type="text">
    list集合车2车名称<input name="carList[1].cname" type="text">
    list集合车2车价格<input name="carList[1].cprice" type="text">
    set集合车1车名称<input name="carSet[0].cname" type="text">
    set集合车1车价格<input name="carSet[0].cprice" type="text">
    set集合车2车名称<input name="carSet[1].cname" type="text">
    set集合车2车价格<input name="carSet[1].cprice" type="text">
    map集合车1车名称<input name="map['x'].cname" type="text">
    map集合车1车价格<input name="map['x'].cprice" type="text">
    map集合车2车名称<input name="map['y'].cname" type="text">
    map集合车2车价格<input name="map['y'].cprice" type="text">
    <input type="submit" value="提交">
</form>
2执行器方法绑定参数
  @RequestMapping("test4")
    public String test4(Person person){
        System.out.println(person);
        return "main";
    }

注意 set集合---了解 
 1set集合必须创建 new HashSet<>();
 2set集合提供set 和get 方法
 3在构造器当中明确set集合当中添加的元素个数

4、数组类型参数(重点)


1页面定义请求
<form action="/hello/test5" >
    爱好1<input name="hobbies" type="text">
    爱好2<input name="hobbies" type="text">
    爱好3<input name="hobbies" type="text">
    <input type="submit" value="提交">
</form>
2执行器方法绑定参数
   @RequestMapping("test5")
    public String test5(String[] hobbies){
        for(String hobby:hobbies){
            System.out.println(hobby);
        }
        return "main";
    }

5、使用 ServletAPI 对象作为方法参数

1引入servletAPI的依赖jar包:(注意jar包作用范围provided:不参与项目部署
		 <!--web: servlet ,jsp, jstl -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
2执行器方法绑定参数
    @RequestMapping("test6")
    public void test6(HttpServletRequest request, HttpServletResponse response,HttpSession session) throws ServletException, IOException {
        System.out.println("我在请求转发");
        request.getRequestDispatcher("/hello/test1").forward(request,response);
    }

6、请求参数乱码问题

tomacat 对 GET 和 POST 请求处理方式是不同的:
(1)GET 请求的编码问题,要改 tomcat 的 server.xml配置文件:【了解】
  
    <!--在实际开发当中, 不允许使用,第一:无权限修改 第二:其对他用户造成影响-->
	<Connector connectionTimeout="20000" port="8080"protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

 使用的方式:  在配置tomcat插件的时候,指定一个tomcat字符集编码。 
 <uriEncoding>utf-8</uriEncoding>
  
(2)POST 请求的编码问题,要在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>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

7、静态资源访问:

(1)将静态资源交给默认的DefaultServlet处理:在springMVC.xml配置文件中加如下配置:
	<mvc:default-servlet-handler></mvc:default-servlet-handler>
(2)指定静态资源的访问路径:在springMVC.xml配置文件中加如下配置:
	<mvc:resources location="/css/" mapping="/css/**"/>
	<mvc:resources location="/images/" mapping="/images/**"/>
	<mvc:resources location="/js/" mapping="/js/**"/>

(三)自定义参数类型转换器

1、使用场景:

SpringMVC不能自动识别参数转换为我们需要的数据类型,浏览器报400错误,类型转换异常;

默认支持的类型: yyyy/MM/dd  
如果需要使用自定义的类型:此时就需要类型转换器
开发步骤: 
(1)开发一个类型转换器  implements Converter<String, Date> 
(2)将自定义的类型转换器配置在工厂当中: 
(3)在注解当中引用工厂: <mvc:annotation-driven conversion-service="serviceFactoryBean" /> 

2、使用步骤:

1定义类型转换器
public class MyDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date=simpleDateFormat.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
2配置类型转换器
 <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <bean class="com.offcn.util.MyDateConverter"></bean>
        </property>
    </bean>
(3)引用类型转换器;	
 引用自定义的类型转换器: 
 <mvc:annotation-driven conversion-service="serviceFactoryBean" />

     
<form action="/hello/test7" >
    入职日期:<input name="hireDate" type="date">
    <input type="submit" value="提交">
</form>

 @RequestMapping("test7")
    public String test7(Date hireDate){
        System.out.println(hireDate);
        return "main";
    }

(四)参数绑定默认类型

参数绑定:默认类型:Map<String,Object> ModelAndView Model ModelMap 类型,能够给前台传递。

@RequestMapping(path="hello01")
    public ModelAndView modelAndView(User user, Map<String,String> map){
        System.out.println(user);
        ModelAndView mav = new ModelAndView();
        map.put("username",user.getUsername());
        mav.setViewName("success");
        return  mav;

}

 @RequestMapping(path="hello01")
    public ModelAndView modelAndView(User user, ModelMap model){
        System.out.println(user);
        ModelAndView mav = new ModelAndView();
        model.addAttribute("username",user.getUsername());
        mav.setViewName("success");
        return  mav;
    }

 @RequestMapping("findById")
    public ModelAndView findById(Integer id, Model model){
        Person person = new Person();
        person.setAge(29);
        person.setName("许~");
        person.setBirthday(new Date());
        //视图路径的跳转:
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("success");

        //存在Model当中: 传递给前台:
        model.addAttribute("person",person);
        return modelAndView;

    }

四、SpringMVC的注解详解

(0)RequestMapping注解

0、RequestMapping 注解

用于定义映射路径,建立请求url和控制层方法之间的对应关系;
(1)注解位置:
	a.类上:定义一级映射路径;
	b.方法上:定义二级映射路径;
(2)注解属性:		
	value:用于指定映射路径url。它和 path 属性的作用是一样的。
	method:用于指定请求的方式。method = {RequestMethod.POST } 只能处理post请求。 状态码405
	params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 	key 和 value 必须和配置的一模一样。eg:params = {"username"},表示请求参数必须有 username; 
	如果没有携带username的参数:前端浏览器400 bad request

(一)RequestParam

1、RequestParam注解介绍

使用在方法入参位置,用于指定请求参数名称,将该请求参数绑定到注解参数位置。
属性:name:指定要绑定的请求参数名称;
     required:指定请求参数是否必传; true:表明必须提交参数, 没有400
	 defaultValue:指定当没有传入请求参数时的默认取值;

2、RequestParam注解使用案例

 @RequestMapping("test1")
    public String test1(@RequestParam(name = "pname",required = true,defaultValue = "李四")String name){
        System.out.println(name);
        return "main";
    }

3、RequestParam注解测试结果

详见课堂案例结果

(二)RequestHeader

1、RequestHeader注解介绍

注解在方法入参位置,用于获取请求头信息。

2、RequestHeader注解使用案例

 value指定头的名称 
 require是否是必须 true必须传递 没传递400 
 defaultValue 如果前台没传递头信息 指定默认值 require冲突
@RequestMapping("test2")
    public String test2(@RequestHeader("Upgrade-Insecure-Requests")String data){
        System.out.println(data);
        return "main";
    }

3、RequestHeader注解测试结果

详见课堂案例结果

(三)RequestBody

1、RequestBody注解介绍

用于方法入参位置,获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。get 请求方式不适用。通常用于将json格式字符串绑定到bean对象中;

2、RequestBody注解使用案例

1直接获取请求体内容
<form action="/annotation/test3" method="post">
    用户名<input name="userName" type="text">
    年龄<input name="age" type="text">
    <input type="submit" value="提交">
</form>
    @RequestMapping("test3")
  public String test3(@RequestBody String data){
      System.out.println(data);
      return "main";
  }
2将json格式请求参数绑定到指定对象bean中
<button onclick="sendCar()">发起ajax请求</button>
<script>
    function sendCar() {
        $.ajax({
            type: "POST",
            url: "/annotation/test4",
            data: '{"cname":"宝马","cprice":"20"}',
            contentType:"application/json",
            success: function(msg){
                alert( "Data Saved: " + msg );
            }
        });
    }
</script>
 @RequestMapping("test4")
  public String test4(@RequestBody Car car){
      System.out.println(car);
      return "main";
  }

注意 使用json 需要引入json的解析器~ 
<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.9</version>
    </dependency>

3、RequestBody注解测试结果

详见课堂案例结果

(四)CookieValue

1、CookieValue注解介绍

用于方法入参位置,把指定 cookie 名称的值传入控制器方法参数。

2、CookieValue注解使用案例

//1 : 获得所有的cookie 
//2:  cookie
//3   getName("JSESSIONID") -value

@RequestMapping("test5")
  public String test5(@CookieValue("JSESSIONID") String data){
      System.out.println(data);
      return "main";
  }


//通过@CookieValue 获得cookie对象
@RequestMapping("cookie2")
    public ModelAndView cookie2(Integer id, @CookieValue("JSESSIONID") Cookie cookie) {

        System.out.println("cookie:"+cookie);
        //cookie 的API信息~
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("success");
        return modelAndView;
    }

3、CookieValue注解测试结果

详见课堂案例结果

(五)ModelAttribute

1、ModelAttribute注解介绍

该注解是SpringMVC4.3版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。

2、ModelAttribute注解使用案例

1注解在方法上
  @ModelAttribute("shareParam")
  public String test6(){
      System.out.println("我是公共方法");
      return "公共参数";
  }
2注解在参数位置
  @RequestMapping("test7")
  public String test7(@ModelAttribute("shareParam")String data){
      System.out.println(data);
      return "main";
  }

3、ModelAttribute注解测试结果

详见课堂案例结果

(六)SessionAttributes

1、SessionAttributes注解介绍

注解在类上,作用将请求域中的参数存放到session域中,用于参数共享。

2、SessionAttributes注解使用案例

   //将参数存放到请求域
   @RequestMapping("test8")
   public ModelAndView test8(ModelAndView modelAndView){
        modelAndView.addObject("aa","aa1");
        modelAndView.addObject("bb","bb1");
        modelAndView.addObject("cc","cc1");
        modelAndView.setViewName("main");
        return modelAndView;
   }
   //将请求域参数存放到session域中
   @Controller
@RequestMapping("annotation")
@SessionAttributes(value = {"aa","bb"})
public class AnnotationController {
...
}

3、SessionAttributes注解测试结果

详见课堂案例结果

springMVC第二天

springMVC: web层的轻量级框架, servlet

springMVC的执行流程: 图

springMVC的入门案例:

参数的绑定:

a: 获得前段页面的参数。

b: 原生servletAPI

c: 绑定一些默认类型:Map Model ModelMap 向前台传递值。

springMVC常用的注解:

一、Rest风格编程

(一)Rest风格URL规范介绍

1、什么是restful?

RESTful架构,就是目前最流行的一种互联网软件架构风格,并不是开发规范。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的. Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。即"表现层状态转化"。如果一个架构符合REST原则,就称它为RESTful架构。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。
它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。

2、restful的优点:

它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

3、restful 的特性【体现】

 (1)资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符。
(2)表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层 (Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
(3)状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP 协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
(4)传统请求url:
新增:http://localhost:8888/annotation/addPerson      POST
修改:http://localhost:8888/annotation/updatePerson   POST
删除:http://localhost:8888/annotation/deletePerson?id=1   GET
查询:http://localhost:8888/annotation/findPerson?id=1     GET
(4)REST风格请求:
新增:http://localhost:8888/annotation/person      POST
修改:http://localhost:8888/annotation/person      PUT
删除:http://localhost:8888/annotation/person/1      DELETE
查询:http://localhost:8888/annotation/person/1      GET

2: 传递的参数可以作为url地址的一部分。 
http://localhost:8888/annotation/person/1

(二)PathVariable注解【重要】

该注解用于绑定 url 中的占位符例如请求 url /annotation/test9/{id}这个{id}就是 url 占位符url 支持占位符是 spring3.0 之后加入的是springmvc 支持 rest 风格 URL 的一个重要标志
属性
	value用于指定 url 中占位符名称
	required是否必须提供占位符
	
	localhost:8080/hello3/250 url: 
	/**
     * 获得url地址当中的变量值:
     * @param modelAndView
     * @param id
     * @return
     */
    @RequestMapping("hello3/{xx}")
    public  ModelAndView hello3(ModelAndView modelAndView, @PathVariable(value = "xx",required = false) Integer id){
        System.out.println("id:"+id);
        //模型数据:
        modelAndView.addObject("key1","value1");//request.attribute()
        //视图数据:
        modelAndView.setViewName("success");
        return modelAndView;
    }

(三)PathVariable案例

1、构建页面发起请求

REST风格编程:
新增:
<form action="/annotation/person" method="post">
    用户名:<input name="userName" type="text">
    年龄:<input name="age" type="text">
    <input type="submit" value="提交">
</form>
修改:
<form action="/annotation/person" method="post">
    <input type="hidden" name="_method" value="PUT">
    用户名:<input name="userName" type="text">
    年龄:<input name="age" type="text">
    <input type="submit" value="提交">
</form>

删除:
<form action="/annotation/person/1" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="提交">
</form>
查询:
<a href="/annotation/person/1">查询用户</a>

2、定义控制层执行器处理请求

 @RequestMapping(value = "person",method = RequestMethod.POST)
 @Getting("/person")
   public String addPerson(String userName,int age){
       System.out.println("新增用户:"+userName);
       return "main";
   }
   @RequestMapping(value = "person",method = RequestMethod.PUT)
   public String updatePerson(String userName,int age){
       System.out.println("修改用户:"+userName);
       return "main";
   }
   @RequestMapping(value = "person/{id}",method = RequestMethod.DELETE)
   public String deletePerson(@PathVariable(value = "id")int id){
       System.out.println("删除用户:id"+id);
       return "main";
   }
   @RequestMapping(value = "person/{id}",method = RequestMethod.GET)
   public String findPerson(@PathVariable(value = "id")int id){
       System.out.println("查询用户信息:id"+id);
       return "main";
   }

3.引入请求方式转换过滤器

 <filter>
        <filter-name>hiddenMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hiddenMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

二、响应数据和结果视图

(一)返回值分类

1、返回值为字符串

用于指定返回的逻辑视图名称
控制器代码
    @RequestMapping("test1")
    public String test1(String pname){
        System.out.println(pname);
        System.out.println("返回string类型测试");
        return "main";
    }

运行结果详见课堂案例结果

2、void类型

 /**
     *  方法的返回值void:
     *  (1) 默认情况下, void也会进行路径的跳转。
     *       跳转位置:  经过视图解析器 + 访问位置 寻找对应的页面。
     *
     *  (2)void 的应用场景:
     *  a:字符流或者是字节流向客户端浏览器异步返回数据。
     *  b:使用原生servlet进行 页面的转换或者是重定向时候, 可以使用void类型。
     */
    @RequestMapping("/void")
    public void voidTest(HttpServletRequest request,HttpServletResponse response){
        System.out.println("void方法被执行了~");
       // response.getWriter().println("xxx");

       // request.getRequestDispatcher().forward();
       // response.sendRedirect();

    }	

3、ModelAndView

用于绑定参数和指定返回视图名称
控制器代码
  @RequestMapping("test3")
    public ModelAndView test3(ModelAndView modelAndView){
        modelAndView.addObject("aa","aa1");
        modelAndView.setViewName("main");
        return modelAndView;
    }

ModelAndView 对象  
封装模型数据
封装视图数据
注意:对象是springMVC底层对象使用很少~

4: 自定义类型【重要】

  @GetMapping("getData")
     @ResponseBody//引入依赖包:
    public String  getDate1(){
       return "ok";
    }


    @GetMapping("getData2")
    @ResponseBody//引入依赖包:
    public Person  getData2(){
        Person person = new Person();
        person.setId(1001);
        person.setName("许8");
        return person;//异步返回数据:{"id":1001,"name":"许8"}

    }


    @GetMapping("getData3")
    @ResponseBody//引入依赖包:
    public List<Person> getData3(){
         List<Person> list = new ArrayList<>();
        Person person = new Person();
        person.setId(1001);
        person.setName("许8");

        Person person2 = new Person();
        person2.setId(1002);
        person2.setName("康7");

        Person person3 = new Person();
        person3.setId(1003);
        person3.setName("夏66");
        list.add(person);
        list.add(person2);
        list.add(person3);


        return list;//异步返回数据:[{"id":1001,"name":"许8"},{},{}]

    }


    @GetMapping("getData4")
    @ResponseBody//引入依赖包:
    public Map<String,Person> getData4(){//
        Map<String,Person> map = new HashMap<>();
        Person person = new Person();
        person.setId(1001);
        person.setName("许8");

        Person person2 = new Person();
        person2.setId(1002);
        person2.setName("康7");

        Person person3 = new Person();
        person3.setId(1003);
        person3.setName("夏66");
        map.put("person1",person);
        map.put("person2",person2);
        map.put("person3",person3);

        return map;//异步返回数据:{person1:{},person2:{}}

    }

注意 
使用@ResponseBody 必须引入jackson-databind json解析器 

(二)转发和重定向

1、forward请求转发

控制器代码
 @RequestMapping("test4")
    public String test4(){
        System.out.println("我是请求转发");
        return "forward:/response/test1";
    }
运行结果详见课堂案例结果	

2、redirect重定向

控制器代码
  @RequestMapping("test5")
    public String test5(RedirectAttributes redirectAttributes,String pname){
        System.out.println("我是重定向");
       // redirectAttributes.addAttribute("pname",pname);
        redirectAttributes.addFlashAttribute("pname",pname);
        return "redirect:/response/test1";
    }
运行结果详见课堂案例结果
//注意:重定向携带参数,需要使用对象RedirectAttributes,该对象提供两个方法封装参数addAttribute()和addFlashAttribute(),第一个方法参数会明文显示在浏览器地址栏,第二个方法参会会隐藏,使用第二种方法传参时,获取参数时需要加注解@ModelAttribute;

三、Postman工具使用

(一)Postman工具介绍

用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具。今天给大家介绍的这款网页调试工具不仅可以调试简单的css、html、脚本等简单的网页基本信息,它还可以发送几乎所有类型的HTTP请求!Postman在发送网络HTTP请求方面可以说是Chrome插件类产品中的代表产品之一。

(二)Postman工具的下载安装

1、下载地址:https://www.postman.com/downloads/
2、安装步骤:
1)下载安装文件
2)运行安装程序
3)重启电脑自动安装
4)运行

(三)Postman工具的使用

四、SpringMVC中的父子容器解析

(一)SpringMVC中的父子容器解析

Spring和SpringMVC的容器具有父子关系,Spring容器为父容器,SpringMVC为子容器,子容器可以引用父容器中的Bean,而父容器不可以引用子容器中的Bean。
配置spring的配置文件时,排出扫描控制层注解:
 <context:component-scan base-package="com.offcn">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
 </context:component-scan>
配置springMVC的配置文件时,扫描控制层注解:
 <context:component-scan base-package="com.offcn.controller">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
 </context:component-scan>

五、SpringMVC中的文件上传

(一)文件上传的必要前提:

1、form 表单的 enctype 取值必须是:multipart/form-data(默认值是:application/x-www-form-urlencoded)enctype:是表单请求正文的类型
2、 method 属性取值必须是 Post
3、提供一个文件选择域<input type=”file”/>

(二)文件上传原理分析

当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。 enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:key=value&key=value&key=value;
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成:每一部分都是 MIME 类型描述的正文;

(三)SpringMVC的文件上传

1、构建maven工程添加相关依赖

  <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
  </dependency>

2、编写 jsp 页面

<form enctype="multipart/form-data" method="post" action="/file/fileUpload">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>

3、编写控制器

   @RequestMapping("fileUpload")
    public String fileUpload(MultipartFile file){
        File dest = new File("C:\\Users\\mwx\\Pictures\\"+file.getOriginalFilename());
        //文件上传
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "main";
    }

4、配置文件解析器

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

5、测试文件上传的运行结果

详见课堂案例结果

六、SpringMVC中的异常处理

(一)项目开发中异常处理的方式介绍

系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。

(二)异常处理的设计思路

系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理。

(三)异常处理的步骤

1、编写异常类和错误页面

  @RequestMapping("test2")
    public String test2(){
        System.out.println("模拟出现异常");
        int i = 10/0;
        return "main";
    }
页面error.jsp详见具体课堂案例

2、自定义异常处理器

public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ex.printStackTrace();
        System.out.println("自定义异常处理");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

3、配置异常处理器

 <bean class="com.offcn.util.MyExceptionHandler"></bean>

4、测试异常处理的运行结果

详见课堂案例结果

七、SpringMVC中的拦截器使用

(一)拦截器的介绍和作用

SpringMVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。用户可以自己定义一些拦截器来实现特定的功能。谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

(二)拦截器与过滤器的区别【面试题目】


过滤器: 
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
过滤器在web.xml中的 url-pattern 标签中配置了/*:
可以对所有要访问的资源拦截。 /* html css js 
底层实现基于回调函数实现: 


拦截器: 
拦截器是 SpringMVC 框架自己的,只有使用了SpringMVC框架的工程才能用。
拦截器在springmvc.xml当中进行配置: 
只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者js是不会进行拦截的: /**
AOP 思想的具体应用。

(三)自定义拦截器的步骤

1、编写一个普通类实现 HandlerInterceptor 接口

public class MyIntercepter implements HandlerInterceptor {
    /**
     * 控制层执行器方法前的拦截器
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("我是控制层执行器方法前的拦截器");
        //校验用户是否登录
        HttpSession session = request.getSession();
        String pname=(String)session.getAttribute("pname");
        if(pname!=null){
            //当前用户已经登录,放行
            return true;
        }else{
            //当前用户未登录,拦截跳转到登录页面
            request.getRequestDispatcher("/login.jsp").forward(request,response);
            return false;
        }
        //返回true表示继续执行控制层执行器方法,返回false表示方法结束,不会执行控制层执行器方法

    }

    /**
     * 控制层方法返回时拦截器
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                    @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("我是控制层执行器方法返回时拦截器");
    }

    /**
     * 控制层方法结束后的拦截器
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                         @Nullable Exception ex) throws Exception {
        System.out.println("我是控制层执行器方法结束后的拦截器");
    }
}

2、配置拦截器

<!--springMVC配置文件中注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/file/login"/>
            <bean class="com.offcn.util.MyIntercepter"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

3、测试拦截器的运行结果

详见课堂案例结果

(四)拦截器的注意事项

1、拦截器的放行

拦截器中的放行指的是如果有下一个拦截器就执行下一个如果该拦截器处于拦截器链的最后一个则执行控制器中的方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)方法返回true表示继续执行控制层执行器方法返回false表示方法结束不会执行控制层执行器方法

2、拦截器中方法的说明

public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 控制层执行器方法前的拦截器(该方法时在控制层执行器方法前调用,当该方法返回结果为true则继续调用下一个拦截器,如果已经时最后
     * 一个拦截器,则调用控制层中的执行器方法;当该方法返回结果为false,则不会继续执行控制层执行器中的方法)
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("我是控制器方法前拦截器2");
        return true;

    }

    /**
     * 控制层方法返回时拦截器(该方法是控制层执行器方法执行之后,由DispatcherServlet在将结果响应给浏览器前调用的方法)
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("我是控制层执行器方法返回时拦截器2");
    }

    /**
     * 控制层方法结束后的拦截器(该方法在请求业务处理执行完全结束之后由DispatcherServlet调用执行)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                @Nullable Exception ex) throws Exception {
        System.out.println("我是控制层执行器方法结束后的拦截器2");
    }
}

3、拦截器的作用路径

  <!--拦截器注册-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/><!--用于指定拦截的 url-->
            <mvc:exclude-mapping path="/file/login"/><!--用于指定排除的 url-->
            <bean class="com.offcn.util.MyIntercepter"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

4、多个拦截器的执行顺序

(1)多个拦截器放行的情况:
拦截器1
public class MyInterceptor1 implements HandlerInterceptor {
    /**
     * 控制层执行器方法前的拦截器(该方法时在控制层执行器方法前调用,当该方法返回结果为true则继续调用下一个拦截器,如果已经时最后
     * 一个拦截器,则调用控制层中的执行器方法;当该方法返回结果为false,则不会继续执行控制层执行器中的方法)
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("我是控制器方法前拦截器1");
        return true;

    }

    /**
     * 控制层方法返回时拦截器(该方法是控制层执行器方法执行之后,由DispatcherServlet在将结果响应给浏览器前调用的方法)
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("我是控制层执行器方法返回时拦截器1");
    }

    /**
     * 控制层方法结束后的拦截器(该方法在请求业务处理执行完全结束之后由DispatcherServlet调用执行)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                @Nullable Exception ex) throws Exception {
        System.out.println("我是控制层执行器方法结束后的拦截器1");
    }
}
拦截器2
public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 控制层执行器方法前的拦截器(该方法时在控制层执行器方法前调用,当该方法返回结果为true则继续调用下一个拦截器,如果已经时最后
     * 一个拦截器,则调用控制层中的执行器方法;当该方法返回结果为false,则不会继续执行控制层执行器中的方法)
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("我是控制器方法前拦截器2");
        return true;

    }

    /**
     * 控制层方法返回时拦截器(该方法是控制层执行器方法执行之后,由DispatcherServlet在将结果响应给浏览器前调用的方法)
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("我是控制层执行器方法返回时拦截器2");
    }

    /**
     * 控制层方法结束后的拦截器(该方法在请求业务处理执行完全结束之后由DispatcherServlet调用执行)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                @Nullable Exception ex) throws Exception {
        System.out.println("我是控制层执行器方法结束后的拦截器2");
    }
}
执行结果如下

(2)多个拦截器阻断的情况:
第一个拦截器返回true,第二个拦截器返回false时,执行结果如下:

第一个拦截器返回false,第二个拦截器返回true时,执行结果如下:

八、拦截器的简单案例(验证用户是否登录)

(一)实现思路分析

1、定义登录页面,并定义请求映射。
2、判断用户名密码是否正确
3、如果正确 向 session 中写入用户信息
4、返回登录成功。
5、拦截用户请求,判断用户是否登录
6、如果用户已经登录。放行
7、如果用户未登录,跳转到登录页面

(二)案例代码

1登录页面login.jsp定义
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/file/login" method="post">
    用户名<input type="text" name="pname">
    密码<input type="text" name="password">
    <input type="submit" value="登录">
</form>
</body>
</html>
2控制器实现
    @RequestMapping("login")
    public String login(String pname, String password, HttpSession session){
        System.out.println("登录校验成功");
        //将登录成功的用户名存放到session中
        session.setAttribute("pname",pname);
        return "main";
   }
3拦截器实现
 @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("我是控制层执行器方法前的拦截器");
        //校验用户是否登录
        HttpSession session = request.getSession();
        String pname=(String)session.getAttribute("pname");
        if(pname!=null){
            //当前用户已经登录,放行
            return true;
        }else{
            //当前用户未登录,拦截跳转到登录页面
            request.getRequestDispatcher("/login.jsp").forward(request,response);
            return false;
        }
        //返回true表示继续执行控制层执行器方法,返回false表示方法结束,不会执行控制层执行器方法

    }
4注册拦截器
<mvc:interceptor>
            <mvc:mapping path="/**"/><!--用于指定拦截的 url-->
            <mvc:exclude-mapping path="/file/login"/><!--用于指定排除的 url-->
            <bean class="com.offcn.util.MyIntercepter"></bean>
</mvc:interceptor>

spring :

springMVC :

xmind:【选做】 有道云笔记 。

Linux: 安装, 配置好网络: 静态分配~ 【必须】


avatar
青山
悟已往之不谏 知来者之可追
一言
今日诗词
站点信息
本站访客数 :
本站总访问量 :