SpringMVC(一)

SpringMVC(一)

SpringMVC的基本概念
  • 三层架构

    • 表现层
    • 业务层
    • 持久层
  • MVC模型

    • Model(模型):通常就是指我们的数据模型,一般情况下用于封装数据。
    • View(视图):通常指的就是我们的jsp或者html,一般用于展示数据。通常视图依据数据模型创建。
    • Controller(控制器):是应用程序中处理用户交互的部分,一般用于处理程序逻辑。
  • SpringMVC :是一种基于 java 的实现 MVC 设计模型的请求驱动类型的轻量级 web 框架,属于Spring Framework 的后续产品,已经融合在Spring Web Flow中。spring框架提供了构建Web应用程序的全功能MVC模块。

  • 它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无需实现任何接口,同时它还支持Restful 编程风格的请求。

  • 优势:

    • 清晰的角色划分
      • 前端控制器(DispatcherServlet)
      • 请求到处理器映射(HandlerMapping)
      • 处理器适配器(HandlerAdapter)
      • 视图解析器(ViewResolver)
      • 处理器或页面控制器(Controller)
      • 验证器(Validator)
      • 命令对象(Command 请求参数绑定到的对象就叫命令对象)
      • 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)
    • 分工明确,扩展灵活
    • 由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象。
    • 和 spring 其他框架无缝集成,是其他 web 框架所不具备的。
    • 可适配。通过 HandlerAdapter 可以支持任意的类作为处理器。
    • 可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。
    • 功能强大的数据验证、格式化、绑定机制。
    • 利用spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
    • 本地化、主题的解析的支持,使我们更容易的进行国际化和主题的切换。
    • 强大的 JSP 框架,使 JSP 编写更加容易。
    • Restful 风格的支持,简单的文件上传,约定大于配置的契约式编程支持,基于注解的零配置支持等等。
  • SpringMVCStruts2 的优劣分析:

    • 共同点:

      • 他们都是表现层框架,都是基于 MVC 模型编写的。
      • 他们的底层都离不开原始 ServletAPI。
      • 他们处理请求的机制都是一个核心控制器。
    • 区别:

      • springMVC 的入口是 Servlet,而 Struts2 是 Filter。
      • SpringMVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所以SpringMVC(单例) 会稍微比 Struts2(多例) 快些。
      • SpringMVC使用更加简洁,同时还支持JSR303(一套JavaBean 参数校验的标准,定义了很多常用的校验注解),处理 ajax 的请求更方便。
      • struts2 的 OGNL 表达式使页面的开发效率相比 SpringMVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 HTML 执行效率高。
SpringMVC的入门
  • 需求:

    • index.jsp (包含一个超链接标签)——> 发送请求 ——> 编写类、方法 ——> 转发到成功 jsp 页面

SpringMVC

  • 实现:

    • 搭建开发环境

      • 在pom.xml中引入依赖
      • 配置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:springmvc.xml</param-value>
          </init-param>
          <!--设置启动时就加载-->
          <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
          <servlet-name>dispatcherServlet</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
      
      • 配置springmvc.xml
      <!--IOC开启注解扫描-->
      <context:component-scan base-package="com.ssm"></context:component-scan>
      
      <!--视图解析器对象-->
      <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <!--文件所在目录-->
          <property name="prefix" value="/WEB-INF/pages/"/>
          <!--文件后缀名-->
          <property name="suffix" value=".jsp"/>
      </bean>
      
      <!--开启springMVC框架的注解支持-->
      <mvc:annotation-driven/>
      
    • 编写入门程序

    //控制器类
    @Controller
    public class HelloController {
        @RequestMapping(path = "/hello")
        public String sayHello(){
            System.out.println("Hello SpringMVC");
            return "success";
        }
    }
    
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>入门程序</h3>
        <a href="hello">入门程序</a>
    </body>
    </html>
    
    • @RequestMapping

      • 如果出现在类上,表示请求URL的一级访问目录,不写则默认根目录,他的出现是为了使我们的url可以按照模块化管理。
      • 如果出现在方法上,表示请求URL的二级访问目录。
      • 属性:

      value:用于指定请求的URL。他和path属性作用一样。

      method:用于指定请求的方式。

      params:用于指定限制请求参数的条件。支持简单表达式,要求参数的key和value必须和配置一模一样。

      headers:用于指定限制请求消息头的条件。

