二:SpringMVC

异常码:

405:请求不允许

404:资源不存在

400:参数有问题

500:代码有问题

SpringMvc是Spring FrameWork提供的WEB组件,是目前的主流的实现MVC设计模式的框架,提供前端的路由映射、视图解析等

java web 开发者必要的框架

Spring mvc 功能

部分概念

MVC :

MVC 设计模式一般指 MVC 框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。使用 MVC 的目的是将 M 和 V 的实现代码分离,使同一个程序可以有不同的表现形式。其中,View 的定义比较清晰,就是用户界面。

  • 视图层(View):负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、界面设计等功能。

  • 控制层(Controller):负责接收并转发请求,对请求进行处理后,指定视图并将响应结果发送给客户端。

  • 数据模型层(Model):模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务规则)的处理和实现数据操作(即在数据库中存取数据)。

  • JSP+JavaBean

  • Servlet+JSP+JavaBean

    优点

  • 多视图共享一个模型,大大提高了代码的可重用性

  • MVC 三个模块相互独立,松耦合架构

  • 控制器提高了应用程序的灵活性和可配置性

  • 有利于软件工程化管理

    缺点

  • 原理复杂

  • 增加了系统结构和实现的复杂性

  • 视图对模型数据的低效率访问

SpringMvc的组件:

1)DispatcherServlet

DispatcherServlet 是前端控制器,从图 1 可以看出,Spring MVC 的所有请求都要经过 DispatcherServlet 来统一分发。DispatcherServlet 相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。

2)HandlerMapping

HandlerMapping 是处理器映射器,其作用是根据请求的 URL 路径,通过注解或者 XML 配置,寻找匹配的处理器(Handler)信息。

3)HandlerAdapter

HandlerAdapter 是处理器适配器,其作用是根据映射器找到的处理器(Handler)信息,按照特定规则执行相关的处理器(Handler)。

4)Handler

Handler 是处理器,和 Java Servlet 扮演的角色一致。其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至 ModelAndView 对象中。

5)View Resolver

View Resolver 是视图解析器,其作用是进行解析操作,通过 ModelAndView 对象中的 View 信息将逻辑视图名解析成真正的视图 View(如通过一个 JSP 路径返回一个真正的 JSP 页面)。

6)View

View 是视图,其本身是一个接口,实现类支持不同的 View 类型(JSP、FreeMarker、Excel 等)。

7)HandlerExecutionChain:处理器执行链(包括两部分Handler和HandlerInterceptor)

SpringMVC 的执行流程如下

  1. 用户点击某个请求路径,发起一个 HTTP request 请求,该请求会被提交到 DispatcherServlet(前端控制器);
  2. 由 DispatcherServlet 请求一个或多个 HandlerMapping(处理器映射器),并返回一个执行链(HandlerExecutionChain)。
  3. DispatcherServlet 将执行链返回的 Handler 信息发送给 HandlerAdapter(处理器适配器);
  4. HandlerAdapter 根据 Handler 信息找到并执行相应的 Handler(常称为 Controller);
  5. Handler 执行完毕后会返回给 HandlerAdapter 一个 ModelAndView 对象(Spring MVC的底层对象,包括 Model 数据模型和 View 视图信息);
  6. HandlerAdapter 接收到 ModelAndView 对象后,将其返回给 DispatcherServlet ;
  7. DispatcherServlet 接收到 ModelAndView 对象后,会请求 ViewResolver(视图解析器)对视图进行解析;
  8. ViewResolver 根据 View 信息匹配到相应的视图结果,并返回给 DispatcherServlet;
  9. DispatcherServlet 接收到具体的 View 视图后,进行视图渲染,将 Model 中的模型数据填充到 View 视图中的 request 域,生成最终的 View(视图);
  10. 视图负责将结果显示到浏览器(客户端)。

SpringMvc 的具体使用

1.导入依赖:

<!--    springMvc依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.3.RELEASE</version>
    </dependency>
  </dependencies>

2.在web.xml中配值SpringMvc 的DispatchServlet

<servlet>
  <servlet-name>springmvc</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>springmvc</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

3.Springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--    配置扫包-->
    <context:component-scan base-package="com.southwind.controller"></context:component-scan>
    <!--    视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--        前缀-->
        <property name="prefix" value="/"></property>
<!--        后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

4.创建Handller

package com.southwind.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.xml.ws.RequestWrapper;

@Controller
public class HellowHandler {
    @RequestMapping ("/index")
    public String index(){
        System.out.println("接受到了请求");
        //返回逻辑视图
        return  "index";
    }
}

流程梳理:

1.DispatcherServlet接收到url请求index,结合@RequestMapping("/index")注解将该请求交给index业务处理

2.执行index业务方法,控制台打印日志,并返回”index“字符串

3.组合springmvc.xml中的视图解析器配置,找到对应的资源;/index.jsp, 即根目录下的index.jsp文件,将该文件的jsp资源返回客户端。

搭建成功;

SpringMvc的常用注解

@RequestMapping()

