springMVC入门

1、MVC设计概述

MVC(Model-View-Controller)模式是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。MVC可对程序的后期维护和扩展提供方便,也为程序某些部分的重用提供了方便。

MVC 设计模式并不是Java Web应用的专属,几乎现在所有 B/S 结构的软件都采用了MVC 设计模式:在早期的 Java Web 开发中,主要是JSP+Java Bean模式,如图所示。服务器端只有JSP页面,所有操作都在JSP页面中,严重的耦合度增加了开发的难度,对后期的维护和扩展极其不利。

springMVC入门_第1张图片
 

2、Spring MVC

首先,Spring MVC框架是围绕着Dispatche Servlet工作的,这个是其核心美,其实它本质是一个Servlet,因此它可以拦截HTTP 发送过来的请求,在Servlet初始化时,Spring MVC 会根据配置,获取配置信息,从而得到统一资源标识符(URL,Uniform Resource Identifier)和处理器(Handler)之间的映射关系(Ha adlerMapping),为了使用更加灵活,且能增强功能,Spring MVC还会给处理器加入拦截器,所以还可以在处理器执行前后加入自己的代码,这样就构成了一个处理器的执行链(Handl er Execution Chain),并且根据上下文初始化视图解析器等内容,当处理器返回的时候就可可以通过视图解析器定位视图,然后将数据模型渲染到视图中,以响应用户的请求。

Spring MVC的核心在于其流程,这是使用 Spring MVC框架的基础,Spring MVCH一种基Servlet 的技术,它提供了核心控制器 DispatcherServlet 和相关的组件,并制定了松散的结构,以适应各种灵活的需求。其流程图如图所示。

springMVC入门_第2张图片

具体的步骤如下:

  • 第一步:发起请求到前端控制器(Dispatcherervet)
  • 第二步:前端控制器请求HandlerMapping查找Hande可以把注解进行查找)
  • 第三步:处理器映射器HandlerMapping控制器andleHanderMapping合把请水映射为HandlerExecutionChain 对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映时策略
  • 第四步:前端控制器调用处理器适配器上执行 Handiers
  • 第五步:处理器适配器HandlerAdapter将会根据适配的结渠执行Handker
  • 第六步:Handler 执行完成给适配器返回ModelAndView。
  • 第七步:处理器适配器向前端控制器返回ModelAndView(ModelAndView是 Spring MvC框架的一个底层对象,包括Model 和View)。
  • 第八步:前端控制器请求视图解析器进行视图解析(根据逻辑视图名解析成真正的视图(Jsp)),通过这种策略很容易更换其他视图技术,只更改视图解析器即可。
  • 第九步:视图解析器向前端控制器返回 View。
  • 第十步:前端控制器进行视图渲染(视图渲染将模型数据(在ModelAndView对象中)填充到 request 域)。
  • 第十一步:前端控制器向用户响应结果。

以上就是一个 Spring MVC完整的流程,它是一个松散的结构,所以可以满足各类请求的需要,为此它也实现了大部分请求所需的类库,拥有较为丰富的类库供使用,所以流程中大部分组件并不需要用户去实现。 

3、springMVC入门实例

1、创建web项目并导入jar包

springMVC入门_第3张图片springMVC入门_第4张图片

2、 index.jsp页面中创建一个a标签,执行一个地址请求

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    首页
  
  
  

欢迎来到项目首页

请求测试

zhuye.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    项目主页


SpringMVC的项目主页!

3、在web.xml中配置springMVC的核心控制器DispatcherServlet,同时设置它创建的时候加载

springmvc 的核心配置文件 springmvc.xml


    
    
        dispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        
        
            contextConfigLocation
            classpath:springmvc.xml
        
        
        1
    
    
        dispatcherServlet
        /
    

关于web.xml中的一些配置解释如下。
①contextConfigLocation:用于指定配置文件的位置。如果有多个配置文件,以逗号
隔开;如果没有指定配置文件,Spring监听器会自动查找/WEB-INF/路径下applicationContext.xml配置文件。

②ContextLoaderListener:它是Spring提供的监听器,实现了 ServleiCon接口。由它来查找 Spring 的配置文件,完成对 Spring 的初始化。

