关于后端:最全的SpringMVC教程终于让我找到了

45次阅读

共计 11638 个字符,预计需要花费 30 分钟才能阅读完成。

  1. 为啥要学 SpringMVC?1.1 SpringMVC 简介在学习 SpringMVC 之前咱们先看看在应用 Servlet 的时候咱们是如何解决用户申请的:配置 web.xml<?xml version=”1.0″ encoding=”UTF-8″?>
    <web-app xmlns=”http://xmlns.jcp.org/xml/ns/javaee”

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
      version="4.0">
    

    <!– 将 Servlet 接口实现类交给 Tomcat 治理 –>
    <servlet>

     <servlet-name>userServlet</servlet-name> <!--Servlet 接口实现类名称 -->
     <servlet-class>com.xxl.controller.UserServlet</servlet-class><!-- 申明 servlet 接口实现类类门路 -->

    </servlet>
    <servlet-mapping>

     <servlet-name>userServlet</servlet-name>
     <url-pattern>/user</url-pattern>  <!-- 设置 Servlet 类的申请门路,必须以 / 结尾 -->

    </servlet-mapping>
    </web-app>
    复制代码继承 HttpServlet,实现 doGet 和 doPost 办法 public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    // 这里用来解决用户的 get 申请
    System.out.println("哈哈哈哈哈哈我头上有注解");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

     // 这里用来解决用户的 post 申请
     System.out.println("接管到用户的 post 申请");

    }
    }
    复制代码获取申请参数
    String name = request.getParameter(“name”);

String age = request.getParameter(“age”);
….

复制代码一顿操作下来,咱们发现用 Servlet 解决用户的申请也太麻烦了吧。

每个 Servlet 都要继承 HttpServlet、重写两个办法,咱们须要写一堆 getParameter() 办法来获取申请参数,而且还要做数据类型的转换。那有没有一个他人封装好的工具或者是框架让我少写这些重复性的代码呢?SpringMVC 闪亮退场。SpringMVC 是一种轻量级的、基于 MVC 的 Web 层利用框架,它属于 Spring 框架的一部分。SpringMVC 说白了就是对 Servlet 进行了封装,不便大家应用。1.2 SpringMVC 长处天生与 Spring 集成反对 Restful 格调开发便于与其余视图技术集成,例如 theamleaf、freemarker 等弱小的异样解决对动态资源的反对总之就是好用!2. HelloWorld 这里咱们先来开发一个基于 SpringMVC 的程序,感受一下 SpringMVC 的迷人个性。开发工具:IDEA 构建工具:Maven2.1 新建基于 Maven 的 web 我的项目

2.2 退出依赖 <!– servlet –>
<dependency>

<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>

</dependency>
<!–springmvc –>
<dependency>

<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>

</dependency>
<!– junit –>
<dependency>

<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>

</dependency>
复制代码

2.3 创立地方调度器 DispatcherServlet 是 SpringMVC 的地方调度器,它次要负责加载 SpringMVC 的配置。从它的名字来看,他也属于一个 Servlet,恪守 Servlet 标准。所以咱们须要在 web.xml 中创立 DispatcherServlet。web.xml<!DOCTYPE web-app PUBLIC

    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

<!--servlet: DispatcherServlet-->
<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>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

</web-app>
复制代码

2.4 创立 SpringMVC 的配置文件这里咱们在 src/resources 资源目录下创立 SpringMVC 的配置文件 springmvc.xml,该文件名字能够任意命名。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"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>
复制代码