SpringMvc通过@RequestMapping注解将URL请求与业务的方法进行映射,在控制器的类定义处定义方法处都可以添加@RequestMapping,在类定义处添加相当于多了一层访问路径。

  • value :指定URL请求的地址,是@RequestMapping的默认值。

  • method:请求的method类型包括 GET POST PUT DELETE

  • params 请求的参数

    @Controller
    public class HellowHandler {
      @RequestMapping (value = "/index",params = {"id=1","name=tom"})
      public String index(){
          System.out.println("接受到了请求");
          //返回逻辑视图
          return  "index";
      }
    }

参数绑定

params是对URL请求参数进行限制,不满足的URL不能访问,需要在业务方法中获取URL的参数值。

1.在业务方法定义时声明参数列表

2.给参数列表添加@RequsetParam 注解进行绑定

@Controller
public class HellowHandler {
    @RequestMapping (value = "/index",params = {"id"})
    public String index(@RequestParam("id") double id){
        System.out.println("接受到了请求"+"id="+id);
        //返回逻辑视图
        return  "index";
    }
}

Springmvc也支持RESTful风格的URL传参

@RequestMapping (value = "/index/{id}")
public String index1(@PathVariable("id") double id){
    System.out.println("接受到了请求"+"id="+id);
    //返回逻辑视图
    return  "index";
}

映射Cookie

@RequestMapping (value = "/Cookie")
public String index2(@CookieValue("JSESSIONID") String session){
    System.out.println("接受到了请求"+"session="+session);
    //返回逻辑视图
    return  "index";
}

使用POJO绑定参数

Springmvc会自动更据请求参数与POJO的属性名匹配,自动为该对象填充属性值,并支持属性级联。

乱码

<!--    过滤器-->
<filter>
  <filter-name>encodingFilter</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>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

User:

package com.southwind.entity;

import lombok.Data;

@Data
public class User {
    private  Integer id;
    private  String name;
    private  Address address;
}

Address;

package com.southwind.entity;

import lombok.Data;

@Data
public class Address {
    private  Integer code;
    private  String name;
}

jsp:

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-06
  Time: 17:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/add">
        <table>
            <tr>
                <td>编号:</td>
                <td>
                    <input type="text" name="id">
                </td>
            </tr>
            <tr>
                <td>姓名:</td>
                <td>
                    <input type="text" name="name">
                </td>
            </tr>
            <tr>
                <td>地址编号:</td>
                <td>
                    <input type="text" name="address.code">
                </td>
            </tr>
            <tr>
                <td>地址信息:</td>
                <td>
                    <input type="text" name="address.name">
                </td>
            </tr>
            <tr>
                <td>
                    <input type="submit" value="提交">
                </td>
            </tr>
        </table>
    </form>
</body>
</html>

controller:

@RequestMapping("/add")
public String add(User user){
    System.out.println(user);
    return "addUser";
}

JSP页面的转发和重定向

转发是服务器行为,重定向是客户端行为。转发耗时比重定向少。

转发——>客户浏览器发送HTTP请求——>web服务器接受请求——>调用内部一个方法在容器内部完成请求处理和转发动作——>再将转发跳转到的那个网页资源返回给客户; 转发只能在同一个容器内完成 转发的时候浏览器地址是不会变的,在客户浏览器里只会显示第一次进入的那个网址或者路径,客户看不到这个过程,只是得到了想要的目标资源。转发行为浏览器只做了一次请求。(转发只能跳转一次)

