spring mvc 实现网站登录与非登录的控制

news/2024/5/11 17:01:33/文章来源:https://blog.csdn.net/az44yao/article/details/8442961

在我们的网站平台上,主要有两类页面,一类是非登录也能查看的页面,另一类是登录后才能查看的页面

通过使用 spring拦截器来实现,当用户没有登录时访问需要登录的页面时自动实现跳转至登录页

1、添加接口用于拦截器与控制器交互数据(包括上下文与登录帐号信息)

View Code IWebContext
/**
 * 用于实现上下文连接 用于在过滤器中实现注入Request与Response
 * 
@author Administrator
 *
 
*/
public interface IWebContext {
    /**
     * 设置请求与应答上下文
     * 
@param request 请求
     * 
@param response 应答
     * 
@param userType 用户类型
     * 
@param loginUrl 登录页面的URL
     
*/
    public void setWebContext(HttpServletRequest request, HttpServletResponse response, UserTypeEnum userType, String loginUrl);
    /**
     * 获取登录帐号
     * 
@return 返回当前的登录帐号,如果没有登录则返回空
     
*/
    public LoginAccount getLoginAccount();
}

2、所有的Controller都继承自BaseController 

View Code BaseController
@Controller
public class BaseController implements IWebContext {
    private static final Logger log = Logger.getLogger(BaseController.class);
    /*********************获取Request与Response*******************/
    /**
     * 请求上下文
     
*/
    private HttpServletRequest request;
    /**
     * 应答上下文
     
*/
    private HttpServletResponse response;
    /**
     * 校验当前登录用户的用户类型
     
*/
    private UserTypeEnum userType;
    /**
     * 登录的页面  当访问需要登录的页面时,自动转到该页面
     
*/
    private String loginUrl; 
    /**
     * 设置请求与应答的上下文
     
*/
    @Override
    public void setWebContext(HttpServletRequest request, HttpServletResponse response, UserTypeEnum userType, String loginUrl){
        this.request = request;
        this.response = response;
        this.userType = userType;
        this.loginUrl = loginUrl;
        //重置当前访问的数据
        this.loginAccount = null;
        this.remoteIp = null;
    }
    /**
     * 当前的请求对象
     * 
@return
     
*/
    protected HttpServletRequest getRequest(){
        //((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest(); 
        return this.request;
    }
    /**
     * 获取当前的应答对象
     * 
@return
     
*/
    protected HttpServletResponse getResponse(){
        return this.response;
    }
    /*********************获取Request与Response*******************/
    
    /*********************用户登录相关*******************/
    /**
     * 当前登录的帐号
     
*/
    private LoginAccount loginAccount = null;
    /**
     * 该对象在调用isLogged方法后才有效
     * 
@return
     
*/
    @Override
    public LoginAccount getLoginAccount(){
        if (this.loginAccount == null){
            this.loginAccount = new LoginAccount();
            if (!this.getCookieObject(LoginAccount.USERCOOKINAME, this.loginAccount)){
                this.loginAccount = null;
                return null;
            }
            if (!UserLoginBLL.verifyToken(this.loginAccount, this.userType)){//校验令牌
                this.loginAccount = null;
                return null;
            }
        }
        return this.loginAccount;
    }
    /**
     * 判断用户是否已经登录
     * 
@return
     
*/
    protected boolean isLogged(){
        return this.getLoginAccount() != null;
    }
    /**
     * 跳转到登录页面
     * 
@return
     
*/
    protected ModelAndView toLoginView(){
        return new ModelAndView(new RedirectView(this.loginUrl), "tourl", this.getRequest().getRequestURI());
    }
    /*********************用户登录相关*******************/
    