③ DispatcherServlet:它是Spring的核心控制器,其初始化属性配置用于指定spring的配置文件位置。如果没有进行初始化配置,其默认的配置文件在/WEB-INF 路径下,名称为配置的servlet-name连上-servlet.xml。例如servlet-name为dispatcher,则配置文件名称为dispatcher-servlet.xml。

④ servlet-mapping:它是 servlet拦截配置,servlet-name 需要和上面配置的servict中的servlet-name 一致。是拦截指定形式的请求,例如这里配置的是“”,则会拦截所有路径型的url;如果配置的是*.do,则会拦截所有以后缀“do”结尾的请求。

4、src目录下创建核心配置文件springmvc.xml,扫描控制器的包、配置视图解析器、开启注解驱动支持(默认配置 HandlerMapping映射器 和 HandlerAdapter 适配器)



    
    
    
    
        
        
        
        
    
    
    
    

关于springmvc.xml 中的一些配置解释如下。
:表示使用注解驱动 Spring MVC。
:定义要扫描注解的包。    
InternalResourceViewResolver:定义视图解析器,解析器中定义了前缀和后缀,这样视图就知道去 Web 工程的/WEB-INF view 文件夹中找到对应的 JSP 文件作为视图响应用户请求。
:为了避免拦截器将一些静态资源也给拦截了,通过属性 location和mapping就可以让拦截器对指定目录下的资源不进行拦截。

5、书写处理器,即我们的 Controller ,首先把类使用 @Controller 标识,标识该类交给 IOC 容器管理,其次在方 法上指定映射关系;
@Controller
public class TestController{
    @RequestMapping("/test")
    public String test(){
        //处理test请求
        System.out.println("TestController......test");
        //做出响应,直接返回视图的名字,视图解析会在指定目录中找到指定后缀的 该视图页面响应给前端页面
        return "zhuye";
    }
}

 测试结果

 springMVC入门_第5张图片

3.1 、RequestMapping注解

在Spring MVC 应用程序中,RequestDispatcher 这个 Servlet 负责将进入的 HTTP 请求路由到控制器的处理方法。
在对Spring MVC 进行配置的时候,需要指定请求与处理方法之间的映射关系。要配置Web请求的映射,就需要用到@RequestMapping 注解。

控制器的开发
控制器开发是Spring MVC的核心内容,主要分为以下三个步骤。

(1) 获取请求参数。

(2)处理业务逻辑。

(3)绑定模型和视图。 

3.2、请求参数的绑定

使用 ServletAPI 对象作为方法参数

SpringMVC 还支持使用原始 ServletAPI 对象作为控制器方法的参数。

    @RequestMapping("/login")
    //可以使用原生态的servlet API 进行处理
    public void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("UserController......login");
        String username = request.getParameter("username");
        System.out.println(username);
        response.sendRedirect("zhuye.jsp");
    }

普通参数的绑定

  • Spring MVC绑定请求参数是自动实现的,只要满足下面的规则即可。
  • 基本数据类型或 String 类型:要求参数名称必须和控制器中的方法的形参名称保持一致。(严格区分大小写)
  • POJO 类型:要求表单中的参数名称和POJO 类的属性名称保持一致,并且控制器方法的参数类型是POJO类型。
  • 集合类型:要求集合类型的请求参数必须在 POJO 中。在表单中的请求参数名称要和POJO中的集合属性名称相同。如果是给List集合中的元素赋值,则使用下标;如果给Map 集合中的元素赋值,则使用键值对。下面针对这几种情况进行示例演示。 

使用要求

  • 基本类型或者 String 类型:要求我们的参数名称必须和控制器中方法的形参名称保持一致。 (严格区分大小写)
  • POJO 类型,或者它的关联对象:要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。

集合类型,有两种方式:

第一种:

  • 要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
  • 给 List 集合中的元素赋值, 使用下标。
  • 给 Map 集合中的元素赋值, 使用键值对。

 第二种:

  • 接收的请求参数是 json 格式数据。需要借助一个注解实现。

基本类型参数:包括基本类型和 String 类型

