Spring Boot 05 —— web开发案例

Spring Boot 的一些坑 https://www.jianshu.com/p/3494c84b4be3

国际化:

1)设置首页:

方法1:在controller添加一个请求

    @RequestMapping({"/","index.html"})
    public String index(){
        return "index.html";
    }

 方法2:设置配置文件  :WebMvcConfigurer  的  addViewControllers  中     registry.addViewController("/index.html").setViewName("login");         registry.addViewController("/").setViewName("login");

package com.anitano.config;

import com.anitano.component.MyLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 *扩展SpringMVC的功能
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        /*视图映射 :当浏览器发送 anita 会来到success*/
        registry.addViewController("/anita").setViewName("success");
    }

    /**
     * 所以的WebMvcConfigurer组件都会起作用
     * @return
     */
    @Bean //记得加到容器里
    public WebMvcConfigurer webMvcConfigurer(){
        WebMvcConfigurer adapter= new WebMvcConfigurer() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/login.html").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/dashboard.html").setViewName("dashboard");
            }

            /*设置拦截器*/
            @Override
            public void addInterceptors(InterceptorRegistry registry) {

            }
        };
        return adapter;
    }
    /**
     * 修改区域信息解析器
     * @return
     */
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

2)修改细节:导入命名空间并设置中文页面

<html lang="zh-cn" xmlns:th="http://www.thymeleaf.org">

 添加 th:src="@{ asserts/img/bootstrap-solid.svg }"    当项目名称改变时,链接会自动加上 项目名称。

<img class="mb-4" src="asserts/img/bootstrap-solid.svg" th:src="@{asserts/img/bootstrap-solid.svg}"  alt="" width="72" height="72">

2)国际化  i18n

1、新建一个文件夹 i18n 和几个配置文件,IDEA会自动识别你要做国际化。    注意要在setting 里边设置 File Encoding 将 配置文件设置 UTF-8编码 和 asii 的方式,

 2、打开随便其中一个文件,点击下方的 Resource Bundle ,在上方有一个 + 号,点击 + 添加属性。 添加完成后增加属性内容。

 3、指定国际化资源的配置文件位置 : 在项目的配置文件里边添加 :spring.messages.basename=i18n.login

 4、在页面获取国际化的值:th:text="#{login.tip}"

<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<!DOCTYPE html>
<html lang="zh-cn" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
		<meta name="description" content="">
		<meta name="author" content="">
		<title>Signin Template for Bootstrap</title>
		<!-- Bootstrap core CSS -->
		<link href="asserts/css/bootstrap.min.css" th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">
		<!-- Custom styles for this template -->
		<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
	</head>

	<body class="text-center">
		<form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post">
			<img class="mb-4" src="asserts/img/bootstrap-solid.svg" th:src="@{/asserts/img/bootstrap-solid.svg}"  alt="" width="72" height="72">
			<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
			<label class="sr-only" th:text="#{login.username}">Username</label>
			<input type="text" name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
			<label class="sr-only" th:text="#{login.password}">Password</label>
			<input type="password" name="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
			<div class="checkbox mb-3">
				<label>
          <input type="checkbox" value="remember-me"> [[#{login.remember}]]
        </label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
			<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
			<a class="btn btn-sm" th:href="@{index.html(language='zh-CN')}">中文</a>
			<a class="btn btn-sm" th:href="@{index.html(language='en-US')}">English</a>
		</form>

	</body>

</html>

 到这里就会根据浏览器的语言显示中英文。 如果到这里有中文乱码,是因为前面说过的 配置文件的编码方式不是 UTF-8

 5 ) 修改 SpringMVC 配置文件,将默认的 根据请求头 设置区域信息进行国际化,改为 点击链接 切换国际化。

添加一个类

package com.anitano.component;

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;

/**
 * 区域信息解析器
 */
    public class MyLocaleResolver implements LocaleResolver {
        @Override
        public Locale resolveLocale(HttpServletRequest httpServletRequest) {
            String language = httpServletRequest.getParameter("language");
            Locale locale=Locale.getDefault();
            if(!StringUtils.isEmpty(language)){
                String[] strings = language.split("_");
                locale=new Locale(strings[0],strings[1]);
            }
            return locale;
        }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}

 修改自己新增加的SpringMVC的配置文件类:

    /**
     * 修改区域信息解析器
     * @return
     */
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }

 切换中英文的链接

<a class="btn btn-sm" th:href="@{index.html(language='zh-CN')}">中文</a>
<a class="btn btn-sm" th:href="@{index.html(language='en-US')}">English</a>

用户登录

 开发期间模板引擎页面修改以后,要实时生效: 首先 禁止模板引擎的缓存,   Ctrl+F9 :重新编译

#禁止模板引擎的缓存
spring.thymeleaf.cache=false

当密码错误时:从返回的信息中读取错误信息。  只有存在错误信息才显示出来

<p class="text-danger" th:text="${msg}" th:if="${ not #strings.isEmpty(msg)}"></p>

 登录成功后的重定向 :

registry.addViewController("/dashboard.html").setViewName("dashboard")
package com.anitano.config;

import com.anitano.component.MyLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
 *扩展SpringMVC的功能
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        /*视图映射 :当浏览器发送 anita 会来到success*/
        registry.addViewController("/anita").setViewName("success");
        registry.addViewController("/dashboard.html").setViewName("dashboard");
    }

    /**
     * 修改区域信息解析器
     * @return
     */
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

 return "redirect:/dashboard.html";

    @PostMapping(value = "user/login")
    public String login(@RequestParam("username")String username, @RequestParam("password")String password, Map<String,Object> map){
        if(!StringUtils.isEmpty(username) && "123456".equals(password)){
            //return "dashboard";
            return "redirect:/dashboard.html";
        }
        map.put("msg","用户名或密码错误");
        return "index";
    }

 设置拦截器:Spring Boot 1.x 版本设置拦截器后静态资源不会被拦截, 2.x 版本静态资源反而会被拦截 ,所以要放行

 关于设置拦截器后的静态资源被拦截: https://my.oschina.net/dengfuwei/blog/1795346