2.5 创立解决申请的处理器 TestController:/**

  • @Desc: 处理器
  • @Author: 知否技术
  • @date: 下午 7:39 2022/4/29
    */
    @Controller
    public class TestController {
    @RequestMapping(“/hello”)
    public ModelAndView sayHello() {

    ModelAndView mv = new ModelAndView();
    mv.addObject("msg", "你好啊,李银河,我是王小波。");
    mv.setViewName("/hello.jsp");
    return mv;

    }
    }
    复制代码 2.6 申明组件扫描器咱们在 springmvc.xml 中注册组件扫描器,
    <!– 扫描组件,将加上 @Controller 注解的类作为 SpringMVC 的管制层 –>
    <context:component-scan base-package=”com.zhifou”></context:component-scan>
    复制代码

    2.7 创立 jsp 页面

    2.8 配置视图解析器咱们须要在 springmvc.xml 中配置申请文件的门路和文件后缀。<!–
    配置视图解析器
    作用:将 prefix + 视图名称 + suffix 确定最终要跳转的页面
    –>
    <bean id=”viewResolver” class=”org.springframework.web.servlet.view.InternalResourceViewResolver”>
    <property name=”prefix” value=”/WEB-INF/view/”></property>
    <property name=”suffix” value=”.jsp”></property>
    </bean>
    复制代码

    2.9 批改处理器申请文件门路因为咱们指定了申请文件的后缀是 .jsp,所以这里能够省略。

    2.10 配置 tomcat,启动我的项目测试

     

     

     

  1. 申请 3.1 @RequestMapping@RequestMapping 注解用来指定解决哪些 URL 申请。3.1.1 注解罕用属性 valuevalue 用来示意申请的 url,能够省略不写 @RequestMapping(value = “/hello”)
    复制代码简写 @RequestMapping(“/hello”)
    复制代码 methodmethod 用来示意申请形式,不写的话默认是 GET 申请。罕用的申请形式:POST、GET、PUT、DELETE
    复制代码如果应用 method 属性,不能省略 value 属性。@RequestMapping(value = “/hello”,method = RequestMethod.GET)
    public ModelAndView sayHello() {
    ModelAndView mv = new ModelAndView();
    mv.addObject(“message”, “ 你好啊,李银河,我是王小波。”);
    mv.setViewName(“/hello”);
    return mv;
    }
    复制代码 3.1.2 标记地位标记在类下面一个零碎蕴含很多模块,例如用户、商品、订单等模块。咱们须要为不同的模块定义不同的类,而后在类下面增加 @RequestMapping 注解,示意这个模块上面对立的申请门路:例如:// 用户操作控制器
    @Controller
    @RequestMapping(“/user”)
    public class UserController {

}
// 订单操作控制器
@Controller
@RequestMapping(“/order”)
public class OrderController {

}

复制代码标记在办法下面每个模块都有很多办法,例如增删改查等。所以咱们个别会在相应的办法下面增加 @RequestMapping 注解,示意申请这个模块下的某个办法,例如:@Controller
@RequestMapping(“/user”)
public class UserController {
@RequestMapping(“/list”)

public Object list() {return null;}
@RequestMapping(value = "/add",method = RequestMethod.POST)
public Object add() {return null;}
@RequestMapping(value = "/update",method = RequestMethod.POST)
public Object update() {return null;}
@RequestMapping(value = "/delete",method = RequestMethod.DELETE)
public Object delete() {return null;}

}
复制代码所以当咱们获取用户列表信息时,咱们申请的后盾接口的 url 就是:ip 地址: 端口号 / 我的项目名 /uset/list
// 例如:
localhost:8080/ems/user/list
复制代码 3.1.3 @RequestMapping 的缩写注解办法上对于不同申请形式的注解都比拟长,例如: @RequestMapping(value = “/add”,method = RequestMethod.POST)
复制代码 SpringMVC 为咱们提供了简化写法:GET 申请:@GetMapping(“/list”)
复制代码 POST 申请:@PostMapping(“/login”)
复制代码 DELETE 申请:@DeleteMapping(“/delete/{id}”)
复制代码 PUT 申请 @PutMapping(“/update”)
复制代码 3.2 接管申请参数 3.2.1 接管多个参数 @PostMapping(“/login”)
public Result<User> login(String username,String password) {

    User user = userService.login(username, password);
    return Result.success(user);
}

复制代码 3.2.2 实体类作为参数 Spring MVC 会按申请参数名和 POJO 属性名进行主动匹配,主动为该对象填充属性值。@PostMapping(“/login”)
public Result<User> login(User user){

User user = userService.login(user.getUsername(), user.getPassword);
return Result.success(user);

}
复制代码 3.2.3 @RequestParam 注解应用 @RequestParam 能够把申请参数传递给申请办法。属性:value:参数名 required:是否必须。默认为 true, 示意申请参数中必须蕴含对应的参数,若不存在,将抛出异样 defaultValue: 默认值,当没有传递参数时应用该值 @PostMapping(“/login”)
public Result<User> login(@RequestParam String username, @RequestParam String password) {

User user = userService.login(username, password);
return Result.success(user);

}
复制代码 3.2.4 @PathVariable 注解通过 @PathVariable 能够将 URL 中占位符参数绑定到控制器解决办法的入参中。URL 中的 {xxx} 占位符能够通过 @PathVariable(“xxx”)绑定到操作方法的入参中。@DeleteMapping(value = “/delete/{id}”)
public Result<?> delete(@PathVariable(“id”) int id) {

userService.remove(id);
return Result.success();

}
复制代码 3.3 解决中文乱码申请参数如果含有中文,会呈现中文乱码问题。咱们能够通过在 web.xml 中配置字符过滤器来解决中文乱码问题。<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>
<init-param>

        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>

