SpringMVC的使用

发布于:2024-12-22 ⋅ 阅读:(13) ⋅ 点赞:(0)

之前我们介绍了如何创建SpringMVC工程,本期介绍如何如何更加详细的使用SpringMVC。

这里给出之前的链接:如何创建SpringMVC工程-CSDN博客

1.跳转不经过视图解析器

之前我们为SpringMVC工程添加了视图解析器,使得每个返回的字符串请求都会加上前缀和后缀。

如果想要不经过视图解析器,可以使用redirect和forward关键字告诉springMVC无需经过视图解析器。

2.controller保存数据的方式 

controller层也就是网络请求服务,我们可以通过在方法中添加request接口参数,将数据保存到本次请求中。

 springMVC也提供了一个Model对象,该对象的保存周期默认和request等价。如果想要改变保存周期为会话周期需要添加注解@SessionAttributes("键"),键的值为model添加的值。

 或者我们直接在方法的参数中引入session对象,将数据直接保存到session对象中。

3.返回json对象

当前端使用ajax请求后端服务器时,我们可以通过查询数据库的数据后将数据以json格式返回到前端,这样前端只需要将数据展示出来就可以,不用等待服务器的响应。

1.首先需要引入依赖jackson

 <!--jackson-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.18.1</version>
    </dependency>

2.在方法上使用@ResponseBody注解

3.前端发送ajax请求

<body>
    <button onclick="submit()">提交</button>
</body>
<script>
     function submit(){
         $.get("/list",function(data){
             console.log(data);//浏览器控制台输出
         },"json")
     }
</script>

4.拦截器的使用

拦截器可以帮助我们拦截请求而不会拦截静态页面和资源。想要使用拦截器需要定义一个拦截器类并实现拦截器接口。

public class MyInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取session对象
        HttpSession session=request.getSession();
        //获取session当前用户的信息
        Object userinfo = session.getAttribute("userinfo");
        if(userinfo==null){
            //没有登录,跳转到登录页面
            response.sendRedirect("/login.jsp");
            return false;
        }
        return true; //如果返回值为true,表示拦截器放行。否则,拦截器不放行
    }
}