    /*********************获取访问IP*******************/
    /**
     * 获取远程访问IP
     
*/
    private String remoteIp = null;
    /**
     * 获取远程访问IP
     * 
@return
     
*/
    protected String getRemoteIp(){
        HttpServletRequest request = this.getRequest();
        if (this.remoteIp==null || this.remoteIp.length()==0)
        {
            this.remoteIp = request.getHeader("x-forwarded-for");
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getHeader("X-Real-IP");
            }
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getHeader("Proxy-Client-IP");
            }
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getHeader("WL-Proxy-Client-IP");
            }
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getHeader("HTTP_CLIENT_IP");
            }
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getRemoteAddr();
            }
            if (this.remoteIp == null || this.remoteIp.isEmpty() || "unknown".equalsIgnoreCase(this.remoteIp)) {
                this.remoteIp= request.getRemoteHost();
            }
        }
        return remoteIp;
    }
    /*********************获取访问IP*******************/
    /*********************获取访问参数*******************/
    /**
     * 获取所有参数
     * 
@return
     
*/
    protected Map<String,String[]> getParams(){
        HttpServletRequest request = this.getRequest();
        return request.getParameterMap();
    }
    /**
     * 获取指定的配置
     * 
@param name
     * 
@return
     
*/
    protected String getParam(String name){
        return getParam(name, "");
    }
    /**
     * 根据参数名称获取参数值,如果没有找到则以默认值返回
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected String getParam(String name, String defaultValue){
        HttpServletRequest request = this.getRequest();
        String strValue = request.getParameter(name);
        return strValue == null ? defaultValue : strValue;
    }
    /**
     * 获取整形的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected int getIntParam(String name){
        return getParam(name, 0);
    }
    /**
     * 获取整形的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected int getParam(String name, Integer defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Integer.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取长整形的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected long getLongParam(String name){
        return getParam(name, 0L);
    }
    /**
     * 获取长整形的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected long getParam(String name, Long defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Long.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取单精度的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected float getFloatParam(String name){
        return getParam(name, 0F);
    }
    /**
     * 获取单精度的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected float getParam(String name, Float defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Float.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取双精度的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected double getDoubleParam(String name){
        return getParam(name, 0D);
    }
    /**
     * 获取双精度的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected double getParam(String name, Double defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Double.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取字节的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected byte getByteParam(String name){
        return getParam(name, (byte)0);
    }
    /**
     * 获取字节的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected byte getParam(String name, Byte defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Byte.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取字节的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected short getShortParam(String name){
        return getParam(name, (short)0);
    }
    /**
     * 获取字节的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected short getParam(String name, Short defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Short.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取布尔的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected boolean getBooleanParam(String name){
        return getParam(name, false);
    }
    /**
     * 获取布尔的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected boolean getParam(String name, Boolean defaultValue){
        String strValue = getParam(name, defaultValue.toString());
        try{
            return Boolean.valueOf(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /**
     * 获取日期的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected Date getDateParam(String name){
        return getParam(name, new Date());
    }
    /**
     * 获取日期的参数值
     * 
@param name
     * 
@param defaultValue
     * 
@return
     
*/
    protected Date getParam(String name, Date defaultValue){
        String strValue = getParam(name);
        if (strValue == null || strValue.length() == 0)
            return defaultValue;
        try{
            return DateUtil.getDateFromString(strValue);
        }
        catch(Exception e){
            return defaultValue;
        }
    }
    /*********************获取访问参数*******************/
    /*******************操作Cookie********************/
    /**
     * 获取指定键的Cookie
     * 
@param cookieName
     * 
@return 如果找到Cookie则返回 否则返回null
     
*/
    protected Cookie getCookie(String cookieName){
        if (StringUtil.isNullOrWhiteSpace(cookieName) || this.getRequest().getCookies() == null)
            return null;
        for(Cookie cookie : this.getRequest().getCookies()){
            if (cookieName.equals(cookie.getName()))
                return cookie;
        }
        return null
    }
    /**
     * 获取指定键的Cookie值
     * 
@param cookieName
     * 
@return 如果找到Cookie则返回 否则返回null
     
*/
    protected String getCookieValue(String cookieName){
        Cookie cookie = this.getCookie(cookieName);
        return cookie == null ? null : cookie.getValue();
    }
    /**
     * 删除指定的Cookie
     * 
@param cookieName
     
*/
    protected void removeCookie(String cookieName){
        HttpServletResponse response = this.getResponse();
        Cookie cookie = new Cookie(cookieName, null);
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }
    /**
     * 保存一个对象到Cookie里   Cookie只在会话内有效
     * 
@param cookieName
     * 
@param inst
     
*/
    protected void setCookie(String cookieName, Object inst){
        this.setCookie(cookieName, "/", inst);
    }
    /**
     * 保存一个对象到Cookie  Cookie只在会话内有效
     * 
@param cookieName
     * 
@param path
     * 
@param inst
     
*/
    protected void setCookie(String cookieName, String path, Object inst){
        if (StringUtil.isNullOrWhiteSpace(cookieName) || inst == null)
            return;
        String strCookieString = this.object2CookieString(inst);
        this.setCookie(cookieName, path, strCookieString);
    }
    /**
     * 保存一个对象到Cookie
     * 
@param cookieName
     * 
@param inst
     * 
@param expiry (秒)设置Cookie的有效时长, 负数不保存,0删除该Cookie 
     
*/
    protected void setCookie(String cookieName, Object inst, int expiry){
        this.setCookie(cookieName, "/", inst, expiry);
    }
    /**
     * 保存一个对象到Cookie
     * 
@param cookieName
     * 
@param path
     * 
@param inst
     * 
@param expiry (秒)设置Cookie的有效时长, 负数不保存,0删除该Cookie 
     
*/
    protected void setCookie(String cookieName, String path, Object inst, int expiry){
        if (StringUtil.isNullOrWhiteSpace(cookieName) || inst == null || expiry < 0)
            return;
        String strCookieString = this.object2CookieString(inst);
        this.setCookie(cookieName, path, strCookieString, expiry);
    }
    /**
     * 保存一个对象到Cookie里   Cookie只在会话内有效
     * 
@param cookieName
     * 
@param cookieValue
     
*/
    protected void setCookie(String cookieName, String cookieValue){
        this.setCookie(cookieName, "/", cookieValue);
    }
    /**
     * 保存一个对象到Cookie  Cookie只在会话内有效
     * 
@param cookieName
     * 
@param path
     * 
@param cookieValue
     
*/
    protected void setCookie(String cookieName, String path, String cookieValue){
        HttpServletResponse response = this.getResponse();
        if (StringUtil.isNullOrWhiteSpace(cookieName) || cookieValue == null)
            return;
        Cookie cookie = new Cookie(cookieName, cookieValue);
        if (!StringUtil.isNullOrWhiteSpace(path)){
            cookie.setPath(path);
        }
        response.addCookie(cookie);
    }
    /**
     * 保存一个对象到Cookie
     * 
@param cookieName
     * 
@param cookieValue
     * 
@param expiry (秒)设置Cookie的有效时长, 负数不保存,0删除该Cookie 
     
*/
    protected void setCookie(String cookieName, String cookieValue, int expiry){
        this.setCookie(cookieName, "/", cookieValue, expiry);
    }
    /**
     * 保存一个对象到Cookie
     * 
@param cookieName
     * 
@param path
     * 
@param cookieValue
     * 
@param expiry (秒)设置Cookie的有效时长, 负数不保存,0删除该Cookie 
     
*/
    protected void setCookie(String cookieName, String path, String cookieValue, int expiry){
        if (StringUtil.isNullOrWhiteSpace(cookieName) || cookieValue == null || expiry < 0)
            return;
        HttpServletResponse response = this.getResponse();
        if (StringUtil.isNullOrWhiteSpace(cookieName) || cookieValue == null)
            return;
        Cookie cookie = new Cookie(cookieName, cookieValue);
        if (!StringUtil.isNullOrWhiteSpace(path)){
            cookie.setPath(path);
        }
        cookie.setMaxAge(expiry);
        response.addCookie(cookie);
    }
    /**
     * 把对象转换为Cookie存贮字串
     * 
@param inst
     * 
@return
     
*/
    private String object2CookieString(Object inst){
        if (inst == null)
            return "";
        StringBuilder strCookieValue = new StringBuilder();
        for(java.lang.reflect.Field field : inst.getClass().getDeclaredFields()){
            try{
                if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) || 
                        java.lang.reflect.Modifier.isFinal(field.getModifiers())){
                    continue;
                }    
                if (!this.isSimpleProperty(field.getType())) continue;//不是元数据
                field.setAccessible(true);// 提升权限
                Object objValue = field.get(inst);
                String strValue;
                if (field.getType().equals(Date.class)){
                    strValue = DateUtil.getLongStrFromDate((Date)objValue);
                }else{
                    strValue = objValue == null ? "" : objValue.toString();
                }
                if (strCookieValue.length() > 0){
                    strCookieValue.append(String.format("&%s=%s", field.getName(), URLEncoder.encode(strValue,"UTF-8")));
                }
                else{
                    strCookieValue.append(String.format("%s=%s", field.getName(), URLEncoder.encode(strValue,"UTF-8")));
                }    
            }
            catch(Exception e){
                log.fatal("object2CookieString faild", e);
                continue;
            }
        }
        return strCookieValue.toString();
    }
    /**
     * 从Cookie中获对对象
     * 
@param cookieName
     * 
@param inst
     * 
@return 如果获取转换成功,则返回true, 否则返回false
     
*/
    protected boolean getCookieObject(String cookieName, Object inst){
        if (inst == null){
            return false;
        }
        String cookieValue = this.getCookieValue(cookieName);
        if (cookieValue == null){
            return false;
        }
        for(java.lang.reflect.Field field : inst.getClass().getDeclaredFields()){
            try{
                if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) || 
                        java.lang.reflect.Modifier.isFinal(field.getModifiers())){
                    continue;
                }
                if (!this.isSimpleProperty(field.getType())) continue;//不是元数据
                field.setAccessible(true);// 提升权限
                
                Pattern pattern = Pattern.compile(String.format("(^|&)%s=([^(&|$)]+)", field.getName()));
                Matcher matcher = pattern.matcher(cookieValue);
                String strValue = "";
                if (matcher.find()){
                    strValue = matcher.group(2);
                    strValue = URLDecoder.decode(strValue, "UTF-8");
                }
                field.set(inst, ConvertUtil.convertSimpleValue(field.getType(), strValue));
            }
            catch(Exception e){
                log.fatal("getCookieObject faild", e);
                return false;
            }
        }
        return true;
    }
    /**
     * 是否是简单的数据类型
     * 
@param type
     * 
@return
     
*/
    private boolean isSimpleProperty(Class<?> propType){
        if (!propType.isPrimitive() && !propType.isEnum() && (!propType.equals(String.class) && !propType.equals(Date.class)))
        {
            return false;
        }
        return true;
    }
    /*******************操作Cookie********************/
}

