springmvc快速入门

关于三层架构:

springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。

springmvc是一个基于mvc模式的web架构。

springmvc用于前后端的数据交互。


SpringMvc工作流程

第一步:发送请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求处理器映射器(HandlerMapping)查找Handler

第三步:处理器映射器返回Handler到前端控制器

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView

ModelAndView是springmvc框架的一个底层对象,包括 Model和view

第八步:前端控制器请求视图解析器去进行视图解析

根据逻辑视图名解析成真正的视图(jsp)

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染

视图渲染将模型数据(在ModelAndView对象中)填充到request域

第十一步:前端控制器向用户响应结果


SpringMvc快速上手

一.SpringMvc的相关配置

1.所需的jar的引入
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.2.4.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.2.4.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.2.4.RELEASE</version>
    </dependency>
  </dependencies>
2.web.xml中的配置

在web.xml中主要配置的是前端控制器,前端控制器的作用是:通过用户的url请求路径查找到匹配该请求的handler,在将用户的请求交由相应的handler处理。

<!-- 配置前端控制器 -->
  <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>//指定配置文件所在位置,默认在WEB-INF下
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>*.action</url-pattern>			//指定拦截的路径
  </servlet-mapping>
3.springmvc.xml的配置
    <!-- 配置视图解析器:解析转向页面,prefix:前缀,suffix:后缀
        将controller层的返回值进行解析,加上前缀和后缀,就解析成了一个jsp页面,跳转到该页面
        -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
	
    <!-- 注解扫描:将扫描配置的包,将符合要求的纳入spring容器 -->
    <context:component-scan base-package="cn.fzkj.controller"/>
        
    <!-- 开启注解支持 -->
    <mvc:annotation-driven/>

二.RequestMapping注解

使用 @RequestMapping注解映射请求路径,就是将前端的请求交给具体的方法去执行。例如:

前端请求:

<a href="user/login.action">登录</a>

Controller层:

@Controller
@RequestMapping("/user")
public class userController {
    @RequestMapping("/login.action")
    public String testLogin(){
        System.out.println("登录成功");
        return "success";
    }
}

@RequestMapping("/user")是请求的前缀,主要用于对项目进行划分模块。@RequestMapping("/login.action")是请求的具体映射。SpringMvc会拦截所有请求(不准确),并在Controller对应的类中找符合的映射,交由该方法去处理。

RequestMapping注解的属性

1.value:用于指定请求的url,和path属性的作用相同

@RequestMapping(value="/login.action")

2.method:用于指定请求的方式(GET、POST)

@RequestMapping(value="",method={RequestMethod.GET})

3.params:用于指定请求的参数,要求请求的key和value要和配置的相同

@RequestMapping(value="",method={},params={"username"})//必须传username参数

三.请求参数的绑定

就是前端给后端传递参数

  • 第一种:基本类型

前端页面代码

 <a href="user/login.action?username=mr">登录</a>

后端代码

 @RequestMapping("/login.action")
    public String testLogin(String username){  //参数名要和前端传递的参数名保持一致
        System.out.println("登录成功");
        System.out.println("用户名:"+username);
        return "success";
    }
  • 第二种:实体类型(javabean)

前端页面代码

    <form action="user/user.action" method="POST">
        姓名:<input type="text" name="username" /><br>
        年龄:<input type="text" name="age" /><br>
        账户名:<input type="text" name="account.name" /><br>
        金额:<input type="text" name="account.money" /><br>
        <input type="submit" value="提交"/>
    </form>

name属性要和JavaBean的属性名称一致

后端页面代码

    @RequestMapping("/user.action")
    public String testuser(User user){ //自动封装成JavaBean
        System.out.println(user);
        return "success";
    }

四.注解

1.RequestParam注解

之前说控制层接收的参数名要和表现层传递的参数名保持一致,那如果不一致要怎么办呢?

<a href="user/login.action?username=mr">登录</a>
    @RequestMapping("/login.action")
    public String testLogin(String name){
        System.out.println("登录成功");
        System.out.println("用户名:"+username);
        return "success";
    }

