化石原创文章,转载请注明来源并保留原文链接


1、使用Maven,pom文件中加入:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2、在需要的field上,比如某个类的一个变量不能为null或者empty

import javax.validation.constraints.NotBlank;

public class Article {
    @NotBlank(message = "title cannot be blank")
    private String title;
}

3、使用到Article实例的地方,用上@valid

import javax.validation.Valid;

public ResponseEntity<?> saveArticle(@Valid @RequestBody Article article) {
}

到此,如果不能通过验证(例子中title如果是null或者trim()后长度为零),那么底层就直接拦住了,saveArticle()不会得到调用。

但是用户收到的信息缺失一个404的错误。这里可以定制处理。

4、写一个继承ResponseEntityExceptionHandler的类

package API;

import java.util.ArrayList;
import java.util.List;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@SuppressWarnings({"unchecked","rawtypes"})
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler
{
    @ExceptionHandler(Exception.class)
    public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
        List<String> details = new ArrayList<>();
        details.add(ex.getLocalizedMessage());
        ErrorResponse error = new ErrorResponse("Server Error", details);
        return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        List<String> details = new ArrayList<>();
        for(ObjectError error : ex.getBindingResult().getAllErrors()) {
            details.add(error.getDefaultMessage());
        }
        ErrorResponse error = new ErrorResponse("Validation Failed", details);
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}

其中的方法handleMethodArgumentNotValid,就是用来处理参数验证错误。

ErrorResponse是一个自定义的类:

package API;

import java.util.List;

public class ErrorResponse {
    private String message;
    private List<String> details;

    public ErrorResponse(String message, List<String> details) {
        super();
        this.message = message;
        this.details = details;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public List<String> getDetails() {
        return details;
    }

    public void setDetails(List<String> details) {
        this.details = details;
    }
}

注意getter一定要写,否则ajax的error回调,responseText是空的json。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


使用Ajax,我们可以指定Post的格式,比如json、uft-8

    var post = {"title": title, "content": content, "catalog": catalog};
    
    $.ajax({
        type: 'post',
        async: true,
        data: JSON.stringify(post),
        url: document.location.origin + '/api/savearticle',
        dataType:'json',
        contentType: 'application/json; charset=utf-8',
        success: function(data) {
            console.log("保存成功");
        },
        error: function () {
            console.log("Ajax 发生错误!");
        }
    });

上面例子上的post数据,可以在SpringBoot服务器端用这样的方式接收:

@RestController
public class ArticleApi {
    @RequestMapping(value = "/api/savearticle", method = RequestMethod.POST,  consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<?> saveArticle(@RequestBody Article article) {

    }
}

其中,Article是这样:

public class Article {
    private String title;
    private String content;
    private String catalog;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getCatalog() {
        return catalog;
    }

    public void setCatalog(String catalog) {
        this.catalog = catalog;
    }
}

这样的方式,能让SpringBoot直接在底层就帮我们绑定好数据。如果加上@Valid,什么数据验证、取数据栏位等工作就方便多了,可以少些很多代码,提升开发效率。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


一个网站,后台没有使用vue写界面,前端界面使用了Vue.js。

架设到IIS上后,发现大多正常,前台、后台都能访问。唯一的问题就是属于vue写的那块页面,只要F5刷新就出现404错误。


查了一下是IIS的安全机制引起,可以使用IIS的URL Rewrite工具解决。

URL Rewrite可以通过IIS管理器,找到Web 平台安装程序这个入口,然后“产品”页面,选中“服务器”,可以找到“URL重写工具 2.0”。如果没有安装,点后面的“安装”即可。

然后到IIS管理器,对应的网站选中后,找到“URL重写”按钮,加入规则。

这里假设我们遇到的F5刷新出问题的url都是hostname/CourseBase/xxx这样的,那么就加入如下规则(选空白规则创建):

1、名称:随便填

2、匹配url:默认状态下,模式填入:^CourseBase/*

3、条件:点击添加,加入“不是文件”

4、操作:重写。重写url中填根目录文件,比如/index.html。

如此操作好,IIS就会在我们的网站web.config.中写入下面内容:

<rewrite>
  <rules>
	  <rule name="F5">
		  <match url="^CourseBase/*" />
			<conditions>
				<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
			</conditions>
			<action type="Rewrite" url="/Index.html" />
		</rule>
	</rules>
</rewrite>

应用后就能生效。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


glb是web3d中使用频率较高的一种3d格式。Unity原生到2019还没有支持。幸运的是,KhronosGroup官方在github上发布了对应的包,能加载glb、gltf格式。

尝试了一下,2019的版本应该还有问题。2018.4.xx后的版本可以正常处理。我测试的版本是2018.4.21f1。

克隆github的源代码后,先打开GLTFSerialization目录下的GLTFSerialization.sln,利用Visual Studio 2019编译默认的激活项目即可。该项目编译出一系列的dll到工程自带的Unity Demo工程下(UnityGLTF)。

然后就可以使用Unity打开工程目录下的UnityGLTF Unity项目。

工程下有很多的demo,在Samples下,每个场景最重要的就是名字为GLTF的GameObject,上挂一个GLTFComponent脚本,变量GLTF Uri是目标glb或者gltf的路径。

我克隆的项目,对应的目录下是空的。所以知道这个加载路径后,无非就是把glb文件放置到一定的路径下,然后在这里改动对应的变量值即可。


化石原创文章,转载请注明来源并保留原文链接



化石原创文章,转载请注明来源并保留原文链接


three.js官方demo的gltf中,使用了hdr图做背景。跟原图(HDR)比,这个背景在实时演示中,是明显模糊了。

这个问题的原因在于:

new RGBELoader()
	.setDataType( THREE.UnsignedByteType )
	.setPath( 'textures/equirectangular/' )
	.load( 'pedestrian_overpass_1k.hdr', function ( texture ) {

		var envMap = pmremGenerator.fromEquirectangular( texture ).texture;

		scene.background = envMap;
		scene.environment = envMap;

这段代码中,envMap的精度被底层控制在了256像素。

使用下面的方式可以提高精度:

envMap = new THREE.WebGLCubeRenderTarget( 1024 ).fromEquirectangularTexture( renderer, texture );

其中的texture就是上面的代码中回调产生的texture,代码里把精度提升到了1024。


化石原创文章,转载请注明来源并保留原文链接