请求地址提供请求参数:username、password。

    @RequestMapping("/login")
    public String login(String username,String password){
        System.out.println("UserController......login");
        System.out.println(username);
        System.out.println(password);
        return "zhuye";
    }

POJO 类型参数:实体类
在jsp页面中添加一个表单,并创建对应的实体类User(name与参数名称一致)

    @RequestMapping("/login")
    public void login(User user){
        //定义实体类,类的属性和请求参数的name属性一致,就会自动获取数据并封装到实体类中
        System.out.println("UserController......login");
        System.out.println(user);
    }

可以在控制器的参数中通过@ReqeustParam指定URL传递参数名称

@RequestParam 可以手动指定请求参数和参数的数据绑定 required 表示请求是必须传递该参数

关于@RequcstParam中的属性配置解释如下。    
required:值类型为布尔值,默认值为true,表示不允许参数为空,如果要允许为空,则设置为false。
defaultValue:当参数为空时候的默认值。

注意:注解@RequestParam可以对自定义简单类型的参数进行绑定,即如果使用@RequestParam,就无须设置controller方法的形参名称与request传入的参数名称一致。而不使用@RequestParam注解时,就要求controller方法的形参名称与request传入的参数名称一致,这样才能绑定成功。  

    @RequestMapping("/login")
    public String login(@RequestParam(value = "username",required = true)String name,String password){
        //@RequestParam 可以手动指定请求参数 和 参数的数据绑定 required 表示请求是必须传递该参数
        System.out.println("UserController......login");
        System.out.println(name);
        System.out.println(password);
        return "zhuye";
    }

如果要求绑定的参数一定不能为空,可以使用@RequestParam注解中的required属性来指定该形参是否必须传入,required属性为“true”指定参数必须传入。 

    @RequestMapping("/del")
    public String del(@RequestParam(required = true)Integer id){
        System.out.println("UserController......del");
        System.out.println(id);
        return "zhuye";
    }

ReuqestBody 主要是处理json串格式的请求参数,要求使用方指定header content-type:application/json
RequestBody 通常要求调用方使用post请求 

@RequestBody 只支持post请求,把数据变成key=value...结构的数据

@RequestMapping("/save")
    public String save(@RequestBody String data) {
        //@RequestBody 只支持post请求,把数据变成key=value...结构的数据
        System.out.println("UserController......save");
        System.out.println(data);
        return "zhuye";
    }

save.jsp 页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


帐号:
密码:
年龄:

 请求参数中文乱码的解决

  • Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
  • Filter 过滤器它是 JavaEE 的规范。也就是接口
  • Filter 过滤器它的作用是:拦截请求,过滤响应。