前端传一个名为username的参数,而后端接收的却是name参数,按照之前讲的这样肯定是接收不到的。

RequstParam注解就是解决这个问题的

修改之后的代码

    @RequestMapping("/login.action")
    public String testLogin(@RequestParam("username") String name){
        System.out.println("登录成功");
        System.out.println("用户名:"+name);
        return "success";
    }

RequestParam的参数就是前端传递的参数名,该注解会将接收到的参数保存到后面的变量中(即name中)

要赋值的变量必须紧跟着RequestParam注解且在其后面

2.RequestBody注解

@RequestBody注解用来接收请求体的内容,请求方式必须是POST,GET请求无请求体。

   <form action="user/user.action" method="POST">
        姓名:<input type="text" name="username" /><br><br>
        年龄:<input type="text" name="age" /><br><br>
        <input type="submit" value="提交"/>
    </form>
    @RequestMapping("/user.action")
    public String testuser(@RequestBody String body){
        System.out.println(body);
        return "success";
    }

运行结果:

username=mr&age=20
3.PathVariable注解

用于接收url中占位符的值

 <a href="/user/testPathVariable/22">testPathVariable</a>
    @RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") String id){
        System.out.println(id);
        return "success";
    }

运行结果

22

五.响应的返回值

1.String类型
    @RequestMapping("/login.action")
    public String testLogin(@RequestParam("username") String name){
        System.out.println("登录成功");
        System.out.println("用户名:"+name);
        return "success";
    }

返回值类型为String,返回值会经过视图解析器解析成为jsp页面,最终显示。

2.void类型

返回值是void类型的方法有三种跳转页面的方式

  • 请求转发

  • 请求重定向

  • 输出流

    @RequestMapping("/testVoid.action")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("testVoid方法执行了....");
        //1.请求转发(一次请求)
//       request.getRequestDispatcher("/WEBINF/jsp/success.jsp").forward(request,response);
        //2.请求重定向(两次请求)
//        response.sendRedirect(request.getContextPath()+"/index.jsp");
        //3.直接向浏览器输出
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().print("mr");
       return;
    }