重定向——>客户浏览器发送HTTP请求——>web服务器接受请求后发送302状态码以及新的位置给客户浏览器——>客户浏览器发现是302响应,则自动再发送一个新的HTTP请求,请求指向新的地址(302:Found 临时移动,但资源只是临时被移动。即你访问网址A,但是网址A因为服务器端的拦截器或者其他后端代码处理的原因,会被重定向到网址B。)——>服务器根据此请求寻找资源发个客户;再客户浏览器中显示的是重定向之后的路径,客户可以看到地址的变化。重定向行为浏览器做了至少两次请求。(重定向可以跳转多次

SpringMVC默认是以转发,(地址栏没有改变0

重定向:redirect

@RequestMapping("/add")
public String add(User user){
    System.out.println(user);
    return "redirect:/addUser.jsp";
}

转发;forward

SpringMVC的数据绑定:

在后端直接得到前端的HTTP中的数据。

HTTP请求中的传输的参数都是String类型,Handler业务方法中的参数是开发者指定的数据类型,int Integer,,因此要进行数据类型的绑定

由HabderAdapter完成参数的绑定:

  • 基本数据类型:

    @RequestMapping("/baseType")
    @ResponseBody
    public String baseType(int id){

      return "id="+id;
    }

请求必须由id参数,否则500错误,同时id的值 , 必须为数值不然为400异常。

  • 包装类

    @RequestMapping("/baseType1")
    @ResponseBody
    public String baseType(Integer id){

      return "id="+id;
    }

请求必须由id参数,否则500错误,同时id的值 , 必须为数值不然为400异常。不传为null。

  • 利用@RequestParam处理参数(设置默认值)

    @RequestMapping("/baseType1")
    @ResponseBody
    public String baseType(@RequestParam(value = "id",required = true,defaultValue = "0") Integer id){

      return "id="+id;
    }
  • 数组

    @RequestMapping("/arrayType")
    @ResponseBody
    public  String arrayType(String[] names){
      StringBuffer stringBuffer =new StringBuffer();
      for(String str:names){
          stringBuffer.append(str).append(" ");
      }
      return "names: "+stringBuffer.toString();
    }
  • POJO

    package com.southwind.entity;

    import lombok.Data;

    @Data
    public class User {
      private  Integer id;
      private  String name;
      private  Address address;
    }
    @RequestMapping("/add")
    public String add(User user){
      System.out.println(user);
      return "redirect:/addUser.jsp";
    }

乱码;

<mvc:annotation-driven>
    <!--        消息转换器-->
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes" value="text/html;charset=utf-8"></property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

List

SpringMVC不支持直接转换Lis类型,需要包装成Object

List的自定义包装类

控制类:

@RequestMapping("/listType")
@ResponseBody
public String listType(UserList users){
    StringBuffer stringBuffer =new StringBuffer();
    for(User user:users.getList()){
        stringBuffer.append(user);
    }
    return "用户"+stringBuffer.toString();
}

实体类:

package com.southwind.entity;

import lombok.Data;

import java.util.List;
@Data
public class UserList {
    private List<User> list;
}

jsp

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-06
  Time: 17:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/listType">
    <input type="text" name="list[0].id">
    <input type="text" name=" list[0].name">
    <input type="text" name="list[1].id">
    <input type="text" name=" list[1].name">
    <input type="submit" value=" 提交">
</form>
</body>
</html>

注意;User要有无参构造

JSON

1.对于返回是text:

<script type="text/javascript">
 $(function () {
     var user= {
         "id":1,
         "name":"张三"
     }
     $.ajax({
         url:"/jsonType",
         data:JSON.stringify(user),
         type:"POST",
         contentType:"application/json;charset=UTF-8",
         dataType:"text",
         success:function (data) {
            // console.log(data);
             var obj=eval("("+data+")")
             alert(obj.id)
             alert(obj.name)
         }
     })
 })
</script>

2.直接是json

页面:

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-06
  Time: 17:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
     $(function () {
         var user= {
             "id":1,
             "name":"张三"
         }
         $.ajax({
             url:"/jsonType",
             data:JSON.stringify(user),
             type:"POST",
             contentType:"application/json;charset=UTF-8",
             dataType:"JSON",
             success:function (data) {
                // console.log(data);
                //  var obj=eval("("+data+")")
                 alert(data.id)
                 alert(data.name)
             }
         })
     })
    </script>
</head>
<body>
</body>
</html>

controller:业务方法:

@RequestMapping("/jsonType")
@ResponseBody
public User jsonType(@RequestBody User user){
    System.out.println(user);
    user.setId(2);
    return  user;
}

配置:

<servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
<!--json依赖-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.32</version>
    </dependency>
  </dependencies>
<mvc:annotation-driven>
    <!--        消息转换器-->
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <property name="supportedMediaTypes" value="text/html;charset=utf-8"></property>
        </bean>
        <!--        fastjson-->
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4">

        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

注意;

  • JSON数据必需用JSON。stringify()妆化成字符串
  • contentType:"application/json;charset=UTF-8"不能省略

Spring mvc 的视图层解析

调用web资源给域对象传值

page

request

session

application

业务数据的绑定是指将业务的数据绑定给jsp对象,业务数据的绑定是由ViewResolver来完成,开发时,我们先添加业务数据,在交给ViewResolve来绑定数据,因此学习的重点在于如何的添加数据,Springmvc提供了一下几中的方式来添加业务:

  • Map
  • Model
  • ModelAndView
  • @SessionAttribute
  • @ModelAttribute
  • Servlet API

业务绑定到request对象

Map

springmvc 在调用业务方法之前会创建一个隐含的对象作为业务的数据的容器,设置业务方法的入参为Maq类型,springmvc会将隐含的对象的引用传递格入参(默认是给Request)

@RequestMapping("/map")
public String map(Map<String,Object> map) {
    User user =new User();
    user.setId(1);
    user.setName("张三");
    map.put("user",user);
    return "show";
}

Model

@RequestMapping("/model")
public String model(Model model) {
    User user =new User();
    user.setId(1);
    user.setName("张三");
    model.addAttribute("user",user);
    return "show";
}

Mo'delAndView

Mo'delAndView不但包含业务数据也包括了视图信息,如果用Mo'delAndView来处理业务数据,业务数据的返回值必需是Mo'delAndView对象

操作;

1.填充业务数据

2.绑定业务信息

  • @RequestMapping("/modelAndView1")
    public ModelAndView modelAndView1() {
      ModelAndView modelAndView =new ModelAndView();
      User user =new User();
      user.setId(1);
      user.setName("张三");
      modelAndView.addObject("user",user);
      modelAndView.setViewName("show");
      return  modelAndView;

    }

    完整路径

  • @RequestMapping("/modelAndView2")
    public ModelAndView modelAndView2() {
      ModelAndView modelAndView =new ModelAndView();
      User user =new User();
      user.setId(1);
      user.setName("张三");
      modelAndView.addObject("user",user);
      View view =new InternalResourceView("/show.jsp");
      modelAndView.setView(view);
      return  modelAndView;

    }

    直接给视图

  • @RequestMapping("/modelAndView3")
    public ModelAndView modelAndView3() {
      ModelAndView modelAndView =new ModelAndView("show");
      User user =new User();
      user.setId(1);
      user.setName("张三");
      modelAndView.addObject("user",user);
      return  modelAndView;

    }

    传递view对象

  • @RequestMapping("/modelAndView4")
    public ModelAndView modelAndView4() {
      View view =new InternalResourceView("/show.jsp");
      ModelAndView modelAndView =new ModelAndView(view);
      User user =new User();
      user.setId(1);
      user.setName("张三");
      modelAndView.addObject("user",user);
      return  modelAndView;

    }

使用Map集合

  • @RequestMapping("/modelAndView5")
    public ModelAndView modelAndView5() {
      Map<String,Object> map =new HashMap<>();
      User user =new User();
      user.setId(1);
      user.setName("张三");
      map.put("user",user);
      ModelAndView modelAndView =new ModelAndView("show",map);
      return  modelAndView;

    }

直接map和view

 @RequestMapping("/modelAndView6")
    public ModelAndView modelAndView6() {
        Map<String,Object> map =new HashMap<>();
        User user =new User();
        user.setId(1);
        user.setName("张三");
        map.put("user",user);
        View view =new InternalResourceView("/show.jsp");
        ModelAndView modelAndView =new ModelAndView(view,map);
        return  modelAndView;

    }

HttpServletRequest

Spring mvc 在业务方法中直接得到Servlet的原生web资源,只需要在方法的定义时添加HttpServletRequest入参即可,在方法体中直接使用request

<!--导入servlet的api-->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.5</version>
</dependency>
@RequestMapping("/request")
public String request(HttpServletRequest request) {
    User user =new User();
    user.setId(1);
    user.setName("张三");
    request.setAttribute("user",user);
    return  "show";
}

@ModelAttribute

  • 定义一个方法来要填充到业务数据中的对线

  • 给方法添加@ModelAttribute,只是添加对象,不做业务

    @ModelAttribute
    public User getUser(){
      User user =new User();
      user.setId(1);
      user.setName("张三");
      return  user;
    }
    @RequestMapping("/modelAttribute")
    public String ModelAttribute() {
      return  "show";
    }

@ModelAttribute,当Handler无论接受到哪格方法都会先调用@ModelAttribute修饰的方法,并将返回值作为业务数据,此时业务方法只需要返回试图即可。

假如返回数据,还是会被@ModelAttribute的数据据覆盖。

而如果没有返回值,要手动填充Map或Model

直接给Model的优先级更高

key-value

key值默认是:对应类的小写首字母

业务数据绑定到Session

  • HttpSession

    @RequestMapping("/session")
    public String session(HttpSession httpSession){
      User user =new User();
      user.setId(1);
      user.setName("张三");
      httpSession.setAttribute("user",user);
        return  "show";
      }
    }
  • @SessionAttributes注解

    默认都是在request下添加,但是注解了@SessionAttributes都会自动的添加到Session中

    @SessionAttributes(value = "user")
    @SessionAttributes(type = User.Class)

多个:

@SessionAttributes(value = {"user","students"})

Spring Mvc自定义的数据类型转换器:

一:Date

1.创建DateConverter 类,并实现Converter接口:需要指定泛型

package com.southwind.converter;

import lombok.SneakyThrows;
import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateConverter implements Converter<String, Date> {
    private  String pattern;
    public DateConverter(String pattern){

        this.pattern=pattern;
    }
    @Override
    public Date convert(String s) {
        SimpleDateFormat simpleDateFormat =new SimpleDateFormat(this.pattern);
        try {
            return  simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

2.配置springMvC

 <mvc:annotation-driven conversion-service="conversionService">
        <!--        消息转换器-->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"></property>
            </bean>
            <!--        fastjson-->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4">

            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
<!--    消息转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.southwind.converter.DateConverter">
                    <constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg>
                </bean>
            </list>
        </property>
    </bean>

3.控制器:

package com.southwind.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.xml.crypto.Data;
import java.util.Date;

@Controller
public class ControverHandler {
    @RequestMapping("/date")
    @ResponseBody
    public String date(Date date){

        return  date.toString();
    }
}

二:实体类;

转换器:

package com.southwind.converter;

import com.southwind.entity.Student;
import org.springframework.core.convert.converter.Converter;

public class StudentConverter  implements Converter<String, Student> {

    @Override
    public Student convert(String s) {
        String[] args=s.split("-");
        Student student =new Student();
        student.setId(Integer.parseInt(args[0]));
        student.setName(args[1]);
        student.setAge(Integer.parseInt(args[2]));
        return student;
    }
}

配置:

<!--    消息转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.southwind.converter.DateConverter">
                    <constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg>
                </bean>
                <bean class="com.southwind.converter.StudentConverter">

                </bean>
            </list>
        </property>
    </bean>

控制器:

    @RequestMapping("/student")
    @ResponseBody
    public String student(Student student, HttpServletResponse response){
        response.setCharacterEncoding("utf-8");
        return  student.toString();
    }

Spring mvc 的RESTful集成

RESTful是当前比较流行的互联网架构模型,通过统一的规范来完成不同端的数据访问和交互,RESTful(资源表现层状态转化)

优点:结构清晰,有统一的标准,扩展性好

  • Resources

    资源是指网路中的某个具体文件,可以是文件、图片、视频、音频等,是网路中真实存在的一个实体。

    获取它:可以通过统一资源定位负找到这个实体,URL,每个资源都有一个特定的URL,通过URL就可以找到一个具体的资源

  • Pepersentation

    资源表现层,资源的具体表现层次,例如一段文字、可以用TXT、HTML、XML、JSON、等不同的形式来描述它。

  • State Transfer

    状态转化是指客户端和服务器之间的数据交互,因为HTTP请求不能传输数据的状态,所有的状态都保存在服务器端,如果客户端希望访问到服务器的数据,就需要使其发生状态改变,同时这种状态的改变是建立在表现层上的。

    RESTful的特点:

    1.URL传递参数更加简洁

    2.完成不同总端之间的资源共享,RESTful提供了一套规范,不同的终端之间只需要遵守规范,就可以实现数据的交互

    RESTful四中表现类型,

    HTTP中的:

  • GET 获取资源

  • POST创建资源

  • PUT修改资源

  • DELETE删除资源

基于RESTful的方式,增删改查分别操作使用不同的HTTP请求来访问。

传统的from表单只支持GET和POST

解决方法:

添加HiddenHttpMeethodFilter过滤器将POST转化为PUT或DELETE

HiddenHttpMeethodFilter实现原理:

HiddenHttpMeethodFilter检测请求的参数是否包含_method参数,如果包含则取出它的值,并且判断它的请求类型之后完成请求的类型的转换,然后继续传递。

实现步骤

1.在from表单中加入隐藏域的标签,name为_method,value为DELETE/PUT

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-07
  Time: 14:10
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/update" method="post">
        <input type="hidden" name="_method" value="PUT">
        <input type="submit" value="提交">
    </form>
        <form action="/delete" method="post">
        <input type="hidden" name="_method" value="DELETE">
        <input type="submit" value="DELETE提交">
    </form>
</body>
</html>
  1. web.xml配置

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

3.控制器

@PutMapping("/update")
@ResponseBody
public  String update(){
    return "PUT已接受到请求";
}

@DeleteMapping("/delete")
public  String delete(){
return "DELETE已接受请求";
}

需求分析

  • 添加课程,成功返回全部课程信息
  • 查询课程,通过id查找课程
  • 修改课程,成功返回全部的课程信息
  • 删除课程,成功返回删除之后的全部课程信息

代码实现

  1. JSP
  • 添加课程
  • 修改课程
  • 课程展示

2.Course实体类

package com.southwind.entity;

import lombok.Data;

@Data
public class Course {
    private Integer id;
    private String name;
    private  Double prive;
}

3.CourseRepository

package com.southwind.respository;

import com.southwind.entity.Course;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Repository
public class CourseRepository {
    private Map<Integer, Course> courseMap;
    public CourseRepository(){
        courseMap=new HashMap<>();
        courseMap.put(1,new Course(1,"java基础",Double.parseDouble("500")));
        courseMap.put(2, new Course(2, "java高级", Double.parseDouble("500")));
        courseMap.put(3, new Course(3, "企业级框架", Double.parseDouble("500")));
    }
    public Collection<Course> findAll(){
        return courseMap.values();
    }
    public Course findById(Integer id){
        return  courseMap.get(id);
    }
    public  void saveOrupdate(Course course){
        courseMap.put(course.getId(),course);
    }
    public void  delete (Integer id){
        courseMap.remove(id);
    }
}

4.CourseController:

package com.southwind.controller;

import com.southwind.entity.Course;
import com.southwind.respository.CourseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/course")
public class CourseController {
    @Autowired
    private CourseRepository courseRepository;
    @PostMapping("/save")
    public  String save(Course course){
        courseRepository.saveOrupdate(course);
       return "redirect:/course/findAll";
    }
    @GetMapping("/findAll")
    public ModelAndView findAll(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        modelAndView.addObject("list",courseRepository.findAll());
        return modelAndView;
    }
    @DeleteMapping("/delete/{id}")
    public String deleteById(@PathVariable("id")Integer id){
        courseRepository.delete(id);
        return  "redirect:/course/findAll";
    }
    @GetMapping("/findById/{id}")
    public ModelAndView findById(@PathVariable("id") Integer id){
        ModelAndView modelAndView =new ModelAndView();
        modelAndView.setViewName("edit");
        modelAndView.addObject("course",courseRepository.findById(id));
        return modelAndView;
    }
    @PutMapping("/update")
    public  String update(Course course){
        courseRepository.saveOrupdate(course);
        return "redirect:/course/findAll";
    }
}

4.jsp

  • 首页(查询和删除修改)

    <%--
    Created by IntelliJ IDEA.
    User: 郝泾钊
    Date: 2022-04-07
    Time: 10:50
    To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@page isELIgnored="false"%>
    <html>
    <head>
      <title>Title</title>
    </head>
    <body>
      <table>
          <tr>
              <td>编号</td>
              <td>名称</td>
              <td>价格</td>
              <td>删除</td>
          </tr>
          <c:forEach items="
    不能识别此Latex公式:
    {list}" var="course">
              <tr>
                  <td>

    {course.id}</td>
                  <td>

    不能识别此Latex公式:
    {course.name}</td>
                  <td>

    {course.price}</td>
                  <td>
                      <form action="/course/delete/

    不能识别此Latex公式:
    {course.id}" method="post">
                          <input type="hidden" name="_method" value="DELETE">
                          <input type="submit" value="删除" >
                      </form>
                      <a href="/course/findById/

    {course.id}">修改</a>
                  </td>

          &lt;/tr&gt;
      &lt;/c:forEach&gt;

    </table>
    </body>
    </html>

  • <%--
    Created by IntelliJ IDEA.
    User: 郝泾钊
    Date: 2022-04-07
    Time: 15:38
    To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@page isELIgnored="false"%>
    <html>
    <head>
      <title>Title</title>
    </head>
    <body>
      <form action="/course/update" method="post">
          <input type="hidden" name="_method" value="PUT">
          <table>
              <tr>
                  <td>编号:</td>
                  <td><input type="text" name="id" readonly value="
    不能识别此Latex公式:
    {course.id}"></td>
              </tr>
              <tr>
                  <td>名称:</td>
                  <td><input type="text" name="name" value="

    {course.name}"></td>
              </tr>
              <tr>
                  <td>价格:</td>
                  <td><input type="text" name="price" value="${course.price}"></td>
              </tr>
              <tr>
                  <td><input type="submit"  value="修改"></td>
              </tr>
          </table>
      </form>
    </body>
    </html>

  • jsp<br /><%--
    Created by IntelliJ IDEA.
    User: 郝泾钊
    Date: 2022-04-07
    Time: 15:10
    To change this template use File | Settings | File Templates.
    --%><br /><%@ page contentType="text/html;charset=UTF-8" language="java" %><br /><br />
    Title
    <br /><br /> </p>
    <form action="/course/save" method="post">
    <table>
    <tr>
    <td>课程编号</td>
    <td><input type="text" name="id"></td>
    </tr>
    <tr>
    <td>课程名称</td>
    <td><input type="text" name="name"></td>
    </tr>
    <tr>
    <td>课程价格</td>
    <td><input type="text" name="price"></td>
    </tr>
    <tr>
    <td><input type="submit" value="提交"></td>
    <td><input type="reset" value="重置"></td>
    </tr>
    </table>
    </form>
    <p><br /><br />

SpringMvc的文件上传下载:

文件上传

单文件上传

1.底层使用的是Apache fileupload组件进行上传的功能,Springmvc 只是对其进行了封装,简化开发,

pom.xml

<!--    apache fileupload-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>

2.JSP页面处理

  • inpu的type设置为file

  • form表单的method设置为post

  • form表单的enctype设置为multipar/form-data

    一:单文件:

JSP

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-07
  Time: 16:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page isELIgnored="false"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="img"/>
        <input type="submit" value="提交"/>
    </form>
<img src="${src}">
</body>
</html>

Handler

package com.southwind.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;

@Controller
@RequestMapping("/file")
public class fileHandler {
    @PostMapping("/upload")
    public String upload(@RequestParam("img")MultipartFile img, HttpServletRequest request) {
        if(img.getSize()>0){
            String path =request.getSession().getServletContext().getRealPath("file");
            String fileName =img.getOriginalFilename();
            File file =new File(path,fileName);
            try {
                img.transferTo(file);
                request.setAttribute("src","/file/"+fileName);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return "upload";
    }
}

配置解析器:

<!--    配置转换器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

二:多文件:

@PostMapping("/uploads")
public String uploads(@RequestParam("imgs")MultipartFile[] imgs, HttpServletRequest request) {
    List<String> pathlist = new ArrayList<>();
    for (MultipartFile img : imgs) {
        if (img.getSize() > 0) {
            String path = request.getSession().getServletContext().getRealPath("file");
            String fileName = img.getOriginalFilename();
            File file = new File(path, fileName);
            try {
                img.transferTo(file);
                pathlist.add("/file/" + fileName);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
    request.setAttribute("list",pathlist);
    return "upload";
}
<form action="/file/uploads" method="post" enctype="multipart/form-data">
        file1:<input type="file" name="imgs"><br>
        file1:<input type="file" name="imgs"><br>
        <input type="submit" value="提交">
</form>
<c:forEach items="${list}" var="path">
    <img src="${path}" width="300px">
</c:forEach>

文件下载

@GetMapping("/downLoad")
public void downLoad(String fileName, HttpServletRequest request, HttpServletResponse response){
    if(fileName!=null){
        String path = request.getSession().getServletContext().getRealPath("file");
        File file =new File(path,fileName);
        OutputStream outputStream=null;
        if(file.exists()){
            //设置下载文件
            response.setContentType("application/force-downlocad");
            //设置文件名
            response.setHeader("Content-Dispoition","attachment;filename"+fileName);
            try {
                outputStream=response.getOutputStream();
                outputStream.write(FileUtils.readFileToByteArray(file));
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(outputStream!=null){
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

Spring Mvc 数据校验的组件

有两种:

  • 基于Vaildator接口进行校验

  • 使用Annotation JSR-303标准校验

    使用Vaildator接口会复杂点,开发者要自己定义规则,而Annotation JSR-303则是要开发者添加对应的校验注解即可。
    基于Validator的接口*

    1.创建实体类:

    package com.southwind.entity;

    import lombok.Data;

    @Data
    public class Student {
    //    private Integer id;
    //    private String name;
    //    private Integer age;
      private  String  name;
      private  String password;
    }

    2.自定义数据校验器StudentValidator实现Validator接口,重写接口的抽象方法,加入校验规则。

    package com.southwind.validation;

    import com.southwind.entity.Student;
    import org.springframework.validation.Errors;
    import org.springframework.validation.ValidationUtils;
    import org.springframework.validation.Validator;

    public class StudentValidator implements Validator {

      @Override
      public boolean supports(Class<?> aClass) {
          return Student.class.equals(aClass);
      }

      @Override
      public void validate(Object o, Errors errors) {
          ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
          ValidationUtils.rejectIfEmpty(errors,"password",null,"密码不能为空");
      }
    }

3.业务方法:

package com.southwind.controller;

import com.southwind.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/validatior")

public class ValidatiorHandler {
    //先数据绑定
    @GetMapping("/login")
    public String  login(Model model){
        model.addAttribute(new Student());
        return  "login";
    }
    @RequestMapping("/login")
    public String login(@Validated Student student, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return "login";
        }else {
            return "login";
        }
    }
}
package com.southwind.validation;

import com.southwind.entity.Student;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

public class StudentValidator implements Validator {

    @Override
    public boolean supports(Class<?> aClass) {
        return Student.class.equals(aClass);
    }

    @Override
    public void validate(Object o, Errors errors) {
        ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
        ValidationUtils.rejectIfEmpty(errors,"password",null,"密码不能为空");
    }
}

Annotation JSR-303

Hibernater Validator,通过注解完成校验

名称 说明
@Null 被标注的元素必须为 null
@NotNull 被标注的元素必须不为 null
@AssertTrue 被标注的元素必须为 true
@AssertFalse 被标注的元素必须为 false
@Min(value) 被标注的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被标注的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMax(value) 被标注的元素必须是一个数字,其值必须大于等于指定的最大值
@DecimalMin(value) 被标注的元素必须是一个数字,其值必须小于等于指定的最小值
@size 被标注的元素的大小必须在指定的范围内
@Digits(integer,fraction) 被标注的元素必须是一个数字,其值必须在可接受的范围内;integer 指定整数精度,fraction 指定小数精度
@Past 被标注的元素必须是一个过去的日期
@Future 被标注的元素必须是一个将来的日期
@Pattern(value) 被标注的元素必须符合指定的正则表达式

配置:

pom.xml

<!--    JSP303-->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.3.6.Final</version>
    </dependency>
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>2.0.1.Final</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.logging</groupId>
      <artifactId>jboss-logging</artifactId>
      <version>3.4.1.Final</version>
    </dependency>
<mvc:annotation-driven></mvc:annotation-driven>

业务页面:

@GetMapping("/register")
public String register(Model model){
    model.addAttribute(new Account());
    return "register";
}
@PostMapping("/register")
public  String register(@Valid Account account,BindingResult bindingResult ){
    if(bindingResult.hasErrors()){
        return "register";
    }else {
        return "success";
    }

}

实体类:

package com.southwind.entity;

import lombok.Data;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Data
public class Account {
    @NotEmpty(message = "用户名不能为空")
    private  String userName;
    @Size(min = 6,max = 20,message = "长度为5到20位")
    private  String password;
    @Email(regexp = "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?",message = "请输入正确的表达式")
    private  String email;
    @Pattern(regexp = "\\d{3}-\\d{8}|\\d{4}-\\{7,8}",message = "请输入正确的表达式")
    private String phone;

}

页面:

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-07
  Time: 19:48
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1> 用户登录</h1>
    <form:form modelAttribute="account" action="/validatior/register">
        用户名:<form:input path="userName"></form:input><form:errors path="userName"></form:errors><br>
        密码:<form:input path="password"></form:input><form:errors path="password"></form:errors><br>
        邮箱:<form:input path="email"></form:input><form:errors path="email"></form:errors><br>
        电话:<form:input path="phone"></form:input><form:errors path="phone"></form:errors><br>
        <input type="submit" value="提交">
    </form:form>
</body>
</html>

spring mvc 的表单标签库

1.Student实体类

package com.southwind.POJO;

import lombok.Data;

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String gender;
}

2.Handler

package com.southwind.controller;

import com.southwind.POJO.Student;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/student")
public class StudenController {
    @GetMapping("/get")
    public String get(Model model){
        Student student =new Student();
        student.setId(1);
        student.setAge(18);
        student.setName("张三");
        student.setGender("男");
        model.addAttribute("student",student);
        return "student";
    }
}

3.JSP

<%--
  Created by IntelliJ IDEA.
  User: 郝泾钊
  Date: 2022-04-07
  Time: 20:53
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>学生编号</h1>
    <form action="" method="post">
        学生编号:<input type="text" value="${student.id}" readonly><br>
        学生姓名:<input type="text" value="${student.name}"><br>
        学生年龄;<input type="text" value="${student.age}"><br>
        学生性别:<input type="text" value="${student.gender}"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

表单标签库的使用

1.JSP页面表单标签库的导入

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

2.将form表单的业务数据进行绑定,通过modelAttribute属性完成绑定,将modelAttribute的值设置位控制器象model对象存值是的name即可。

<%--@elvariable id="student" type="com.southwind.POJO.Student"--%>
<form:form  modelAttribute="student" action="/student/update" method="post">
    学生编号:<form:input path="id"></form:input><br>
    学生姓名:<form:input path="name"></form:input><br>
    学生年龄;<form:input path="age"></form:input><br>
    学生性别:<form:input path="gender"></form:input><br>
    <input type="submit" value="提交">
</form:form>

常用标签的使用

1.from:

<form:form  modelAttribute="student" action="/student/update" method="post">
    </form:form>

渲染的是HTML的from标签,通过modelAttribute属性绑定业务数据。

2.input:

<form:input path="name"></form:input><br>

渲染的是HTML的input标签,type="text" 绑定的是业务数据中的属性值,与path的业务属性值一样。支持级联

3.password:

<form:password path="age"></form:password><br>

渲染的是HTML的password标签,type="text" 绑定的是业务数据中的属性值,与path的业务属性值一样。但是不会在页面现实

4.checkbox:

<form:checkbox path="hobby" value="读书">

</form:checkbox>

渲染的是HTML的checkbox标签,type="text" 绑定的是业务数据中的属性值,与path的业务属性值一样。

有Boolean,数组,集合

  • boolean 为true选中 false为不选中。

    student.setFlag(true)

    check:<form:checkbox path="flag" value="读书">

    </form:checkbox>
  • 数组,集合如果和集合中的元素和checkbox相同就选中

5.checkboxs:

<form:checkboxes path="name" items="${student.hobby}"></form:checkboxes>

渲染的是一组checkbox标签

item绑定别遍历的数组,path表述选中的数组

student.setHobby(Array.asList("读书","鞋子"))

path可以直接写属性名,item则要通过EL表达式从作用域对象中取值,不能直接写属性名。

6.radiobuttion

<form:radiobutton path="name" value="0"></form:radiobutton>

渲染的是一个HTML中的一个单选按钮,值相同为选中状态,值不同为不状态。

7.radiobuttion

<form:radiobuttons path="name" items="${student.name}"></form:radiobuttons>

渲染的是html中的一组单选按钮标签

item绑定别遍历的数组,path表述选中的数组

8.select

<form:select path="name" items="${student.name}"></form:select>

渲染的是html中的一组选择标签

item绑定别遍历的数组,path表述选中的数组

9.from:select结合form:optations使用

from:select只定义path form:optations写 items

10.from:select结合form:optation使用

from:select只定义path form:optation写 value

path与哪个valu相等,则默认选择

Springmvc 国际化

在不同的语言设置的浏览器自动显示不同的语言。

1.spring.mvc

<!--    国计化资源文件-->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<!--        多语言配置文件放在根路径 以langua开头-->
        <property name="basename" value="classpath:language"></property>
        <property name="useCodeAsDefaultMessage" value="true"></property>
    </bean>
<!--    拦截器-->
    <mvc:interceptors>
        <bean id="localeChangeInterceotor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
            <property name="paramName" value="Lang"></property>
        </bean>
    </mvc:interceptors>
<!--    配置SessionResolver,动态获取local对象存入Session-->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>

2.创建国际化资源文件:

language_en_US.properties

language.cn=\u4E2D\u6587
language.en=English
info=login
userbane=username
password=password
repassword=repassword
tel=tel
email=email
submit=submit
reset=reset

language_en_US.properties

language.cn=\u4E2D\u6587
language.en=English
info=\u767B\u5F55
userbane=\u7528\u6237\u540D
password=\u5BC6\u7801
repassword=\u786E\u8BA4\u5BC6\u7801
tel=\u7535\u8BDD
email=\u7535\u5B50\u90AE\u7BB1
submit=\u63D0\u4EA4
reset=\u91CD\u7F6E

业务页面:

package com.southwind.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/inter")
public class InterHandler {
    @GetMapping("/index")
    public String index(){
        return "inter";
    }
}

最新文章

  1. textarea之placeholder
  2. 【转】c# 协变和逆变
  3. JSONP - 跨域AJAX
  4. [Java Basics] Stack, Heap, Constructor, I/O, Immutable, ClassLoader
  5. VBA添加表格
  6. IDA 在string窗口中显示中文字符串
  7. DevExpress 控件 GridControl常见用法
  8. [转]The Best Plugins for Sublime Text
  9. 线程池ThreadPoolExecutor源码解读研究(JDK1.8)
  10. C语言——第二次作业(2)
  11. C++ Primer 有感(标准库类型)
  12. ECharts前端图形展示
  13. python 经典博客链接
  14. git 变基(无卵用)
  15. 20165228 2017-2018-2 《Java程序设计》第6周学习总结
  16. Kubernetes学习之路(二十五)之Helm程序包管理器
  17. nginx init 官方启动脚本
  18. OC Foundation框架—集合
  19. eclipse如何设置时常挂提示
  20. OpenERP对象字段定义的详解

热门文章

  1. &lt;一&gt;关于运算符重载
  2. 一张VR图像帧的生命周期
  3. Solon v1.11.0 发布,Hello Java
  4. 关于CSDN发布博客接口的研究
  5. 运用领域模型——DDD
  6. Linux通过脚本实现多台主机统一部署
  7. 【RocketMQ】主从模式下的消费进度管理
  8. js 非空判断
  9. python 爬虫可视化,天气
  10. 《HelloGitHub》第 81 期