1) 新添加一个方法:

package com.anitano.component;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截器组件:登录拦截,没有登录不允许进入后台页面 和 对员工进行增删改查
 */
public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //方法执行前
        Object user = request.getSession().getAttribute("LoginUser");
        if(user == null){
            //未登录,返回登录页面
            request.setAttribute("msg","没有登录请先登录");
            request.getRequestDispatcher("/login.html").forward(request,response);
            return false;
        }else {
            //已登录,
            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 {

    }
}

2) 在配置文件配置: 注意放行  /user/login  前面要加 /

 /*注册拦截器*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
        .excludePathPatterns("/","/index.html","/user/login","/login.html","/asserts/**");
       /*拦截 所有请求, 放行 "/","/index.html","user/login" */
}

 完整配置文件:

package com.anitano.config;

import com.anitano.component.LoginHandlerInterceptor;
import com.anitano.component.MyLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 *扩展SpringMVC的功能
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        /*视图映射 :当浏览器发送 anita 会来到success*/
        registry.addViewController("/anita").setViewName("success");
    }

    /**
     * 所以的WebMvcConfigurer组件都会起作用
     * @return
     */
    @Bean //记得加到容器里
    public WebMvcConfigurer webMvcConfigurer(){
        WebMvcConfigurer adapter= new WebMvcConfigurer() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/login.html").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }
            /*注册拦截器*/
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
                        .excludePathPatterns("/","/index.html","/user/login","/login.html","/asserts/**");
                /*拦截 所有请求, 放行 "/","/index.html","user/login" */
            }
        };
        return adapter;
    }
    /**
     * 修改区域信息解析器
     * @return
     */
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

 公共页抽取

#在 dashboard.html 抽取公共页
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar"></nav>

#在 list.html 页面应用   ---> 这样只会插入 <nav></nav>,不会也把 <div></div> 插进去
<div th:replace="dashboard::topbar">

 所谓   模板名::选择器   HTML模板 ::ID选择器 或者 class选择器             ----> # 选择器名    .选择器名

1、抽取公共片段 <div th:fragment="copy"> © 2011 The Good Thymes Virtual Grocery </div>   
2、引入公共片段 <div th:insert="~{footer :: copy}"></div>
~{templatename::selector}:模板名::选择器 
~{templatename::fragmentname}:模板名::片段名   
3、默认效果: 
insert的公共片段在div标签中 
如果使用th:insert等属性进行引入,可以不用写~{}: 
行内写法可以加上:[[~{}]];[(~{})];

三种引入公共片段的th属性:

th:insert:将公共片段整个插入到声明引入的元素中  ---->   例如上面,这个会把 <div>   <nav></nav>  </div> 导入进去
th:replace:将声明引入的元素替换为公共片段         ------> 这样只会插入 <nav></nav>,不会也把 <div></div> 导入进去

th:include:将被引入的片段的内容包含进这个标签中 ----->只有<div></div>  ,里边不会有 <nav></nav>

动态链接高亮:

1)抽取时添加一个 变量 activeUri

 th:fragment="navbar(activeUri)"

2)进行判断: 加入这个变量值为 main 则标为 高亮

th:classappend="${activeUri}=='main'?' active ' :''"

3)引入时设置一个变量值

<!--引入侧边栏-->
<div th:replace="commons/bar::navbar(activeUri='main')"></div>

 显示员工数据:

 时间格式化:${ #dates.format(emp.birth,'yyyy/MM/dd HH:mm') }

    						<table class="table table-striped table-sm">
							<thead>
								<tr>
									<th>#</th>
									<th>lastName</th>
									<th>email</th>
									<th>gender</th>
									<th>department</th>
									<th>birth</th>
								</tr>
							</thead>
							<tbody>
							<tr th:each="emp:${emps}">
								<td th:text="${emp.id}"></td>
								<td th:text="${emp.lastName}"></td>
								<td th:text="${emp.email}"></td>
								<td th:text="${emp.gender}==0?'女':'男' "></td>
								<td th:text="${emp.department.departmentName}"></td>
								<td th:text="${ #dates.format(emp.birth,'yyyy/MM/dd  HH:mm')  }"></td>
							</tr>
							</tbody>
						</table>

 自动化装配,修改日期格式 :

#日期格式化类型
spring.mvc.date-format=yyyy-MM-dd HH:mm

 路径变量: 链接  http://localhost:8080/emp/1001    想要把 1001 当做一个值获取。 使用@GetMapping("/emp/{id}")  ,在参数上 使用 @PathVariable("id") Integer id

    @GetMapping("/emp/{id}")
    public String toEditPage(@PathVariable("id") Integer id,Model model){
        Employee employee = employeeDao.get(id);
        model.addAttribute("employee",employee);
        return "/emp/add";
    }

  

 修改表单的提交方式:在from表单里添加 下面的语句:当employee这个值存在时,将这条标签添加到页面里边,并且提交方式为 put。

<input type="hidden" value="put" th:if="${employee} !=null">

 form表单必填: required=""

 a

猜你喜欢

转载自www.cnblogs.com/Lemonades/p/11629016.html