然后需要在springmvc的配置文件中添加拦截器的配置标签:

 <!--注册自定义拦截器以及拦截规则-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--path:拦截的路径 /**表示拦截多层路径,这样不会拦截/login,/register等单层路径-->
            <mvc:mapping path="/**"/>
            <!--排除的路径。-->
            <mvc:exclude-mapping path="/user/login"/>
             <!--放置自定义的拦截器类-->
            <bean class="com.aaa.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

5.全局异常处理

如果controller层发生异常,可以定义一个全局异常类用于处理请求出现的问题,这样对于所有异常都有一个统一的处理方法。

我们需要确保这个类能够被springmvc扫描器扫描到。

这个类捕获优先执行异常范围更为精确的异常,对于不同异常执行的顺序不由它们的位置决定。

//全局异常处理类.
@ControllerAdvice
public class MyGlobalException {
    @ExceptionHandler(Exception.class) //当发生Exception类型的异常会执行该方法,并异常对象传递给该方法的参数。
    @ResponseBody
    public String handlerException(Exception e){
        System.out.println(e.getMessage());
        return "error";//经过视图解析器: /views/error.jsp
    }
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public String handlerArithmeticException(Exception e){
        System.out.println("算数错误");
        return "error";
    }

}

如果前端使用的是ajax,那么可以接收到错误信息。

function loadEmp(){
        $.ajax({
            url:"/emp/list",
            type:"get",
            dataType:"json",
            //服务器响应成功
            success:function(data){
                console.log(data)
                var str="";
                for(var i=0;i<data.length;i++){
                    str+="<tr>"
                    str+="<td>"+data[i].empId+"</td>"
                    str+="<td>"+data[i].empName+"</td>"
                    str+="</tr>"
                }
                document.getElementById("empBody").innerHTML=str;
            },
            //服务器响应故障,这个用来接收异常请求
            error: function (data){
                console.log(data);
            }
        })
    }

6.上传本地文件

在我们浏览网页时,通常都会有上传图片或文件的功能,例如我们上传一张头像后,前端就显示了我们所上传的图像图片。想要实现文件上传的功能需要以下几个步骤:

1.引入文件上传的依赖

 <!--文件上传依赖-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.5</version>
    </dependency>

2.在spring配置文件中上传解析器

 <!--文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--最大上传的大小。单位byte字节。5M=5*1024*1024-->
        <property name="maxUploadSize" value="5242880"/>
        <!--设置文件上传的编码-->
        <property name="defaultEncoding" value="utf-8"/>
    </bean>

3.前端编写能够提交文件的代码

 <%--文件上传的表单提交方式必须为post.而且需要设置表单提交的编码格式。enctype="multipart/form-data" 该类型表示既能上传文本又能上传文件。--%>
   <form action="/upload" method="post" enctype="multipart/form-data">
      选择文件:<input type="file" name="myfile"/><br>
      姓名:<input type="text" name="username"/><br>
      <input type="submit"/>
   </form>

4.编写存储到本地的接口

springmvc提供了一个transferTo的方法,可以将文件存储到本地服务器下。

  @RequestMapping("/upload")
    public String upload(MultipartFile myfile, HttpServletRequest request) throws IOException {
        //1.获取保存文件的路径
        String realPath = request.getSession().getServletContext().getRealPath("/images");
        //2.根据上面的路径创建文件对象
        File file=new File(realPath);
        //3.判断该文件夹是否存在
        if(!file.exists()){
            file.mkdirs();
        }
        //4.获取上传文件的名称. 获取登录者ip+登录者id+登录者的时间戳
        String filename = UUID.randomUUID().toString().replace("-","")+myfile.getOriginalFilename();
        //5.把上传的文件保存到指定服务器下的路径。
        File target=new File(realPath+"/"+filename);
        myfile.transferTo(target);
        System.out.println("上传成功");
        return "main";
    }

5.阿里云服务器的使用

在实际编写代码中,一般除了公司配置了专门的服务器,其余大都是通过第三方文件服务器存储客户上传的文件。这里我使用的是阿里云的OSS存储。

首先需要登录阿里云。官网地址:阿里云-计算,为了无法计算的价值 。

如果之前没有注册过阿里云需要先注册账号,然后我们在上方的产品导航栏中找到对象存储OSS,点击进入。

如果之前没有开通过对象存储OSS服务,需要点击立即开通。之后会出现如下界面。

点击管理控制台后,会进入新的界面。这里我们找到Bucket列表,然后选择创建Bucket。

 创建有许多选项,这里根据个人需求选择,部分选项可能会带来额外的收费。

创建完Bucket后我们还需要去申请密钥,密钥是用来连接阿里云服务的唯一凭证,需要妥善保管。将鼠标移至头像处有一个Accesskey,在这里可以进入到密钥处。

 

进入后看到左上角有一个创建AccessKey。点击即可,之后需要进行验证, 完成后会给一个文件,里面填写者密钥的id和key。密钥同时最多只能持有三个,需要妥善管理。

 

 之后我们就能够开始进行代码的编写了,这里阿里云给我们提供好了基础的代码,我们只需要在此基础上进行更改即可。

回到主界面找到产品文档,点击进入。

找到开发参考下的SDK参考,选择java。点击快速入门。

 里面有许多说明,可以根据自己的开发需求进行阅读。这里我使用了maven工程,所以直接引入依赖。

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.17.4</version>
</dependency>

<!--如果使用的是Java 9及以上的版本,则需要添加以下JAXB相关依赖。-->

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

然后选择Java下的,对象/文件下的 简单上传,在里面找到文件上传。

 

 下方代码展示了如何上传基础的文件。其中有一些参数需要进行解释。

  • endpoint为地域节点,需要填写您实际申请的地域地址。地域节点可以点击bucket名称中的概述中找到地域节点填写。
  • bucketName为您创建Bucket时所起的名字。
  • credentialsProvider 为您申请的密钥Id 和 key 的访问凭证申请。
  • objectName为您想要上传文件的名称。
  • filePath为您想要上传文件所存放的地址。
  • region为您申请bucket的所在地域。

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.File;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
        String filePath= "D:\\localpath\\examplefile.txt";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";
        
        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
            // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);
            
            // 上传文件。
            PutObjectResult result = ossClient.putObject(putObjectRequest);           
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

 这样已经可以上传指定位置的文件了,但如果想要根据前端用户上传的文件进行存放,需要对这段代码进行改造。这里我将其编写成了一个方法,可以用来传入文件。并返回该文件的网络地址。

这里返回的网络地址,是根据上传文件生成的URL拼接得来的。

public class AliyunConnection {
    public String uploadOss(MultipartFile file) {
        // 其它Region请按实际情况填写。我填写的是北京
        String endpoint = "oss-cn-beijing.aliyuncs.com";
        // 这里我改成了默认输入密钥ID和密钥key
        DefaultCredentialProvider defaultCredentialProvider = CredentialsProviderFactory.newDefaultCredentialProvider("密钥ID", "密钥key");
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "bucket名称";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = UUID.randomUUID().toString().replaceAll("-","") + file.getOriginalFilename();
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。

        // 填写Bucket所在地域。
        String region = "cn-beijing";

        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(defaultCredentialProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            InputStream inputStream = file.getInputStream();
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);

            // 上传文件。
            //https://createdreamchen.oss-cn-beijing.aliyuncs.com/96c29d54034241d6aff3923dbb34e31d1.jpg
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            return "http://"+ bucketName + "." + endpoint + "/" + objectName;
        } catch (OSSException oe) {
            throw new OSSException("OSS错误");
        } catch (ClientException ce) {
            throw new ClientException(ce);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

至此,就完成了上传本地文件的所有操作。之后可以调用这个方法返回一个string字符串,将其存入数据库中。并在前端获取该文件的url路径即可。