3、编写拦截器 

View Code LoggedInterceptor
/**
 * 已经登录拦截器
 * 
@author Administrator
 *
 
*/
public class LoggedInterceptor extends HandlerInterceptorAdapter {


    /**
     * 登录页面的URL
     
*/
    private UserTypeEnum userType = UserTypeEnum.Personal;
    /**
     * 登录的页面URL  当未登录访问已登录的页面时,自动跳转到该页面
     * 
@param loginUrl
     
*/
    public void setUserType(UserTypeEnum userType){
        this.userType = userType;
    }
    /**
     * 登录页面的URL
     
*/
    private String loginUrl;
    /**
     * 登录的页面URL  当未登录访问已登录的页面时,自动跳转到该页面
     * 
@param loginUrl
     
*/
    public void setLoginUrl(String loginUrl){
        this.loginUrl = loginUrl;
    }
    /**
     * 利用正则映射到需要拦截的路径
     
*/
    private String[] regexUrls;
    /**
     * 利用正则映射到需要拦截的路径
     * 
@param mappingURL
     
*/
    public void setRegexUrls(String[] regexUrls) {
        this.regexUrls = regexUrls;
    }
    /**
     * 在Controller方法前进行拦截
     
*/
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果handler controller实现了接口,则设置上下文
        LoginAccount loginAccount = null;
        if (handler != null && handler instanceof IWebContext){
            ((IWebContext)handler).setWebContext(request, response, userType, this.loginUrl);
            loginAccount = ((IWebContext)handler).getLoginAccount();
        }
        