请求参数的绑定
  • 设置方法参数名与配置一样
@Controller
@RequestMapping("/param")
public class ParamController {
    /**
     * 请求参数的绑定
     * @return
     */
    @RequestMapping("/testParam")
    public String testParam(String username,String password){
        System.out.println("执行了……");
        System.out.println("用户名:" + username);
        System.out.println("密码:" + password);
        return "success";
    }
}
<%--此处username和password必须与controller中方法参数名一样--%>
<body>
    <a href="param/testParam?username=jinlu&password=123">请求参数的绑定</a>
</body>
</html>
  • 把数据封装到Account类(JavaBean)中,类中存在对象引用、list、map集合等
/**
     * 请求参数绑定把数据封装到JavaBean的类中
     * @param account
     * @return
     */
@RequestMapping("saveAccount")
public String saveAccount(Account account){
    System.out.println("执行……");
    System.out.println(account);
    return "success";
}
<%--把数据封装到Account类中,类中存在对象引用--%>
<form action="param/saveAccount" method="post">
    姓名:<input type="text" name="username"/><br/>
    密码:<input type="text" name="password"/><br/>
    金额:<input type="text" name="money"/><br/>
    用户:<input type="text" name="user.uname"/><br/>
    年龄:<input type="text" name="user.age"/><br/>
    <input type="submit" value="提交"/>
</form>
<%--把数据封装到Account类中,类中存在list和map集合--%>
<form action="param/saveAccount" method="post">
    姓名:<input type="text" name="username"/><br/>
    密码:<input type="text" name="password"/><br/>
    金额:<input type="text" name="money"/><br/>
    用户:<input type="text" name="list[0].uname"/><br/>
    年龄:<input type="text" name="list[0].age"/><br/>
    用户:<input type="text" name="map['one'].uname"/><br/>
    年龄:<input type="text" name="map['one'].age"/><br/>
    <input type="submit" value="提交"/>
</form>
  • 自定义类型转换器

    • 当实体类中含有如Date类型数据时,在jsp页面必须填写yyyy/mm/dd格式,如果写成yyyy-mm-dd则会出错,无法转换日期类型,因为在jsp页面上的数据其实都是以 String 类型返回的。
    • 自定义类型转换类及其方法:(必须实现接口Converter)
    public class StringToDateConverter implements Converter<String,Date> {
        /**
         *  自定义类型转换
         * @param s 传入的字符串
         * @return
         */
        @Nullable
        @Override
        public Date convert(String s) {
            //判断
            if (s == null){
                throw new RuntimeException("请您传入数据");
            }
            DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
            try {
                //把字符串转换为日期
                return df.parse(s);
            } catch (Exception e) {
                throw new RuntimeException("数据类型转换出错");
            }
        }
    }
    

    配置自定义类型转换器:springmvc.xml

    <!--自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.ssm.utils.StringToDateConverter"/>
            </set>
        </property>
    </bean>
    <!--开启springMVC框架的注解支持-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    
  • 获取Servlet 原生API

/**
     * 获取Servlet原生API
     * @return
     */