</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
复制代码注:filter 标签要在 servlet 标签之上 4. 响应 SpringMVC 提供了以下几种形式解决响应数据。4.1 返回 StringSpringMVC 的视图解析器将返回的字符串转换为视图(页面)。@GetMapping(“/hello”)
public String toHello() {

return "/hello";

}
复制代码重定向:应用 redirect 关键字能够重定向到其余页面。@GetMapping(“/hello”)
public String toHello() {

return "redirect:/hello";

}
复制代码 4.2 返回 ModelAndView 控制器在解决完用户的申请之后,如果既想跳转页面,又想传递数据,能够应用 ModelAndView 对象。@RequestMapping(value = “/hello”,method = RequestMethod.GET)
public ModelAndView sayHello() {

  ModelAndView mv = new ModelAndView();
  mv.addObject("message", "你好啊,李银河,我是王小波。");
  mv.setViewName("/hello");
  return mv;

}
复制代码 4.3 返回 ModelMode 对象也能够在跳转页面的时候传递数据。@GetMapping(“/print”)
public String print(Model model) {

model.addAttribute("msg", "祝大家五一高兴!");
return "/hello";

}
复制代码 4.4 返回 json 控制器的办法也能够返回 Object 对象,但返回的对象不是作为视图呈现的,而是作为页面上显示的数据。返回对象,须要应用 @ResponseBody 注解将对象转换为 json 格局的数据响应给浏览器。@GetMapping(value = “/print”, produces = “application/json;charset=utf8”)
@ResponseBody
public Object print() {

User user = new User(11111L, "张无忌", 12);
String json = JSONUtil.toJsonStr(user);
return json;

}
复制代码

如果遇到中文乱码的问题,咱们能够在 @GetMapping 注解外面设置 produces 属性。@RestController 注解 @RestController 注解是 @Controller 和 @ResponseBody 注解的组合注解,示意这个控制器中所有的办法全都返回 json 格局的数据。4.5 返回 void 有时候咱们不须要跳转页面,也不须要转发数据,咱们只是心愿浏览器可能渲染数据(例如后盾向前台输入验证码)。这时候能够应用 HttpServletResponse 向浏览器输入数据。@GetMapping(“/print”)
public void print(HttpServletResponse response) throws IOException {

/* 解决响应数据中文乱码问题 */
response.setContentType("text/html;charset=utf8");
PrintWriter writer = response.getWriter();
writer.print("祝大家五一高兴");
writer.flush();
writer.close();

}
复制代码 5. 拜访动态资源咱们在 web.xml 中配置 url-pattern 为 /,当咱们申请我的项目的动态资源的时候,SpringMVC 的地方调度器会先依据处理器映射器寻找相应的处理器,后果没找到,所以申请动态资源会报 404。