        String strUrl = request.getRequestURI();
        if (loginAccount == null && !StringUtil.isNullOrEmpty(strUrl) && regexUrls != null && regexUrls.length >0){
            for(String regex : regexUrls){
                if (StringUtil.isNullOrEmpty(regex)){
                    continue;
                }
                if (strUrl.matches(regex)){ //当前页面需要登录
                    String strToUrl = "/login.htm?tourl=" + URLEncoder.encode(strUrl, "utf-8");
                    if ("GET".equalsIgnoreCase(request.getMethod())){
                        response.sendRedirect(strToUrl);//转到登录页    
                    }else{
                        //Json返回数据
                        JsonResponse jsonResponse = new JsonResponse();
                        jsonResponse.setFaildMsg(JsonResponse.Nologin, "请登录后操作", strToUrl);
                        Gson gson = null;
                        PrintWriter printWriter = null;
                        try{
                            gson = new Gson();
                            String strJson = gson.toJson(jsonResponse);
                            response.setContentType("application/json");
                            printWriter = response.getWriter();
                            printWriter.print(strJson);
                            printWriter.flush();
                        }
                        finally{
                            if (printWriter != null){
                                printWriter.close();
                            }
                            gson = null;
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * This implementation is empty.
     
*/
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if (handler != null && handler instanceof IWebContext
                && modelAndView != null && "GET".equalsIgnoreCase(request.getMethod())){
            //当get的时候,系统自动封闭loginAccount到modelAndView里
            modelAndView.addObject("loginAccount", ((IWebContext)handler).getLoginAccount());
        }
    }

    /**
     * 在Controller方法后进行拦截
     
*/
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        
    }
}

4、修改配置文件  

View Code SpringMvc-servelet.xml
<!-- 以下正则符合的页面必须登录后才能访问 -->
    <bean id="loggedInterceptor" class="com.zufangbao.web.base.LoggedInterceptor">
        <!-- 用户类型 注入 -->
        <property name="userType">
            <bean class="com.zufangbao.enums.UserTypeEnum" factory-method="fromValue">
                <constructor-arg>
                    <value>1</value>
                </constructor-arg>
            </bean>
        </property>
        <!-- 登录页面 -->
        <property name="loginUrl" value="login.htm"/>
        <!-- 必须登录后才能访问的页面 -->
        <property name="regexUrls">
            <list>
                <value>/rentlist.*</value>
                <value>/rentdetail.*</value>
                <value>/getrentpagelist.*</value>
                <value>/cancelrentrecord.*</value>
            </list>
        </property>
    </bean>
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
         <property name="interceptors">
             <list>
                 <ref bean="loggedInterceptor"/>
             </list>
         </property>
    </bean>
    <!-- Json支持 -->
     <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
         <property name="messageConverters">
            <list>
                <ref bean="jacksonMessageConverter"/>
              </list>
        </property>
    </bean>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_757318.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jsp为什么错误页面不跳转_为什么网站页面不收录,如何提高收录率?

当百度蜘蛛去爬行互联网上的每一个URL的时候&#xff0c;它是有一套完整的过滤机制&#xff0c;言外之意&#xff0c;并非是每一个URL都是编入百度的索引库。 它会根据目标网站的信任度&#xff0c;以及内容质量&#xff0c;外部链接结构等诸多因素去衡量。 那么&#xff0c;为…

敏捷开发流程的8个步骤_8个步骤快速构建WooCommerce B2C商城网站

建立一个完全自主可控的外贸B2C商城网站&#xff0c;有多种技术方案路径&#xff0c;其中wordpress woocommerce插件是目前最成熟&#xff0c;也是最易入手的方案&#xff0c;全球有超过20%的网上商城采用以上技术方案来构建。如果我们已经熟练使用wordpress了&#xff0c;那么…

模板建站和开发网站区别_定制营销型网站建设与模板建站相比的优势特点讲解...

网络时代&#xff0c;独立网站的开发与选择模板实现建站的企业数量不相上下&#xff0c;根据实际需求&#xff0c;选择建站的方式各不相同&#xff0c;但是这两者之间有何区别呢&#xff1f;随着互联网之风盛行&#xff0c;越来越多的中小企业建立了企业网站&#xff0c;做起了…

miniui页面移动的时候透明_移动端快速建站,你应该关注的5个指标

在2019年&#xff0c;移动端建站是一个重要的侧重点&#xff0c;这是不争的事实&#xff0c;随着PC端流量向移动端大量转移的过程中&#xff0c;它变得格外的重要。 因此&#xff0c;在做移动端快速建站的时候&#xff0c;我们除了要保持站点的搜索引擎友好&#xff0c;还需要重…

python爬虫实验(静态网页内容爬取):爬取中国工程院网站相关信息

实验内容:爬取中国工程院网页上的院士信息&#xff0c;把每位院士的简介保存为本地文本文件&#xff0c;把每位院士的照片保存为本地图片&#xff0c;文本文件和图片文件都以院士的姓名为主文件名。 #-*- codeing utf-8 -*- #Time :2021/5/20 8:54 #Author :Onion #File :Exp…

Vaadin在SEO中的冒险

TL; DR &#xff1a;Vaadin过去几乎对SEO不友好。 不再有新的伏尔加河图书馆。 为页面添加书签 书签与www本身一样古老。 能够保存URL是网站ADN的一部分。 关于网络应用程序&#xff0c;这有所不同。 例如&#xff0c;在电子商务Web应用程序中&#xff0c;为特定产品添加书签确…

推荐一个命名变量的神奇网站 CODELF

推荐一个命名变量的神奇网站 CODELF 在我们写程序的时候&#xff0c;总是需要去给各种变量命名。于是各种命名大法都上来了&#xff0c;有拼音的&#xff0c;有首字母缩写的&#xff0c;各种各样。而我们推荐的命名肯定是英文的驼峰命名。今天给大家推荐一个网站&#xff1a;h…

11个资源强大的网站!知乎超20万人强烈推荐,再也不怕资源难找

在我们日常工作学习中难免就需要在网站搜索资料&#xff0c;这时候一定需要一个能够帮你搜索一切你想要的资源&#xff0c;从而为你剩下一大半时间&#xff0c;那么今天为大家整理了11个超级好用的黑科技资源搜索网站&#xff0c;帮你解决因为上网找不到合适的资源而发愁&#…

新版Bintray网站发布Library到JCenter

本文介绍了Maven、JCenter、MavenCenter、JitPack、Bintray的概念以及如何在新版的Bintray网站上发布Library并提交到JCenter上 前言 由于Bintray网站增加了Organization的概念&#xff0c;所以我在发布Library的时候发现网上很多文章都已经过时了。网站样子发生了很大的变化…

vaadin_Vaadin在SEO中的冒险

vaadinTL; DR &#xff1a;Vaadin过去几乎对SEO不友好。 不再有新的伏尔加河图书馆。 为页面添加书签 书签与www本身一样古老。 能够保存URL是网站ADN的一部分。 关于网络应用程序&#xff0c;这有所不同。 例如&#xff0c;在电子商务Web应用程序中&#xff0c;虽然为特定产品…

静态网页加一个静态的搜索框_在静态网站上搜索

静态网页加一个静态的搜索框当我将博客从WordPress移至Jekyll时&#xff0c;我遇到了让用户搜索其中内容的问题。 我没有考虑太多&#xff0c;因此使用了Google自定义搜索引擎。 在这篇文章中&#xff0c;我想回顾一下搜索静态站点的可能选项&#xff0c;并对每个站点进行回顾。…

pdf怎么打开上次看到的地方_最好用的PDF转换软件和网站

经常有小伙伴问到PDF编辑转换的问题&#xff0c;今天陈蛋蛋就专门写一篇文章讲一下这个。很早就关注我的小伙伴可能知道&#xff0c;我曾经在一篇推文中介绍过一款pdf转换的软件&#xff0c;是糖果pdf&#xff08;pdf candy&#xff09;&#xff0c;如图。可是后来我用了一段时…

oracle的sqlplus命令讲解,SQL*PLUS使用 - Oracle sqlplus命令详解_数据库技术_Linux公社-Linux系统门户网站...

五、SQL*PLUS使用a、近入SQL*Plus$sqlplus 用户名/密码退出SQL*PlusSQL>exitb、在sqlplus下得到帮助信息列出全部SQL命令和SQL*Plus命令SQL>help列出某个特定的命令的信息SQL>help 命令名c、显示表结构命令DESCRIBESQL>DESC 表名d、SQL*Plus中的编辑命令显示SQL缓冲…

网站linux支持php吗,thinkphp支持linux吗

准备工作&#xff1a;购买一个linux服务器地址&#xff1b;安装好linux常用的ssh工具(我这边喜欢用xshell敲命令&#xff0c;用filezilla传输文件&#xff0c;这些工具只要到官网下载就好&#xff0c;速度很快的)&#xff1b;1.安装phpstudy for linux安装下载phpstudy的方式千…

首页生成静态的html,关于网站生成静态html文件的两种方案思考

关于网站生成静态文件有利有弊&#xff0c;通常来讲交互性的站点不太适合静态化&#xff0c;如社交网站&#xff0c;论坛之类的站点等等。如果以资讯内容展示为主&#xff0c;生成静态文件能够很好的提高服务器吞吐量。下面提供两种生成静态文件的方案&#xff0c;分析下其中的…

什么叫基于web的网站_给Web前端初学者的一些建议和学习方法路线

很多时候跟着书和不系统的视频学习&#xff0c;会发现没有方向&#xff0c;学了很多却不知道自己能够做出什么成绩。学习要有一个清晰的职业学习规划&#xff0c;学习过程中会遇到很多问题&#xff0c;你可以到我们的web学习交流群-点击此处&#xff0c;同时准备了基础&#xf…

如何把小程序里面的图片扒下来_企业网站制作如何用CMS系统快速建站?

今天给大家分享一下如何利用CMS系统最快速度的模仿一个企业网站&#xff1f;这里着重点强调一下&#xff0c;是U快速模仿&#xff0c;不用什么专业基础就可以办到&#xff0c;只需要熟悉操作流程就可以。首先&#xff0c;来讲下大体的思路&#xff0c;确定站点&#xff0c;选择…

360 网站服务器漏洞扫描,360Webscan

360Webscan&#xff0c;云探安全监测系统是遵循360在总结多年市场经验和客户需求基础上提出的一款面向党政军、金融、教育和互联网用户的基于SaaS的网站应用安全监测服务产品&#xff0c;依赖于360安全大脑&#xff0c;以及360在搜索、终端 安全、网站安全等方面积累的数亿用户…

ps not a png file怎么解决_PS太难学不会?这16个图片处理网站你一定要收藏!

提到图片处理&#xff0c;很多人首先想到的一定是PS。不得不说PS对大部分职场人士来说还是有一定的技术壁垒的。不懂PS没关系&#xff0c;今天给大家分享的16个小网站或许能够帮到你。综合类网站IMG365http://www.img365.cn/该网站提供“图片压缩”、“图片格式转换”、“图片转…

php项目中自动搜索变量,迅睿CMS 自定义搜索seo变量{param}字符串

当搜索seo设置参数中包含了 {param} 标签时&#xff0c;会自动根据浏览器参数来组装网页的title字符串&#xff0c;比如在实际项目中需要变更内容时&#xff0c;比如把栏目名称去掉&#xff0c;那么可以重写content类完成操作1、新建或打开文件dayrui/App/Demo/Models/Content.…