到 web.xml 中去配置 Filter 的拦截路径


    
        encodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
    
    
        encodingFilter
        /*
    

3.3、保存并获取属性参数

  • @RequestAttribute:获取HTTP 的请求(Request)对象属性值,用来传递给控制器的参数。
  • @SessionAttribute:在HTTP的会话(Session)对象属性值中,用来传递给控制器的
  • @SeasionAttributes:可以将数据模型中的数据存储到 Session 中。

4、转发和重定向

请求转发 :浏览器发送了一次请求,在服务器内部转发了一次;请求了一次,页面地址不会变化;

request.getRequestDispatcher("zhuye.jsp").forward(request,response);

重定向 :浏览器发送了一次请求,服务器让浏览器再去请求一次;请求了两次,页面地址会变化;

response.sendRedirect("zhuye.jsp");

springMVC的响应方式:请求转发

SpringMVC中可以使用两种方式进行重定向和转发: 

servlet的请求转发(forward)和重定向(sendRedirect)

使用ModelAndView对象进行转发和重定向

在Controller中,可以使用ModelAndView对象进行转发和重定向。使用ModelAndView对象进行转发时,可以将数据添加到ModelAndView对象中,然后将其返回给DispatcherServlet

DispatcherServlet会将其转发到指定的页面。使用ModelAndView对象进行重定向时,需要设置重定向的URL,然后将其返回给DispatcherServlet,DispatcherServlet会将其重定向到指定的URL。

@RequestMapping("/login1")
    public ModelAndView login1(User user){
        ModelAndView mv = new ModelAndView();
        System.out.println("UserController......login");
        System.out.println(user);
        //存储数据,默认存入request作用域
        mv.addObject("data","后端响应的数据");
        //指定响应的视图,执行的是请求转发
        mv.setViewName("zhuye");
        //请求转发和重定向使用关键词后不会再经过视图解析器,所以需要明确 位置/页面名.后缀
        //mv.setViewName("forward:/zhuye.jsp");
        //mv.setViewName("redirect:/zhuye.jsp");
        return mv;
    }
}

 GoodsController类

@Controller
public class GoodsController {
    @RequestMapping("/findAll")
    public ModelAndView findAll(){
        ModelAndView mv = new ModelAndView();
        //查询商品信息
        List goodsList = new ArrayList<>();
        Goods g1 = new Goods();
        g1.setGid(1);
        g1.setGname("泡面");
        g1.setPrice(4.5);

        Goods g2 = new Goods();
        g2.setGid(2);
        g2.setGname("可乐");
        g2.setPrice(3.5);

        Goods g3 = new Goods();
        g3.setGid(3);
        g3.setGname("火腿肠");
        g3.setPrice(6.5);

        goodsList.add(g1);
        goodsList.add(g2);
        goodsList.add(g3);

        mv.addObject("goodsList",goodsList);
        mv.setViewName("zhuye");

        return mv;
    }
}
@Controller
public class UserController {
    @RequestMapping("/login")
    public ModelAndView login(User user){
        ModelAndView mv = new ModelAndView();
        System.out.println(user);
        if(user.getUsername().equals("admin") && user.getPassword().equals("666")){
            //我们重定向到商品查询
            mv.setViewName("redirect:/findAll");//重定向请求 /findAll 这个地址
        }else{
            mv.addObject("error","用户名或密码错误!");
            mv.setViewName("error");
        }
        return mv;
    }
}

 5、静态资源处理

页面插入图片 

 

在springmvc.xml配置文件中配置

mapping:指定静态资源的映射

location:指定静态资源的文件目录


    
    
    

6、拦截器

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

拦截器的定义

Spring MVC拦截器的实现一般有两利方式:第一种方式是要定义的Interceptor类要实现 Spring 的 HandlerInterceptor 接口;    第二种方式是继承实现了HandlerInterceptor接口的类,比如Spring已经提供的实现了HandlerInterceptor接口的抽象类HandlerInterceptorAdapter


    
        
            
            
        
    

接口中定义了三个方法,其含义解释如下。

  • preHandle:在处理器之前执行的前置方法,如果该方法返回 true,则请求继续向下进行,否则请求不会继续向下进行,处理器也不会被调用。    
  • postHandle:在处理器之后执行的后置方法。
  • afterCompletion:只要该拦截器中的pr eHandle 方法返回 true,该方法就会在渲染视图后被调用。

注:拦截器中的前置方法返回值决定了后续的流程是否执行,同时需要注意的是后置方法postHandle是在handler方法(Controller)成功执行之后、dispatcher渲染视图之前执行。因此如果handler 方法抛出异常,则 postHandle也是不会执行的。但 afterCompletion 只要前置方法返回true,后面无论是否抛出异常,都会在视图渲染结束后执行。 

从输出结果可以看出,当其中一个前置方法返回false,那么后面的前置方法、控制器方法、后置方法都不会执行,只有对应返回true的拦截器的完成方法(afterCompletion)才会逆序执行。

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor......preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor......postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor......afterCompletion");
    }
}

未登录拦截的原理

判断用户是否登录(首先登录时需要把用户信息存入session,后续只要判断session中是否存在用户信息),如果没有登录则拦截。

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor......preHandle(前置通知)");
        //登录请求不拦截,其它请求查看session域
        String servletPath = request.getServletPath();
        if(servletPath.equals("/login")){
            return true;
        }else{
            //获得session域中的user对象
            User user = (User) request.getSession().getAttribute("user");
            if(user!=null){
                return true;
            }else{
                return false;
            }
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor......postHandle(后置通知)");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor......afterCompletion(最终通知)");
    }
}

拦截 

你可能感兴趣的:(前端,java,servlet)