咱们能够应用 mvc:resources 标签来解决无法访问动态资源的问题。然而 DispatcherServlet 的映射门路为 /,而 Tomcat 默认的 Servlet 的映射门路也为 /,所以 DispatcherServlet 会笼罩 Tomcat 中默认的 Servlet,去解决除 jsp 之外的所有资源,导致动态资源无奈被拜访。所以这里还须要联合另外一个标签应用:<!– static/** 示意该目录下所有文件 –>
<mvc:resources mapping=”/static/**” location=”/static/”/>
<mvc:annotation-driven/>
复制代码

这里咱们测试拜访我的项目中的照片:@GetMapping(“/hello”)
public String toHello() {

return "/hello";

}
复制代码

 

  1. 全局异样解决在开发过程中咱们会遇到各种各样的异样,咱们会有两种解决形式:try-catch 捕捉 throws 抛出异样然而用户不心愿看到一堆异样信息:

     即使是程序出错了,他们也心愿看到一些看得懂的错误信息,例如:{
    code: 500,
    message: ‘ 该商品信息不存在,请分割管理员 ’
    }
    复制代码所以咱们须要搞一个全局异样处理器先捕捉这些错误信息,而后返回给用户对立的后果信息。创立全局异样处理器 @RestControllerAdvice
    public class GlobalExceptionHandler {
    // 自定义异样处理器
    @ExceptionHandler(CustomException.class)
    public Result CustomExceptionHandler(Exception e) {

     
     return Result.fail(500,e.getMessage());

    }
    }
    复制代码 @RestControllerAdvice:示意这个类是全局异样处理器,返回的格局是 json 格局。@ExceptionHandler:捕捉的异样类型创立自定义异样 /**

    • @Desc: 自定义异样
    • @Author: 知否技术
    • @date: 下午 8:05 2022/5/3
      */

    public class CustomException extends RuntimeException{

    public CustomException(String message) {

     super(message);

    }
    }
    复制代码因为大部分异样是运行时异样,所以这里自定义的异样继承了运行时异样。封装返回的对立后果类 /**

    • @Desc: 对立后果类
    • @Author: 知否技术
    • @date: 下午 9:02 2022/5/3
      */

    public class Result implements Serializable {

    private int code;

    private String message;

    private Object data;

    private Result(String message) {

     this.code = 200;
     this.message = message;

    }

    private Result(String message, Object data) {

     this.code = 200;
     this.message = message;
     this.data = data;

    }

    private Result(int code, String message) {

     this.code = code;
     this.message = message;

    }

    public static Result success(String message) {

     return new Result(message);

    }

    public static Result success(String message, Object data) {

     return new Result(message, data);

    }

    public static Result fail(int code, String message) {

     return new Result(code, message);

    }

    public int getCode() {

     return code;

    }

    public void setCode(int code) {

     this.code = code;

    }

    public String getMessage() {

     return message;

    }

    public void setMessage(String message) {

     this.message = message;

    }

    public Object getData() {

     return data;

    }

    public void setData(Object data) {

     this.data = data;

    }
    }
    复制代码测试 @GetMapping(“/hello”)
    @ResponseBody
    public Result toHello() {
    throw new CustomException(“ 卧槽!!出错了 ”);
    }
    复制代码

  2. 拦截器 SpringMVC 中的拦截器次要是用来拦挡用户的申请,并进行相干的解决。实现拦截器:创立拦截器 /**

    • @Desc:
    • @Author: 知否技术
    • @date: 下午 2:09 2022/5/3
      */

    public class MyInterceptor implements HandlerInterceptor {

    // 在处理器中办法执行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    
     return false;

    }
    // 在处理器中办法执行之后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }
    }
    复制代码配置拦截器 <!– 配置拦截器 –>
    <mvc:interceptors>
    <mvc:interceptor>

     <!-- 拦挡所有申请 -->
     <mvc:mapping path="/**"/>
     <!-- 排除申请 -->
     <mvc:exclude-mapping path="/user/login"/>
     <bean class="com.zhifou.interceptor.MyInterceptor"></bean>

    </mvc:interceptor>
    </mvc:interceptors>
    复制代码测试:

     

     

  3. SpringMVC 执行流程

    1.Tomcat 服务器启动的时候会立刻创立 DispatcherServlet(地方调度器),同时会创立 SpringMVC 容器。2.SpringMVC 容器初始化的时候会先依据配置文件中的组件扫描器先扫描一下哪些类下面有 @Controller 注解,并将这些类作为处理器类。而后通过 @RequestMapping 注解生成对应的映射关系。这些对应关系由处理器映射器治理。3. 当收到用户的申请,地方调度器将申请转发给处理器映射器。4. 处理器映射器依据用户申请的 URL 从映射关系中找到解决该申请的处理器,而后封装成处理器执行链返回给中央处理器。5. 地方调度器依据处理器执行链中的处理器,找到可能执行该处理器的处理器适配器,处理器适配器调用执行处理器。6. 处理器将处理结果及要跳转的视图封装到 ModelAndView 中,并将其返回给处理器适配器。7. 处理器适配器间接将后果返回给地方调度器,地方调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。8. 视图解析器将封装了的视图对象返回给地方调度器,地方调度器调用视图对象,填充数据,生成响应对象。9. 地方调度器将后果响应给浏览器。

正文完
 0