SpringBoot之Web开发

自动配置原理?

这个场景SpringBoot帮我们配置了什么?能不能修改?能修改哪些配置?能不能扩展?xxx

xxxxAutoConfiguration:帮我们给容器中自动配置组件;

xxxxProperties:配置类来封装配置文件的内容;

Web开发的自动配置类:org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration

RestfulCRUD

1)、默认访问首页

//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
//@EnableWebMvc   不要接管SpringMVC
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
@Override
    public void addViewControllers(ViewControllerRegistry registry) {
       // super.addViewControllers(registry);
        //浏览器发送 /zhou 请求来到 success
        registry.addViewController("/zhou").setViewName("success");
    }
    //所有的WebMvcConfigurerAdapter组件都会一起起作用
    @Bean //将组件注册在容器
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
            }
        };
        return adapter;
    }
}
2)、国际化
1)、编写国际化配置文件;
2)、使用ResourceBundleMessageSource管理国际化资源文件
3)、在页面使用fmt:message取出国际化内容
步骤:

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


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

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

@ConfigurationProperties(prefix = "spring.messages")
public class MessageSourceAutoConfiguration {
   
    /**
 * Comma‐separated list of basenames (essentially a fully‐qualified classpath    
 * location), each following the ResourceBundle convention with relaxed support for    
 * slash based locations. If it doesn't contain a package qualifier (such as    
 * "org.mypackage"), it will be resolved from the classpath root.    
 */    
private String basename = "messages";      
    //我们的配置文件可以直接放在类路径下叫messages.properties(默认国际化资源文件);
   
    @Bean
public MessageSource messageSource() {    
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();        
if (StringUtils.hasText(this.basename)) {        
            //设置国际化资源文件的基础名(去掉语言国家代码的)
messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(            
StringUtils.trimAllWhitespace(this.basename)));                    
}        
if (this.encoding != null) {        
messageSource.setDefaultEncoding(this.encoding.name());            
}        
messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);        
messageSource.setCacheSeconds(this.cacheSeconds);        
messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat);        
return messageSource;        
} 
spring.messages.basename=i18n.login #修改国际化资源文件
<h1 class="h3 mb‐3 font‐weight‐normal" th:text="#{login.tip}">Please signin</h1> 
<input type="checkbox" value="remember‐me"/> [[#{login.remember}]]           
<label class="sr‐only" th:text="#{login.username}">Username</label>

3)、去页面获取国际化的值;

效果:根据浏览器语言设置的信息切换了国际化;
原理:

国际化Locale(区域信息对象);LocaleResolver(获取区域信息对象);

@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;            
}        
默认的就是根据请求头带来的区域信息获取Locale进行国际化

4)、点击链接切换国际化

/**
 * 可以在连接上携带区域信息
 */
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[] split = l.split("_");
            locale = new Locale(split[0],split[1]);
        }
        return locale;
    }
    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale
locale) {
    }
}
 @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}
3)、登陆

开发期间模板引擎页面修改以后,要实时生效

1)、禁用模板引擎的缓存

# 禁用缓存
spring.thymeleaf.cache=false
2)、页面修改完成以后ctrl+f9:重新编译;
登陆错误消息的显示
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
4)、拦截器进行登陆检查

拦截器

/**
 * 登陆检查,
 */
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("/index.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 {
    }

注册拦截器

//所有的WebMvcConfigurerAdapter组件都会一起起作用
    @Bean //将组件注册在容器
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                registry.addViewController("/main.html").setViewName("dashboard");
            }
            //注册拦截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                //super.addInterceptors(registry);
                //静态资源;  *.css , *.js
                //SpringBoot已经做好了静态资源映射
                registry.addInterceptor(new
LoginHandlerInterceptor()).addPathPatterns("/**")
                        .excludePathPatterns("/index.html","/","/user/login");
            }
        };
        return adapter;
    }
通过[[${session.loginUser]]获取登录成功的用户
5)、CRUD-员工列表
实验要求:
1)、RestfulCRUD:CRUD满足Rest风格;

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


2)、实验的请求架构;


3)、员工列表:

thymeleaf公共页面元素抽取

1、抽取公共片段
<div th:fragment="copy">
&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:将公共片段整个插入到声明引入的元素中
th:replace:将声明引入的元素替换为公共片段

th:include:将被引入的片段的内容包含进这个标签中

<footer th:fragment="copy">
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
引入方式
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
效果
<div>
    <footer>
    &copy; 2011 The Good Thymes Virtual Grocery
    </footer>
</div>
<footer>
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
<div>
&copy; 2011 The Good Thymes Virtual Grocery
</div>

使用选择器方式引入:

<!--引入侧边栏-->
<div th:replace="dashboard::#sidebar"></div>
引入片段的时候传入参数:
<nav class="col‐md‐2 d‐none d‐md‐block bg‐light sidebar" id="sidebar">
    <div class="sidebar‐sticky">
        <ul class="nav flex‐column">
            <li class="nav‐item">
                <a class="nav‐link active"
                   th:class="${activeUri=='main.html'?'nav‐link active':'nav‐link'}"
                   href="#" th:href="@{/main.html}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke‐width="2" stroke‐
linecap="round" stroke‐linejoin="round" class="feather feather‐home">
                        <path d="M3 9l9‐7 9 7v11a2 2 0 0 1‐2 2H5a2 2 0 0 1‐2‐2z"></path>
                        <polyline points="9 22 9 12 15 12 15 22"></polyline>
                    </svg>
                    Dashboard <span class="sr‐only">(current)</span>
                </a>
            </li>
<!‐‐引入侧边栏;传入参数‐‐>
<div th:replace="commons/bar::#sidebar(activeUri='emps')"></div>

高亮显示:

<a class="nav-link active" href="#" th:href="@{/emps}"
th:class="${activeUri=='emps'?'nav-link active':'nav-link'}">

6)、CRUD-员工添加

提交的数据格式不对:生日:日期;
2017-12-12;2017/12/12;2017.12.12;
日期的格式化;SpringMVC将页面提交的值需要转换为指定的类型;
2017-12-12---Date; 类型转换,格式化;

默认日期是按照/的方式;

spring.mvc.date-format=yyyy-MM-dd

7)、CRUD-员工修改

<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑</a>

修改添加二合一表单

<!‐‐需要区分是员工修改还是添加;‐‐>
<form th:action="@{/emp}" method="post">
    <!‐‐发送put请求修改员工数据‐‐>
    <!‐‐
1、SpringMVC中配置HiddenHttpMethodFilter;(SpringBoot自动配置好的)
2、页面创建一个post表单
3、创建一个input项,name="_method";值就是我们指定的请求方式
‐‐>
<input type="hidden" name="_method" value="put" th:if="${emp!=null}"/>
8)、CRUD-员工删除
<button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn‐sm btn‐danger
deleteBtn">删除</button>
<script>
    $(".deleteBtn").click(function(){
        //删除当前员工的
        $("#deleteEmpForm").attr("action",$(this).attr("del_uri")).submit();
        return false;
    });
</script>

猜你喜欢

转载自blog.csdn.net/qq_35508033/article/details/80714948