SpringBoot(六)——————国际化、Restful、错误处理机制

源码地址:https://github.com/877148107/scms_admin/tree/master/scms_learn_thymeleaf

参考文档:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/html/spring-boot-features.html#boot-features-internationalization

  • 国际化

1)、编写国际化配置文件,抽取页面需要显示的国际化消息

SpringBoot(六)——————国际化、Restful、错误处理机制_第1张图片

 

#配置国际化资源的配置文件路径+名称
spring.messages.basename=i18n.login

2)、SpringBoot自动配置好了管理国际化资源文件的组件;

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {

	private static final Resource[] NO_RESOURCES = {};

	@Bean
	@ConfigurationProperties(prefix = "spring.messages")
	public MessageSourceProperties messageSourceProperties() {
		return new MessageSourceProperties();
	}

 3)、可以根据浏览器语言切换



	
		
		
		
		
		Signin Template for Bootstrap
		
		
		
		
	

	
		

	


4)、点击按钮切换国际化

SpringMvc自动配置中添加了国际化Locale(区域信息对象),LocaleResolver(获取区域信息对象)

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
......
    		@Bean
		@ConditionalOnMissingBean
		@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
		public LocaleResolver localeResolver() {
			if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
				return new FixedLocaleResolver(this.mvcProperties.getLocale());
			}
			AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
			localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
			return localeResolver;
		}
}

自己重写获取区域信息对象,那么自动配置中的就会失效

package com.wmy.scms.comment;


import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * @ClassName: MyLocaleResolver
 * =================================================
 * @Description: 区域信息
 * =================================================
 * CreateInfo:
 * @Author: William.Wangmy
 * @Email: [email protected]
 * @CreateDate: 2020/1/7 23:08
 * @Version: V1.0
 */
public class MyLocaleResolver implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String l = request.getParameter("l");
        Locale locale = Locale.getDefault();
        if (!StringUtils.isEmpty(l)) {
            String[] s = l.split("_");
            locale = new Locale(s[0],s[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }
}

效果

SpringBoot(六)——————国际化、Restful、错误处理机制_第2张图片

SpringBoot(六)——————国际化、Restful、错误处理机制_第3张图片

  •  Restful

1)、RestfulCRUD:CRUD满足Rest风格;

URI: /资源名称/资源标识 HTTP请求方式区分对资源CRUD操作

  普通CRUD(uri来区分操作) RestfulCRUD
查询 getEmp emp---GET
添加 addEmp?xxx emp---POST
修改 updateEmp?id=xxx&xxx=xx emp/{id}---PUT
删除 deleteEmp?id=1 emp/{id}---DELETE

2)、查询


	
	[[${emp.lastName}]]
	
	
	
	
	
		编辑
	
    /**
     * 修改页面
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/emp/{id}")
    public String toEditPage(@PathVariable("id") Integer id,Model model){
        Employee employee = employeeDao.get(id);
        model.addAttribute("emp",employee);

        //页面要显示所有的部门列表
        Collection departments = departmentDao.getDepartments();
        model.addAttribute("depts",departments);
        //回到修改页面(add是一个修改添加二合一的页面);
        return "emp/add";
    }

 

3)、添加



/**
 * 新增
 * @param employee
 * @return
 */
@PostMapping("/emp")
public String addEmp(Employee employee){
	//来到员工列表页面

	System.out.println("保存的员工信息:"+employee);
	//保存员工
	employeeDao.save(employee);
	// redirect: 表示重定向到一个地址  /代表当前项目路径
	// forward: 表示转发到一个地址
	return "redirect:/emps";
}

 

4)、修改

/**
 * 修改信息
 * @param employee
 * @return
 */
@PutMapping("/emp")
public String updateEmployee(Employee employee){
	System.out.println("修改的员工数据:"+employee);
	employeeDao.save(employee);
	return "redirect:/emps";
}

5)、删除

/**
 * 员工删除
 */
@DeleteMapping("/emp/{id}")
public String deleteEmployee(@PathVariable("id") Integer id){
	employeeDao.delete(id);
	return "redirect:/emps";
}
  • 错误处理机制

1)、Springboot默认的错误处理机制

  • 默认的错误显示方式

SpringBoot(六)——————国际化、Restful、错误处理机制_第4张图片

  • 浏览器请求和非浏览器请求的区别