3.ModelAndView对象类型
@RequestMapping("/testModelAndView.action")
    public ModelAndView testModelAndView(){
        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        System.out.println("testModelAndView执行了...");
        Account a =new Account();
        a.setMoney(1000.0);
        a.setName("123");
        User user = new User();
        user.setUsername(456");
        user.setAccount(a);
        user.setAge(20);
        
        //把user对象存放到mv对象中,同时也会保存到request域中
        mv.addObject("user",user);
        //设置要跳转的页面,默认经过试图解析器
        mv.setViewName("success");
        
        return mv;
    }
4.使用forward和redirect关键字进行页面跳转
    @RequestMapping("/testGuanjianzi.action")
    public String testGuanjianzi() throws IOException {
        System.out.println("登录成功1");
        //使用forward请求转发
//        return "forward:/WEB-INF/jsp/success.jsp";
        //redirect重定向
        return "redirect:/index.jsp";
    }

六.json格式的数据传递

​ 所需的jar包:

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>

使用ajax进行异步交互

    <script src="js/jquery-3.4.1.min.js"></script>
    <script>
        $(document).ready(function(){
            $("#btn").click(function(){
                // alert("lala");
                $.ajax({
                    cache:false,
                    url:"user/testAjax.action",
                    contentType:"application/json;charset=utf-8",
                    data:'{"username":"lj","age":20}',
                    dataType:"json",
                    success:function(data){	//接收服务器端的响应数据
                        //data:服务器端响应的数据,json格式的
                        alert(data.username);
                        alert(data.age);
                    },
                    type:"post"
                });
            });
        });
    </script>

Controler层的接收方法:

    @ResponseBody   //将返回值转换为json格式
    @RequestMapping("/testAjax.action")
    public User testJson(@RequestBody User user){	//接收请求体
        System.out.println(user);
        //重新赋值
        user.setAge(21);
        user.setUsername("xlj");
        return user;
    }

七.springmvc文件上传

1.springmvc文件上传
    <h3>springmvc文件上传</h3>
    <form action="user/fileupload.action" method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="upload" />
        <input type="submit" value="上传"/>
    </form>
    @RequestMapping("/fileupload.action")
    public String testFileUpLoad(HttpServletRequest request, MultipartFile upload) throws IOException {
        System.out.println("springmvc文件上传");
        //确定上传的路径
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断该路径是否存在
        File file = new File(path);
        if(!file.exists()){
            //创建文件夹
            file.mkdirs();
        }
        //获取上传文件的名称
        String filename = upload.getOriginalFilename();
        //设置名称为唯一值
        String uuid = UUID.randomUUID().toString().replace("-","");
        filename = uuid +"_"+ filename;
        //文件上传
        upload.transferTo(new File(path,filename));
        return "success";
    }
2.springmvc跨服务器文件上传
    @RequestMapping("/fileupload1.action")
    public String testFileUpLoad1(MultipartFile upload) throws IOException {
        System.out.println("跨服务器文件上传");
        //定义上传的服务器路径
        String path = "http://localhost:9090/uploads/";
        //获取上传文件的名称
        String filename = upload.getOriginalFilename();
        //设置名称为唯一值
        String uuid = UUID.randomUUID().toString().replace("-","");
        filename = uuid +"_"+ filename;
        //创建客户端对象
        Client client = Client.create();
        //与图片服务器进行连接
        WebResource webResource = client.resource(path+filename);
        //上传文件
        webResource.put(upload.getBytes());
        return "success";
    }

八.异常处理

定义异常类:

public class SysException extends Exception {
    //提示信息
    private String message;
    public SysException(String message) {
        this.message = message;
    }
    @Override
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

定义异常处理类:

//异常处理器类
public class SysExceptionResolver implements HandlerExceptionResolver {
    /**
     * 处理异常
     * @param request
     * @param response
     * @param handler
     * @param ex:抛出的异常对象
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //获取到异常对象
        SysException e = null;
        if(ex instanceof SysException){
            e = (SysException)ex;
        }else{
            e = new SysException("系统错误");
        }
        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e.getMessage());
        mv.setViewName("error");
        return mv;
    }
}

controller层:

    @RequestMapping("/testException.action")
    public String testException() throws SysException {
        System.out.println("exception执行了...");
        try{
            int a = 1/0;
        }catch (Exception e){
            e.printStackTrace();
            //向上抛出异常
            throw new SysException("捕获到异常");
        }
        return "success";
    }

springmvc.xml配置

 <!-- 配置异常处理器 -->
    <bean id="sysExceptionResolver" class="cn.fzkj.exception.SysExceptionResolver" />

捕获到的异常都是交由异常处理类(SysExceptionResolver)处理的


九.拦截器

SpringMVC的处理器拦截器类似于Servlet中的过滤器(Filter),用于对处理器进行预处理和后处理。

过滤器和拦截器的区别:

过滤器:是servlet规范中的一部分,任何java web工程都能使用。在url-pattern中配置了/*之后,对所有的访问资源都会拦截。

拦截器:是SpringMvc自己的,只有使用SpringMvc框架的工程才能使用。且只会拦截访问的控制器中的方法。

要自定义拦截器,必须要实现HandlerInterceptor接口。

1.编写拦截器类

2.配置拦截器

拦截器类:

//自定义的拦截器
public class DiyInterceptor implements HandlerInterceptor {
    /**
     * 预处理
     * @param request
     * @param response
     * @param handler
     * @return true:放行
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("预处理执行了...");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

配置:

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 配置拦截的方法-->
            <mvc:mapping path="/user/*"/>
            <!--配置不拦截的方法
            <mvc:exclude-mapping path=""/>
            -->
            <!-- 注册拦截器-->
            <bean class="cn.fzkj.interceptor.DiyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

持续更新~~~

原文地址:https://www.cnblogs.com/mrjkl/p/13051572.html