@RequestMapping("testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response){
    System.out.println("执行……");
    System.out.println(request);
    HttpSession session = request.getSession();
    System.out.println(session);
    ServletContext context = session.getServletContext();
    System.out.println(context);
    System.out.println(response);
    return "success";
}
常用注解
  • @RequestParam

    • 作用:把请求中指定名称的参数给控制器中的形参赋值
    • 属性:
      • value:请求参数中的名称
      • required:请求参数中是否必须提供此参数,。默认为true,表示必须提供,如果不提供将报错。
    @RequestMapping("/testRequestParam")
    public String testRequestParam(@RequestParam(name = "uname") String username){
        System.out.println("执行了……");
        System.out.println(username);
        return "success";
    }
    
    <a href="anno/testRequestParam?uname=hah">requestParam注解</a>
    
  • @RequestBody

    • 作用:用于获取请求体内容,直接使用得到是key=value&key=value……结构的数据。get请求方式不适用。
    • 属性:
      • required:是否必须有请求体,默认值为true,当取值为true时,get请求方式会报错。如果取值为false,get请求得到的是null。
    @RequestMapping("/testRequestBody")
    public String testRequestBody(@RequestBody String body){
        System.out.println("执行了……");
        System.out.println(body);
        return "success";
    }
    
    <form action="anno/testRequestBody" method="post">
        用户姓名:<input type="text" name="username"><br/>
        用户年龄:<input type="text" name="age"><br/>
        <input type="submit" value="提交">
    </form>
    
  • PathVariable

    • 作用:用于绑定url中的占位符,例如:请求url中的 /delete/{id},这个 {id} 就是url的占位符。url 支持占位符是spring3.0 之后加入的。是springmvc 支持restful 风格 url 的一个重要标志。
    • 属性:
      • value:用于指定 url 中的占位符名名称。
      • required:是否必须提供占位符。
    @RequestMapping("/testPathVariable/{sid}")
    public String testPathVariable(@PathVariable(name = "sid") String id){
        System.out.println("执行了……");
        System.out.println(id);
        return "success";
    }
    
    
    <a href="anno/testPathVariable/10">PathVariable注解</a>
    
    
  • @RequestHeader

    • 作用:用于获取请求消息头。
    • 属性:
      • value:提供消息头名称
      • required:是否必须有此消息头。
    @RequestMapping("/testRequestHeader")
    public String testRequestHeader(@RequestHeader(value = "Accept") String header){
        System.out.println("执行了……");
        System.out.println(header);
        return "success";
    }
    
    
  • @CookieValue

    • 作用:用于把指定cookie 名称的值传入控制器方法参数。
    • 属性:
      • value:指定cookie的名称
      • required:是否必须有此cookie
    @RequestMapping("/testCookieValue")
    public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookieValue){
        System.out.println("执行了……");
        System.out.println(cookieValue);
        return "success";
    }
    
    
  • @ModelAttribute

    • 作用:
      • 出现在方法上:表示当前方法会在控制器的方法前先执行。他可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
      • 出现在参数上:获取指定数据的给参数赋值。
    • 属性:
      • value:用于获取数据的key。key可以是POJO的属性名称,也可以是map结构的key。
    • 应用场景:
      • 当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库原来的数据。
      • 例如:我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数据时肯定没有此字段的内容,一旦更新会把该字段的内容置为null,此时就可以使用此注解解决问题。
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(User user){
        System.out.println("testModelAttribute执行了……");
        System.out.println(user);
        return "success";
    }
    //该方法会先执行
    @ModelAttribute
    public User showUser(String uname){
        System.out.println("showUser执行了……");
        //通过uname查询数据库(模拟)
        User user = new User();
        user.setUname(uname);
        user.setAge(20);
        user.setDate(new Date());
        return user;
    }
    
    
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("abc") User user){
        System.out.println("testModelAttribute执行了……");
        System.out.println(user);
        return "success";
    }
    //该方法会先执行
    @ModelAttribute
    public void showUser(String uname, Map<String,User> map){
        System.out.println("showUser执行了……");
        //通过uname查询数据库(模拟)
        User user = new User();
        user.setUname(uname);
        user.setAge(20);
        user.setDate(new Date());
        map.put("abc",user);
    }
    
    
  • @SessionAttribute

    • 作用:用于多次执行控制器方法间的参数共享。只能作用在类上。
    • 属性:
      • value:用于指定存入的属性名称。
      • type:用于指定存入的数据类型。
    //在类上添加
    @SessionAttributes(value = "msg")   //把 msg=靳璐 存入到 session 域对象中
    
    
    //存入值
    @RequestMapping("/testSessionAttributes")
    public String testSessionAttributes(Model model){
        System.out.println("testSessionAttributes执行了……");
        model.addAttribute("msg","靳璐");
        return "success";
    }
    
    //获取值
    @RequestMapping("/getSessionAttributes")
    public String getSessionAttributes(ModelMap modelMap){
        System.out.println("getSessionAttributes执行了……");
        String str = (String) modelMap.get("msg");
        System.out.println(str);
        return "success";
    }
    
    //删除值
    @RequestMapping("/delSessionAttributes")
    public String delSessionAttributes(SessionStatus status){
        System.out.println("delSessionAttributes执行了……");
        status.setComplete();
        return "success";
    }
    
    

    success.xml

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>成功!!!</h3>
        ${requestScope.msg}
        ${sessionScope}
    </body>
    </html>
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值