SpringBoot(六)——————国际化、Restful、错误处理机制_第5张图片

SpringBoot(六)——————国际化、Restful、错误处理机制_第6张图片

  • Sprigboot错误自动配置,ErrorMvcAutoConfiguration

错误信息自动配置给容器中添加了一下组件:

1.DefaultErrorAttributes

页面共享信息

@Order(Ordered.HIGHEST_PRECEDENCE)
public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver, Ordered {

	@Override
	public Map getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
		Map errorAttributes = new LinkedHashMap<>();
		errorAttributes.put("timestamp", new Date());
		addStatus(errorAttributes, webRequest);
		addErrorDetails(errorAttributes, webRequest, includeStackTrace);
		addPath(errorAttributes, webRequest);
		return errorAttributes;
	}

timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里

以上信息都可以在页面获取到


2.BasicErrorController

第一个方法产生HTML数据、第二个方法产生JSON数据

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {


	@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
		HttpStatus status = getStatus(request);
		Map model = Collections
				.unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
		response.setStatus(status.value());
        //跳转到那个错误页面
		ModelAndView modelAndView = resolveErrorView(request, response, status, model);
		return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
	}

	@RequestMapping
	public ResponseEntity> error(HttpServletRequest request) {
		HttpStatus status = getStatus(request);
		if (status == HttpStatus.NO_CONTENT) {
			return new ResponseEntity<>(status);
		}
		Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
		return new ResponseEntity<>(body, status);
	}
}


3.ErrorPageCustomizer

private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {

		private final ServerProperties properties;

		private final DispatcherServletPath dispatcherServletPath;

		protected ErrorPageCustomizer(ServerProperties properties, DispatcherServletPath dispatcherServletPath) {
			this.properties = properties;
			this.dispatcherServletPath = dispatcherServletPath;
		}

		@Override
		public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
			ErrorPage errorPage = new ErrorPage(
					this.dispatcherServletPath.getRelativePath(this.properties.getError().getPath()));
			errorPageRegistry.addErrorPages(errorPage);
		}

系统出现错误后来到error请求进行处理, BasicErrorController

public class ErrorProperties {

	/**
	 * Path of the error controller.
	 */
	@Value("${error.path:/error}")
	private String path = "/error";


4.DefaultErrorViewResolver

系统默认是找工程目录下error下的错误代码页面,比如error/404.html

模板引擎可以解析的就返回对应的页面,不能解析就去找静态资源下的页面error/404.html

public class DefaultErrorViewResolver implements ErrorViewResolver, Ordered {

	private static final Map SERIES_VIEWS;

	static {
		Map views = new EnumMap<>(Series.class);
		views.put(Series.CLIENT_ERROR, "4xx");
		views.put(Series.SERVER_ERROR, "5xx");
		SERIES_VIEWS = Collections.unmodifiableMap(views);
	}
	
	
	@Override
	public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map model) {
		ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
		if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
			modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
		}
		return modelAndView;
	}
	
	private ModelAndView resolve(String viewName, Map model) {
		String errorViewName = "error/" + viewName;
		TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
				this.applicationContext);
		if (provider != null) {
			return new ModelAndView(errorViewName, model);
		}
		return resolveResource(errorViewName, model);
	}
	
	private ModelAndView resolveResource(String viewName, Map model) {
		for (String location : this.resourceProperties.getStaticLocations()) {
			try {
				Resource resource = this.applicationContext.getResource(location);
				resource = resource.createRelative(viewName + ".html");
				if (resource.exists()) {
					return new ModelAndView(new HtmlResourceView(resource), model);
				}
			}
			catch (Exception ex) {
			}
		}
		return null;
	}

错误处理规则:

1.系统当中出现了错误信息4xx、5xx等错误信息ErrorPageCustomizer组件就会生效

2.出现错误后系统会发出error请求BasicErrorController进行处理,错误页面的跳转由默认的错误页面解析器处理DefaultErrorViewResolver

protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status,
			Map model) {
		for (ErrorViewResolver resolver : this.errorViewResolvers) {
			ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
			if (modelAndView != null) {
				return modelAndView;
			}
		}
		return null;
	}

 

你可能感兴趣的:(SpringBoot,Restful)